doveadm-mail-fetch.c revision 2dbb7b30d9bf6d6b0cd104c6931c4b44a77c2383
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen/* Copyright (c) 2010-2016 Dovecot authors, see the included COPYING file */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen /* if print() returns -1, log this error if non-NULL. otherwise log
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen the storage error. */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int fetch_user(struct fetch_cmd_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_print(ctx->ctx.cur_mail_user->username);
ea546eaab672d441e180b7619d4750be813c08d8Timo Sirainenstatic int fetch_mailbox(struct fetch_cmd_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_MAILBOX_NAME, &value) < 0)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainenstatic int fetch_mailbox_guid(struct fetch_cmd_context *ctx)
31ddc75584c5cde53d2e78a737587f2e7fdcb0d2Timo Sirainen if (mailbox_get_metadata(ctx->mail->box, MAILBOX_METADATA_GUID,
0add8c99ca65e56dbf613595fc37c41aafff3f7fTimo Sirainen doveadm_print(guid_128_to_string(metadata.guid));
0add8c99ca65e56dbf613595fc37c41aafff3f7fTimo Sirainenstatic int fetch_seq(struct fetch_cmd_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int fetch_uid(struct fetch_cmd_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int fetch_guid(struct fetch_cmd_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_GUID, &value) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int fetch_flags(struct fetch_cmd_context *ctx)
93b29720c5141f787bd1861796867e4595c9d084Timo Sirainen imap_write_flags(str, mail_get_flags(ctx->mail),
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int fetch_modseq(struct fetch_cmd_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_print_num(mail_get_modseq(ctx->mail));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenfetch_set_istream_error(struct fetch_cmd_context *ctx, struct istream *input)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->print_error = t_strdup_printf("read(%s) failed: %s",
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_stream_get_name(input), i_stream_get_error(input));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int fetch_hdr(struct fetch_cmd_context *ctx)
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen if (mail_get_hdr_stream(ctx->mail, &hdr_size, &input) < 0)
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen input = i_stream_create_limit(input, hdr_size.physical_size);
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainenstatic int fetch_hdr_field(struct fetch_cmd_context *ctx)
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen const char *const *value, *filter, *name = ctx->cur_field->name;
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen if (filter != NULL && strcmp(filter, "utf8") == 0) {
bef8712387812fc5d9496b9958935c6d0c418777Timo Sirainen if (mail_get_headers_utf8(ctx->mail, name, &value) < 0)
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen if (mail_get_headers(ctx->mail, name, &value) < 0)
7c5b51bdf43a98e12c654ad437e0b258c5fffbc1Timo Sirainen if (filter == NULL || strcmp(filter, "utf8") == 0) {
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen /* print the header as-is */
b20fb5b1df9d604a7541f5118fc5b4b466d211efTimo Sirainen addr = message_address_parse(pool_datastack_create(),
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int fetch_body_field(struct fetch_cmd_context *ctx)
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainen i_unreached(); /* we already verified this was ok */
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (imap_msgpart_open(ctx->mail, msgpart, &result) < 0) {
b5ea11802f2bafbec06282a7b3b6704dc5fae584Timo Sirainen if ((ret = doveadm_print_istream(result.input)) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int fetch_body(struct fetch_cmd_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_get_stream(ctx->mail, &hdr_size, NULL, &input) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int fetch_body_snippet(struct fetch_cmd_context *ctx)
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_BODY_SNIPPET, &value) < 0)
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainen /* [0] contains the snippet algorithm, skip over it */
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainenstatic int fetch_text(struct fetch_cmd_context *ctx)
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen if (mail_get_stream(ctx->mail, NULL, NULL, &input) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int fetch_text_utf8(struct fetch_cmd_context *ctx)
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen if (mail_get_stream(ctx->mail, NULL, NULL, &input) < 0)
8e7da21696c9f8a6d5e601243fb6172ec85d47b2Timo Sirainen parser = message_parser_init(pool_datastack_create(), input,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while ((ret = message_parser_parse_next_block(parser, &raw_block)) > 0) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (!message_decoder_decode_next_block(decoder, &raw_block,
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_error("read(%s) failed: %s", i_stream_get_name(input),
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int fetch_size_physical(struct fetch_cmd_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_get_physical_size(ctx->mail, &size) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int fetch_size_virtual(struct fetch_cmd_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_get_virtual_size(ctx->mail, &size) < 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int fetch_date_received(struct fetch_cmd_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen if (mail_get_received_date(ctx->mail, &t) < 0)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainenstatic int fetch_date_sent(struct fetch_cmd_context *ctx)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen doveadm_print(t_strdup_printf("%s (%c%02u%02u)", unixdate2str(t),
7e94cf9d70ce9fdeccb7a85ff400b899e6386f36Timo Sirainenstatic int fetch_date_saved(struct fetch_cmd_context *ctx)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic int fetch_date_received_unixtime(struct fetch_cmd_context *ctx)
7797aa2479e99aeb71057b7a2584b2cb72e4d3f8Timo Sirainen if (mail_get_received_date(ctx->mail, &t) < 0)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic int fetch_date_sent_unixtime(struct fetch_cmd_context *ctx)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic int fetch_date_saved_unixtime(struct fetch_cmd_context *ctx)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic int fetch_imap_envelope(struct fetch_cmd_context *ctx)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_IMAP_ENVELOPE, &value) < 0)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic int fetch_imap_body(struct fetch_cmd_context *ctx)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_IMAP_BODY, &value) < 0)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainenstatic int fetch_imap_bodystructure(struct fetch_cmd_context *ctx)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_IMAP_BODYSTRUCTURE, &value) < 0)
df4018ae2f0a95be602f724ca70df7e0e3bd6a7dTimo Sirainenstatic int fetch_pop3_uidl(struct fetch_cmd_context *ctx)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_UIDL_BACKEND, &value) < 0)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainenstatic int fetch_pop3_order(struct fetch_cmd_context *ctx)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_POP3_ORDER, &value) < 0)
5a07b37a9df398b5189c14872a600384208ab74bTimo Sirainenstatic int fetch_refcount(struct fetch_cmd_context *ctx)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_REFCOUNT, &value) < 0)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic int fetch_storageid(struct fetch_cmd_context *ctx)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_STORAGE_ID, &value) < 0)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic const struct fetch_field fetch_fields[] = {
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen { "hdr", MAIL_FETCH_STREAM_HEADER, fetch_hdr },
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen { "body", MAIL_FETCH_STREAM_BODY, fetch_body },
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen { "body.snippet", MAIL_FETCH_BODY_SNIPPET, fetch_body_snippet },
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen { "size.physical", MAIL_FETCH_PHYSICAL_SIZE, fetch_size_physical },
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen { "size.virtual", MAIL_FETCH_VIRTUAL_SIZE, fetch_size_virtual },
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen { "date.received", MAIL_FETCH_RECEIVED_DATE, fetch_date_received },
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen { "date.sent", MAIL_FETCH_DATE, fetch_date_sent },
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen { "date.saved", MAIL_FETCH_SAVE_DATE, fetch_date_saved },
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen { "date.received.unixtime", MAIL_FETCH_RECEIVED_DATE, fetch_date_received_unixtime },
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen { "date.sent.unixtime", MAIL_FETCH_DATE, fetch_date_sent_unixtime },
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen { "date.saved.unixtime", MAIL_FETCH_SAVE_DATE, fetch_date_saved_unixtime },
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen { "imap.envelope", MAIL_FETCH_IMAP_ENVELOPE, fetch_imap_envelope },
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen { "imap.body", MAIL_FETCH_IMAP_BODY, fetch_imap_body },
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen { "imap.bodystructure", MAIL_FETCH_IMAP_BODYSTRUCTURE, fetch_imap_bodystructure },
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen { "pop3.uidl", MAIL_FETCH_UIDL_BACKEND, fetch_pop3_uidl },
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen { "pop3.order", MAIL_FETCH_POP3_ORDER, fetch_pop3_order },
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen { "refcount", MAIL_FETCH_REFCOUNT, fetch_refcount },
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen { "storageid", MAIL_FETCH_STORAGE_ID, fetch_storageid }
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainenstatic const struct fetch_field *fetch_field_find(const char *name)
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen unsigned int i;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen for (i = 0; i < N_ELEMENTS(fetch_fields); i++) {
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic void print_fetch_fields(void)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainen unsigned int i;
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen fprintf(stderr, "Available fetch fields: hdr.<name> body.<section> binary.<section> %s", fetch_fields[0].name);
bb10ebcf076c959c752f583746d83805d7686df8Timo Sirainen for (i = 1; i < N_ELEMENTS(fetch_fields); i++)
16c89b1260c9d07c01c83a9219424d3727069b2eTimo Sirainenstatic void parse_fetch_fields(struct fetch_cmd_context *ctx, const char *str)
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen if ((field = fetch_field_find(name)) != NULL) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen bool binary = strncmp(name, "binary.", 7) == 0;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen body_field.name = t_strarray_join(t_strsplit(name, ","), " ");
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ctx->wanted_fields |= imap_msgpart_get_fetch_data(msgpart);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainenstatic int cmd_fetch_mail(struct fetch_cmd_context *ctx)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_error("fetch(%s) failed for box=%s uid=%u: %s",
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen doveadm_mail_failed_mailbox(&ctx->ctx, mail->box);
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainencmd_fetch_box(struct fetch_cmd_context *ctx, const struct mailbox_info *info)
1b3bb8d39686ed24730cbc31cc9a33dc62c8c6c3Timo Sirainen if (doveadm_mail_iter_init(&ctx->ctx, info, ctx->ctx.search_args,
24fc71a693331ffe77e2b6d81c70aca6fa055e47Timo Sirainen while (doveadm_mail_iter_next(iter, &ctx->mail)) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainencmd_fetch_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
int ret = 0;
} T_END;
return ret;
const char *const args[])
DOVEADM_CMD_PARAM('\0', "fieldstr", CMD_PARAM_STR, CMD_PARAM_FLAG_POSITIONAL | CMD_PARAM_FLAG_DO_NOT_EXPOSE) /* FIXME: horrible hack, remove me when possible */