doveadm-mail-fetch.c revision 94ba4820927b906b333e39445c1508a29387c3aa
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen#include "lib.h"
def516ea503a60f20d510c14d5070b7ff5bbddf4Timo Sirainen#include "istream.h"
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen#include "ostream.h"
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen#include "base64.h"
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen#include "randgen.h"
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen#include "str.h"
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen#include "imap-quote.h"
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen#include "imap-parser.h"
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen#include "mail-storage.h"
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen#include "mail-search-build.h"
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen#include "doveadm-mail.h"
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
55a7410569737197afb302b07b488973324b0cc5Timo Sirainenstatic struct mail_search_args *search_args_from_str(const char *str)
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen{
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen struct istream *input;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen struct imap_parser *parser;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen const struct imap_arg *args;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen struct mail_search_args *sargs;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen const char *error;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen bool fatal;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen int ret;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen input = i_stream_create_from_data(str, strlen(str));
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen (void)i_stream_read(input);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen parser = imap_parser_create(input, NULL, (size_t)-1);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen ret = imap_parser_finish_line(parser, 0, 0, &args);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen if (ret < 0)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen i_fatal("%s", imap_parser_get_error(parser, &fatal));
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen if (mail_search_build_from_imap_args(mail_search_register_human,
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen args, "UTF-8", &sargs, &error) < 0)
63946971b08cfb1eec698c28569e1c4aa237852dTimo Sirainen i_fatal("%s", error);
63946971b08cfb1eec698c28569e1c4aa237852dTimo Sirainen
63946971b08cfb1eec698c28569e1c4aa237852dTimo Sirainen imap_parser_destroy(&parser);
63946971b08cfb1eec698c28569e1c4aa237852dTimo Sirainen i_stream_destroy(&input);
63946971b08cfb1eec698c28569e1c4aa237852dTimo Sirainen return sargs;
63946971b08cfb1eec698c28569e1c4aa237852dTimo Sirainen}
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainenstatic const char *params_to_imap_args_string(const char *const args[])
def516ea503a60f20d510c14d5070b7ff5bbddf4Timo Sirainen{
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen string_t *str;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen const char *p;
4525c4a8f8d1a6365e4469c0c8f46575400a9a67Timo Sirainen
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen str = t_str_new(256);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen for (; *args != NULL; args++) {
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen for (p = *args; *p != '\0'; p++) {
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen if (IS_ATOM_SPECIAL_INPUT(*p))
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen break;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen }
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen if (*p == '\0' ||
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen strcmp(*args, "(") == 0 ||
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen strcmp(*args, ")") == 0)
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen str_append(str, *args);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen else
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen imap_dquote_append(str, *args);
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen str_append_c(str, ' ');
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen }
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen return str_c(str);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen}
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen
def516ea503a60f20d510c14d5070b7ff5bbddf4Timo Sirainenvoid cmd_fetch(struct mail_user *user, const char *const args[])
def516ea503a60f20d510c14d5070b7ff5bbddf4Timo Sirainen{
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen const char *mailbox = args[0];
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen struct mail_storage *storage;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen struct mailbox *box;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen struct mail_search_args *search_args;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen struct mailbox_transaction_context *t;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen struct mail_search_context *search_ctx;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen struct mail *mail;
def516ea503a60f20d510c14d5070b7ff5bbddf4Timo Sirainen struct istream *input;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen struct ostream *output;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen string_t *prefix;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen unsigned char prefix_buf[9];
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen unsigned int prefix_len;
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen if (mailbox == NULL || args[1] == NULL)
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen doveadm_mail_help_name("fetch");
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen search_args = search_args_from_str(params_to_imap_args_string(args+1));
c0435c854a0e7246373b9752d163095cc4fbe985Timo Sirainen
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen random_fill_weak(prefix_buf, sizeof(prefix_buf));
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen prefix = t_str_new(32);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen str_append(prefix, "===");
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen base64_encode(prefix_buf, sizeof(prefix_buf), prefix);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen str_append_c(prefix, ' ');
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen prefix_len = str_len(prefix);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen
9e0959adf671330f95ba941cff238ad5cd408fe1Timo Sirainen output = o_stream_create_fd(STDOUT_FILENO, 0, FALSE);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen box = doveadm_mailbox_find_and_sync(user, mailbox);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen storage = mailbox_get_storage(box);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen t = mailbox_transaction_begin(box, 0);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen search_ctx = mailbox_search_init(t, search_args, NULL);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen mail = mail_alloc(t, 0, NULL);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen while (mailbox_search_next(search_ctx, mail)) {
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen if (mail_get_stream(mail, NULL, NULL, &input) < 0) {
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen i_error("Couldn't open mail uid=%u: %s", mail->uid,
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen mail_storage_get_last_error(storage, NULL));
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen continue;
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen }
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen
4525c4a8f8d1a6365e4469c0c8f46575400a9a67Timo Sirainen str_truncate(prefix, prefix_len);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen str_printfa(prefix, "seq=%u uid=%u\n", mail->seq, mail->uid);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen if (o_stream_send(output, str_data(prefix), str_len(prefix)) < 0)
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen i_fatal("write(stdout) failed: %m");
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen while (!i_stream_is_eof(input)) {
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen if (o_stream_send_istream(output, input) <= 0)
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen i_fatal("write(stdout) failed: %m");
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen }
fd4632d0060b2e9eef513b544ccff1e26d1fc222Timo Sirainen }
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen mail_free(&mail);
4525c4a8f8d1a6365e4469c0c8f46575400a9a67Timo Sirainen if (mailbox_search_deinit(&search_ctx) < 0) {
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen i_fatal("Search failed: %s",
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen mail_storage_get_last_error(storage, NULL));
fd4632d0060b2e9eef513b544ccff1e26d1fc222Timo Sirainen }
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen (void)mailbox_transaction_commit(&t);
5ce2084ada06ade9f44fc2914c34658e9a842dc1Timo Sirainen mailbox_free(&box);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen o_stream_unref(&output);
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen}
55a7410569737197afb302b07b488973324b0cc5Timo Sirainen