From: Timo Sirainen Date: Tue, 13 Apr 2010 17:54:46 +0000 (+0300) Subject: doveadm: Added initial code for fetch command. X-Git-Tag: 2.0.beta5~127 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=94ba4820927b906b333e39445c1508a29387c3aa;p=thirdparty%2Fdovecot%2Fcore.git doveadm: Added initial code for fetch command. --HG-- branch : HEAD --- diff --git a/src/doveadm/Makefile.am b/src/doveadm/Makefile.am index e1912dc4fb..546e73f595 100644 --- a/src/doveadm/Makefile.am +++ b/src/doveadm/Makefile.am @@ -51,6 +51,7 @@ doveadm_SOURCES = \ doveadm-dump-thread.c \ doveadm-kick.c \ doveadm-mail.c \ + doveadm-mail-fetch.c \ doveadm-penalty.c \ doveadm-pw.c \ doveadm-settings.c \ diff --git a/src/doveadm/doveadm-mail-fetch.c b/src/doveadm/doveadm-mail-fetch.c new file mode 100644 index 0000000000..ad099c3aad --- /dev/null +++ b/src/doveadm/doveadm-mail-fetch.c @@ -0,0 +1,121 @@ +/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */ + +#include "lib.h" +#include "istream.h" +#include "ostream.h" +#include "base64.h" +#include "randgen.h" +#include "str.h" +#include "imap-quote.h" +#include "imap-parser.h" +#include "mail-storage.h" +#include "mail-search-build.h" +#include "doveadm-mail.h" + +static struct mail_search_args *search_args_from_str(const char *str) +{ + struct istream *input; + struct imap_parser *parser; + const struct imap_arg *args; + struct mail_search_args *sargs; + const char *error; + bool fatal; + int ret; + + input = i_stream_create_from_data(str, strlen(str)); + (void)i_stream_read(input); + + parser = imap_parser_create(input, NULL, (size_t)-1); + ret = imap_parser_finish_line(parser, 0, 0, &args); + if (ret < 0) + i_fatal("%s", imap_parser_get_error(parser, &fatal)); + if (mail_search_build_from_imap_args(mail_search_register_human, + args, "UTF-8", &sargs, &error) < 0) + i_fatal("%s", error); + + imap_parser_destroy(&parser); + i_stream_destroy(&input); + return sargs; +} + +static const char *params_to_imap_args_string(const char *const args[]) +{ + string_t *str; + const char *p; + + str = t_str_new(256); + for (; *args != NULL; args++) { + for (p = *args; *p != '\0'; p++) { + if (IS_ATOM_SPECIAL_INPUT(*p)) + break; + } + if (*p == '\0' || + strcmp(*args, "(") == 0 || + strcmp(*args, ")") == 0) + str_append(str, *args); + else + imap_dquote_append(str, *args); + str_append_c(str, ' '); + } + return str_c(str); +} + +void cmd_fetch(struct mail_user *user, const char *const args[]) +{ + const char *mailbox = args[0]; + struct mail_storage *storage; + struct mailbox *box; + struct mail_search_args *search_args; + struct mailbox_transaction_context *t; + struct mail_search_context *search_ctx; + struct mail *mail; + struct istream *input; + struct ostream *output; + string_t *prefix; + unsigned char prefix_buf[9]; + unsigned int prefix_len; + + if (mailbox == NULL || args[1] == NULL) + doveadm_mail_help_name("fetch"); + search_args = search_args_from_str(params_to_imap_args_string(args+1)); + + random_fill_weak(prefix_buf, sizeof(prefix_buf)); + prefix = t_str_new(32); + str_append(prefix, "==="); + base64_encode(prefix_buf, sizeof(prefix_buf), prefix); + str_append_c(prefix, ' '); + prefix_len = str_len(prefix); + + output = o_stream_create_fd(STDOUT_FILENO, 0, FALSE); + box = doveadm_mailbox_find_and_sync(user, mailbox); + storage = mailbox_get_storage(box); + + t = mailbox_transaction_begin(box, 0); + search_ctx = mailbox_search_init(t, search_args, NULL); + mail = mail_alloc(t, 0, NULL); + while (mailbox_search_next(search_ctx, mail)) { + if (mail_get_stream(mail, NULL, NULL, &input) < 0) { + i_error("Couldn't open mail uid=%u: %s", mail->uid, + mail_storage_get_last_error(storage, NULL)); + continue; + } + + str_truncate(prefix, prefix_len); + str_printfa(prefix, "seq=%u uid=%u\n", mail->seq, mail->uid); + if (o_stream_send(output, str_data(prefix), str_len(prefix)) < 0) + i_fatal("write(stdout) failed: %m"); + + while (!i_stream_is_eof(input)) { + if (o_stream_send_istream(output, input) <= 0) + i_fatal("write(stdout) failed: %m"); + } + } + mail_free(&mail); + if (mailbox_search_deinit(&search_ctx) < 0) { + i_fatal("Search failed: %s", + mail_storage_get_last_error(storage, NULL)); + } + (void)mailbox_transaction_commit(&t); + mailbox_free(&box); + o_stream_unref(&output); +} diff --git a/src/doveadm/doveadm-mail.c b/src/doveadm/doveadm-mail.c index d7e2c657a0..368f5e1998 100644 --- a/src/doveadm/doveadm-mail.c +++ b/src/doveadm/doveadm-mail.c @@ -59,6 +59,20 @@ mailbox_find_and_open(struct mail_user *user, const char *mailbox) return box; } +struct mailbox * +doveadm_mailbox_find_and_sync(struct mail_user *user, const char *mailbox) +{ + struct mailbox *box; + + box = mailbox_find_and_open(user, mailbox); + if (mailbox_sync(box, MAILBOX_SYNC_FLAG_FULL_READ) < 0) { + i_fatal("Syncing mailbox %s failed: %s", mailbox, + mail_storage_get_last_error(mailbox_get_storage(box), + NULL)); + } + return box; +} + static void cmd_force_resync(struct mail_user *user, const char *const args[]) { const char *mailbox = args[0]; @@ -297,7 +311,8 @@ void doveadm_mail_help_name(const char *cmd_name) static struct doveadm_mail_cmd mail_commands[] = { { cmd_purge, "purge", NULL }, - { cmd_force_resync, "force-resync", "" } + { cmd_force_resync, "force-resync", "" }, + { cmd_fetch, "fetch", " " } }; void doveadm_mail_init(void) diff --git a/src/doveadm/doveadm-mail.h b/src/doveadm/doveadm-mail.h index ba0378b8af..a3a5983894 100644 --- a/src/doveadm/doveadm-mail.h +++ b/src/doveadm/doveadm-mail.h @@ -25,4 +25,9 @@ void doveadm_mail_help_name(const char *cmd_name) ATTR_NORETURN; void doveadm_mail_init(void); void doveadm_mail_deinit(void); +struct mailbox * +doveadm_mailbox_find_and_sync(struct mail_user *user, const char *mailbox); + +void cmd_fetch(struct mail_user *user, const char *const args[]); + #endif