dovecot-2.0: doveadm: Added import command for importing mails f...

dovecot at dovecot.org dovecot at dovecot.org
Mon Oct 18 20:30:45 EEST 2010


details:   http://hg.dovecot.org/dovecot-2.0/rev/6c2d5ed0b664
changeset: 12304:6c2d5ed0b664
user:      Timo Sirainen <tss at iki.fi>
date:      Mon Oct 18 18:30:42 2010 +0100
description:
doveadm: Added import command for importing mails from other storages.

diffstat:

 .hgignore                         |    2 +-
 doc/man/Makefile.am               |    6 +
 doc/man/doveadm-import.1.in       |   81 ++++++++++++++++
 src/doveadm/Makefile.am           |    1 +
 src/doveadm/doveadm-mail-import.c |  198 +++++++++++++++++++++++++++++++++++++++
 src/doveadm/doveadm-mail.c        |    1 +
 src/doveadm/doveadm-mail.h        |    1 +
 7 files changed, 289 insertions(+), 1 deletions(-)

diffs (truncated from 360 to 300 lines):

diff -r 507d4c4859cf -r 6c2d5ed0b664 .hgignore
--- a/.hgignore	Mon Oct 18 18:30:02 2010 +0100
+++ b/.hgignore	Mon Oct 18 18:30:42 2010 +0100
@@ -94,5 +94,5 @@
 
 syntax: regexp
 src/.*/test-[^\.]*$
-doc/man/doveadm-(altmove|auth|director|dump|expunge|fetch|force-resync|help|kick|log|mailbox|penalty|purge|pw|quota|search|user|who)\.1$
+doc/man/doveadm-(altmove|auth|director|dump|expunge|fetch|import|force-resync|help|kick|log|mailbox|penalty|purge|pw|quota|search|user|who)\.1$
 doc/man/(doveadm|doveconf|dovecot-lda|dovecot|dsync)\.1$
diff -r 507d4c4859cf -r 6c2d5ed0b664 doc/man/Makefile.am
--- a/doc/man/Makefile.am	Mon Oct 18 18:30:02 2010 +0100
+++ b/doc/man/Makefile.am	Mon Oct 18 18:30:42 2010 +0100
@@ -17,6 +17,7 @@
 	doveadm-dump.1 \
 	doveadm-expunge.1 \
 	doveadm-fetch.1 \
+	doveadm-import.1 \
 	doveadm-force-resync.1 \
 	doveadm-help.1 \
 	doveadm-kick.1 \
@@ -49,6 +50,7 @@
 	doveadm-dump.1.in \
 	doveadm-expunge.1.in \
 	doveadm-fetch.1.in \
+	doveadm-import.1.in \
 	doveadm-force-resync.1.in \
 	doveadm-help.1.in \
 	doveadm-kick.1.in \
@@ -98,6 +100,10 @@
 	$(SHELL) $(srcdir)/sed.sh $(srcdir) $(rundir) $(pkgsysconfdir) \
 		< $(srcdir)/doveadm-fetch.1.in > doveadm-fetch.1
 
+doveadm-import.1: $(srcdir)/doveadm-import.1.in $(man_includefiles) Makefile
+	$(SHELL) $(srcdir)/sed.sh $(srcdir) $(rundir) $(pkgsysconfdir) \
+		< $(srcdir)/doveadm-import.1.in > doveadm-import.1
+
 doveadm-force-resync.1: $(srcdir)/doveadm-force-resync.1.in $(man_includefiles) Makefile
 	$(SHELL) $(srcdir)/sed.sh $(srcdir) $(rundir) $(pkgsysconfdir) \
 		< $(srcdir)/doveadm-force-resync.1.in > doveadm-force-resync.1
diff -r 507d4c4859cf -r 6c2d5ed0b664 doc/man/doveadm-import.1.in
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/doc/man/doveadm-import.1.in	Mon Oct 18 18:30:42 2010 +0100
@@ -0,0 +1,81 @@
+.\" Copyright (c) 2010 Dovecot authors, see the included COPYING file
+.TH DOVEADM\-IMPORT 1 "2010-10-18" "Dovecot v2.0" "Dovecot"
+.SH NAME
+doveadm\-import \- Import messages matching given search query
+.\"------------------------------------------------------------------------
+.SH SYNOPSIS
+.BR doveadm " [" \-Dv "] " import
+.I source_location dest_parent search_query
+.br
+.\"-------------------------------------
+.BR doveadm " [" \-Dv "] " "import \-A"
+.I source_location dest_parent search_query
+.br
+.\"-------------------------------------
+.BR doveadm " [" \-Dv "] " "import \-u"
+.I user source_location dest_parent search_query
+.\"------------------------------------------------------------------------
+.SH DESCRIPTION
+This command can be used to import mails from another mail storage specified by
+.I source_location
+to one or more user\(aqs mailboxes. All the mailboxes are imported under the
+given
+.I dest_parent
+mailbox. The
+.I search_query
+can be used to restrict which mailboxes or messages are imported.
+
+In the first form,
+.BR doveadm (1)
+will executed the
+.B import
+action with the environment of the logged in system user.
+.PP
+In the second form, the mails will be imported for all users.
+.PP
+In the third form, the mails will be imported only for given
+.IR user (s)
+.\"------------------------------------------------------------------------
+ at INCLUDE:global-options@
+.\" --- command specific options --- "/.
+.PP
+Command specific
+.IR options :
+.\"-------------------------------------
+ at INCLUDE:option-A@
+.\"-------------------------------------
+ at INCLUDE:option-u-user@
+.\"------------------------------------------------------------------------
+.SH ARGUMENTS
+.TP
+.I search_query
+Copy messages matching this search query.
+See
+.BR doveadm\-search\-query (7)
+for details.
+.\"------------------------------------------------------------------------
+.SH EXAMPLE
+This example imports all mails from a backup under a
+.I backup-20101026
+mailbox:
+.PP
+.nf
+.B doveadm import \-u jane.doe at example.org \(rs
+.B mdbox:/backup/20101026/jane.doe/mdbox backup-20101026 all
+.fi
+.PP
+Another example that imports only messages from foo at example.org in the
+backup mdbox\(aqs INBOX to jane\(aqs INBOX:
+.PP
+.nf
+.B doveadm import \-u jane.doe at example.org \(rs
+.B mdbox:~/mdbox-backup "" mailbox INBOX from foo at example.org
+.fi
+.\"------------------------------------------------------------------------
+ at INCLUDE:reporting-bugs@
+.\"------------------------------------------------------------------------
+.SH SEE ALSO
+.BR doveadm (1),
+.BR doveadm\-fetch (1),
+.BR doveadm\-search (1),
+.BR doveadm\-search\-query (7)
diff -r 507d4c4859cf -r 6c2d5ed0b664 src/doveadm/Makefile.am
--- a/src/doveadm/Makefile.am	Mon Oct 18 18:30:02 2010 +0100
+++ b/src/doveadm/Makefile.am	Mon Oct 18 18:30:42 2010 +0100
@@ -61,6 +61,7 @@
 	doveadm-mail-altmove.c \
 	doveadm-mail-expunge.c \
 	doveadm-mail-fetch.c \
+	doveadm-mail-import.c \
 	doveadm-mail-iter.c \
 	doveadm-mail-mailbox.c \
 	doveadm-mail-mailbox-status.c \
diff -r 507d4c4859cf -r 6c2d5ed0b664 src/doveadm/doveadm-mail-import.c
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/doveadm/doveadm-mail-import.c	Mon Oct 18 18:30:42 2010 +0100
@@ -0,0 +1,198 @@
+/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
+
+#include "lib.h"
+#include "array.h"
+#include "mail-storage.h"
+#include "mail-storage-service.h"
+#include "mail-namespace.h"
+#include "doveadm-mail-list-iter.h"
+#include "doveadm-mail-iter.h"
+#include "doveadm-mail.h"
+
+struct import_cmd_context {
+	struct doveadm_mail_cmd_context ctx;
+
+	struct mail_user *src_user;
+	const char *dest_parent;
+};
+
+static int
+dest_mailbox_open_or_create(struct import_cmd_context *ctx,
+			    struct mail_user *user, const char *name,
+			    struct mailbox **box_r)
+{
+	struct mail_namespace *ns;
+	struct mailbox *box;
+	enum mail_error error;
+	const char *errstr, *storage_name;
+
+	if (*ctx->dest_parent != '\0') {
+		/* prefix destination mailbox name with given parent mailbox */
+		storage_name = ctx->dest_parent;
+		ns = mail_namespace_find(user->namespaces, &storage_name);
+		if (ns == NULL) {
+			i_error("Can't find namespace for parent mailbox %s",
+				ctx->dest_parent);
+			return -1;
+		}
+		name = t_strdup_printf("%s%c%s", ctx->dest_parent,
+				       ns->sep, name);
+	}
+
+	storage_name = name;
+	ns = mail_namespace_find(user->namespaces, &storage_name);
+	if (ns == NULL) {
+		i_error("Can't find namespace for mailbox %s", name);
+		return -1;
+	}
+
+	box = mailbox_alloc(ns->list, storage_name, MAILBOX_FLAG_SAVEONLY |
+			    MAILBOX_FLAG_KEEP_RECENT);
+	if (mailbox_create(box, NULL, FALSE) < 0) {
+		errstr = mail_storage_get_last_error(mailbox_get_storage(box),
+						     &error);
+		if (error != MAIL_ERROR_EXISTS) {
+			i_error("Couldn't create mailbox %s: %s", name, errstr);
+			mailbox_free(&box);
+			return -1;
+		}
+	}
+	if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) {
+		i_error("Syncing mailbox %s failed: %s", name,
+			mail_storage_get_last_error(mailbox_get_storage(box),
+						    NULL));
+		mailbox_free(&box);
+		return -1;
+	}
+	*box_r = box;
+	return 0;
+}
+
+static int
+cmd_import_box_contents(struct doveadm_mail_iter *iter, struct mail *src_mail,
+			struct mailbox *dest_box)
+{
+	struct mail_storage *dest_storage = mailbox_get_storage(dest_box);
+	struct mail_save_context *save_ctx;
+	struct mailbox_transaction_context *dest_trans;
+	const char *mailbox = mailbox_get_vname(dest_box);
+	int ret;
+
+	dest_trans = mailbox_transaction_begin(dest_box,
+				MAILBOX_TRANSACTION_FLAG_EXTERNAL);
+	do {
+		if (doveadm_debug) {
+			i_debug("import: box=%s uid=%u",
+				mailbox, src_mail->uid);
+		}
+		save_ctx = mailbox_save_alloc(dest_trans);
+		if (mailbox_copy(&save_ctx, src_mail) < 0) {
+			i_error("Copying box=%s uid=%u failed: %s",
+				mailbox, src_mail->uid,
+				mail_storage_get_last_error(dest_storage, NULL));
+			ret = -1;
+		}
+	} while (doveadm_mail_iter_next(iter, src_mail));
+
+	if (mailbox_transaction_commit(&dest_trans) < 0) {
+		i_error("Committing copied mails to %s failed: %s", mailbox,
+			mail_storage_get_last_error(dest_storage, NULL));
+		ret = -1;
+	}
+	return ret;
+}
+
+static int
+cmd_import_box(struct import_cmd_context *ctx, struct mail_user *dest_user,
+	       const struct mailbox_info *info,
+	       struct mail_search_args *search_args)
+{
+	struct doveadm_mail_iter *iter;
+	struct mailbox_transaction_context *trans;
+	struct mailbox *box;
+	struct mail *mail;
+	int ret = 0;
+
+	if (doveadm_mail_iter_init(info, search_args, &trans, &iter) < 0)
+		return -1;
+
+	mail = mail_alloc(trans, 0, NULL);
+	if (doveadm_mail_iter_next(iter, mail)) {
+		/* at least one mail matches in this mailbox */
+		if (dest_mailbox_open_or_create(ctx, dest_user, info->name,
+						&box) == 0) {
+			if (cmd_import_box_contents(iter, mail, box) < 0)
+				ret = -1;
+			mailbox_free(&box);
+		}
+	}
+	mail_free(&mail);
+	if (doveadm_mail_iter_deinit_sync(&iter) < 0)
+		ret = -1;
+	return ret;
+}
+
+static void
+cmd_import_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
+{
+	struct import_cmd_context *ctx = (struct import_cmd_context *)_ctx;
+	const enum mailbox_list_iter_flags iter_flags =
+		MAILBOX_LIST_ITER_RAW_LIST |
+		MAILBOX_LIST_ITER_NO_AUTO_INBOX |
+		MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
+	struct doveadm_mail_list_iter *iter;
+	const struct mailbox_info *info;
+
+	iter = doveadm_mail_list_iter_init(ctx->src_user,
+					   _ctx->search_args, iter_flags);
+	while ((info = doveadm_mail_list_iter_next(iter)) != NULL) T_BEGIN {
+		(void)cmd_import_box(ctx, user, info, _ctx->search_args);
+	} T_END;
+	doveadm_mail_list_iter_deinit(&iter);
+}
+
+static void cmd_import_init(struct doveadm_mail_cmd_context *_ctx,
+			    const char *const args[])
+{
+	struct import_cmd_context *ctx = (struct import_cmd_context *)_ctx;
+	struct mail_storage_service_input input;
+	struct mail_storage_service_user *service_user;
+	struct mail_user *user;


More information about the dovecot-cvs mailing list