doveadm-mail-fetch.c revision c154a05c76d4d83de1cdf9746ce4e2da0869705d
5f5870385cff47efd2f58e7892f251cf13761528Timo Sirainen/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "lib.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "array.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include "istream.h"
472369cba85d9f7c995dda60e7cd01d78b4a960aTimo Sirainen#include "ostream.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "str.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "message-size.h"
bd4e36a8cd7257cca7d1434c49a1e343ed7c5100Timo Sirainen#include "imap-utf7.h"
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen#include "imap-util.h"
b1f37113a5760bee842c5a7678bb5fa6f5bd8b60Timo Sirainen#include "mail-user.h"
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen#include "mail-storage.h"
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen#include "mail-search.h"
e28fa207d1a097fa6e4a867f74ee0761472ef1ceTimo Sirainen#include "mail-namespace.h"
37847ec8eaec9ad55c9df10ae109efe7b37ac573Timo Sirainen#include "doveadm-print.h"
ef50336eefcb9ba99f73c6af37420eaf8857a39bTimo Sirainen#include "doveadm-mail.h"
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen#include "doveadm-mail-list-iter.h"
13d98ffa534f2e7d04a832c9d0153fc9c568b878Timo Sirainen#include "doveadm-mail-iter.h"
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen#include <stdio.h>
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenstruct fetch_cmd_context {
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen struct doveadm_mail_cmd_context ctx;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
5694eeb99b69dea8033ca77ad69743c6b4871370Timo Sirainen struct ostream *output;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen struct mail *mail;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ARRAY_DEFINE(fields, const struct fetch_field);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen ARRAY_TYPE(const_string) header_fields;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen enum mail_fetch_field wanted_fields;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const struct fetch_field *cur_field;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen bool print_field_prefix;
8e371a3ce32bd64288786855b8ce0cb63f19f7d1Timo Sirainen};
220e21750948941dc6e33b8f11b552fa21d7f81eTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstruct fetch_field {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *name;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen enum mail_fetch_field wanted_fields;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen int (*print)(struct fetch_cmd_context *ctx);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen};
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenstatic int fetch_user(struct fetch_cmd_context *ctx)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen doveadm_print(ctx->ctx.cur_mail_user->username);
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen return 0;
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen}
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int fetch_mailbox(struct fetch_cmd_context *ctx)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen const char *value;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen string_t *str = t_str_new(128);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_MAILBOX_NAME, &value) < 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen if (imap_utf7_to_utf8(value, str) == 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen doveadm_print(str_c(str));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen else {
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen /* not a valid mUTF-7 name, fallback to showing it as-is */
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen doveadm_print(value);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen }
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainenstatic int fetch_mailbox_guid(struct fetch_cmd_context *ctx)
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen{
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen uint8_t guid[MAIL_GUID_128_SIZE];
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen
8a0ad174adb1eb5108511b90e97f4e5f9089b0eeTimo Sirainen if (mailbox_get_guid(ctx->mail->box, guid) < 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen doveadm_print(mail_guid_128_to_string(guid));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int fetch_seq(struct fetch_cmd_context *ctx)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen doveadm_print_num(ctx->mail->seq);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int fetch_uid(struct fetch_cmd_context *ctx)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen{
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen doveadm_print_num(ctx->mail->seq);
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenstatic int fetch_guid(struct fetch_cmd_context *ctx)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen{
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen const char *value;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_GUID, &value) < 0)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return -1;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen doveadm_print(value);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return 0;
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen}
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainenstatic int fetch_flags(struct fetch_cmd_context *ctx)
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen string_t *str = t_str_new(64);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen imap_write_flags(str, mail_get_flags(ctx->mail),
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen mail_get_keywords(ctx->mail));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen doveadm_print(str_c(str));
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen}
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainenstatic int fetch_hdr(struct fetch_cmd_context *ctx)
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen{
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen struct istream *input;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct message_size hdr_size;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const unsigned char *data;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen size_t size;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen int ret = 0;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (mail_get_stream(ctx->mail, &hdr_size, NULL, &input) < 0)
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen return -1;
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen
a27e065f1a1f91c7fbdf7c2ea1c387441af0cbb3Timo Sirainen input = i_stream_create_limit(input, hdr_size.physical_size);
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen while (!i_stream_is_eof(input)) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (i_stream_read_data(input, &data, &size, 0) == -1)
63e207529879438e9f4412d97cdc34bdc82a3702Timo Sirainen break;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (size == 0)
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen break;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen doveadm_print_stream(data, size);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen i_stream_skip(input, size);
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen if (input->stream_errno != 0) {
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen i_error("read() failed: %m");
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen ret = -1;
2649b237dd4690575e75a30b2bf3b39ebd37b835Timo Sirainen }
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen i_stream_unref(&input);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen doveadm_print_stream(NULL, 0);
a24519c36d5f8fa22f58b2c693ba547e8d175a54Timo Sirainen return ret;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int fetch_hdr_field(struct fetch_cmd_context *ctx)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const char *const *value;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen string_t *str = t_str_new(256);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen bool add_lf = FALSE;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (mail_get_headers(ctx->mail, ctx->cur_field->name, &value) < 0)
3fe67ec75ccae1230bb9eb9f16affc48377f6441Timo Sirainen return -1;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen for (; *value != NULL; value++) {
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen if (add_lf)
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen str_append_c(str, '\n');
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen str_append(str, *value);
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen add_lf = TRUE;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen }
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen doveadm_print(str_c(str));
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen return 0;
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen}
2a6dcd984104fed84bed8795ccdfabb20e41ce52Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int fetch_body(struct fetch_cmd_context *ctx)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen{
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct istream *input;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen struct message_size hdr_size;
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen const unsigned char *data;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen size_t size;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen int ret = 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
27586e4785d56aeb76e1fd96af8db799688dc64aTimo Sirainen if (mail_get_stream(ctx->mail, &hdr_size, NULL, &input) < 0)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return -1;
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_stream_skip(input, hdr_size.physical_size);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen while (!i_stream_is_eof(input)) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (i_stream_read_data(input, &data, &size, 0) == -1)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen break;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (size == 0)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen break;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen doveadm_print_stream(data, size);
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_stream_skip(input, size);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen }
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (input->stream_errno != 0) {
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen i_error("read() failed: %m");
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen ret = -1;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk }
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk doveadm_print_stream(NULL, 0);
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk return ret;
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk}
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volk
e5acc283bf030b0b5c79ca4e52d315c516a299faPascal Volkstatic int fetch_text(struct fetch_cmd_context *ctx)
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen{
7920a47321690c932ffd4d286cd16b4048d22d41Timo Sirainen struct istream *input;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen const unsigned char *data;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen size_t size;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen int ret = 0;
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen
db8b0a3f74a20528d66a3c4be7df920e5c4554c2Timo Sirainen if (mail_get_stream(ctx->mail, NULL, NULL, &input) < 0)
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen return -1;
5666a3d6a7ea89362b8d9e8b39b15424cd9d6388Timo Sirainen
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen while (!i_stream_is_eof(input)) {
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen if (i_stream_read_data(input, &data, &size, 0) == -1)
1701e3f91107051b1704721bf1dc1e32491faaf9Timo Sirainen break;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (size == 0)
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen break;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen doveadm_print_stream(data, size);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen i_stream_skip(input, size);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (input->stream_errno != 0) {
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen i_error("read() failed: %m");
9abf5be0962538e1f6f5c73c838ff677341da0c9Timo Sirainen ret = -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen }
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen doveadm_print_stream(NULL, 0);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return ret;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen}
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainenstatic int fetch_size_physical(struct fetch_cmd_context *ctx)
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen{
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen uoff_t size;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen if (mail_get_physical_size(ctx->mail, &size) < 0)
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen doveadm_print_num(size);
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return 0;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen}
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainenstatic int fetch_size_virtual(struct fetch_cmd_context *ctx)
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen uoff_t size;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (mail_get_virtual_size(ctx->mail, &size) < 0)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return -1;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen doveadm_print_num(size);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return 0;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen}
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenstatic int fetch_date_received(struct fetch_cmd_context *ctx)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen{
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen time_t t;
5c597df6aa8d81de4053c6986fab7739f3b44b20Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (mail_get_received_date(ctx->mail, &t) < 0)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return -1;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen doveadm_print(unixdate2str(t));
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return 0;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen}
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainenstatic int fetch_date_sent(struct fetch_cmd_context *ctx)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen{
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen time_t t;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen int tz;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen char chr;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (mail_get_date(ctx->mail, &t, &tz) < 0)
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen return -1;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen chr = tz < 0 ? '-' : '+';
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen if (tz < 0) tz = -tz;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen doveadm_print(t_strdup_printf("%s (%c%02u%02u)", unixdate2str(t),
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen chr, tz/60, tz%60));
5214b67a7dabab87da74e04bb8b227f94b95bce4Timo Sirainen return 0;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen}
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainenstatic int fetch_date_saved(struct fetch_cmd_context *ctx)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen time_t t;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen if (mail_get_save_date(ctx->mail, &t) < 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen return -1;
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen doveadm_print(unixdate2str(t));
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen return 0;
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen}
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainenstatic int fetch_imap_envelope(struct fetch_cmd_context *ctx)
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen{
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen const char *value;
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen
c58c12049c883b281c088d47a2a7278c21c390e1Timo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_IMAP_ENVELOPE, &value) < 0)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return -1;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen doveadm_print(value);
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return 0;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen}
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainenstatic int fetch_imap_body(struct fetch_cmd_context *ctx)
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen{
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen const char *value;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_IMAP_BODY, &value) < 0)
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen return -1;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen doveadm_print(value);
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen return 0;
c1d19144dd7b1de6822df6ed1d10af0c9cb38840Timo Sirainen}
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic int fetch_imap_bodystructure(struct fetch_cmd_context *ctx)
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen{
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen const char *value;
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_IMAP_BODYSTRUCTURE, &value) < 0)
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen return -1;
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen doveadm_print(value);
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen return 0;
2615df45a8027948a474abe5e817b34b0499c171Timo Sirainen}
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic const struct fetch_field fetch_fields[] = {
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen { "user", 0, fetch_user },
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen { "mailbox", 0, fetch_mailbox },
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen { "mailbox-guid", 0, fetch_mailbox_guid },
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen { "seq", 0, fetch_seq },
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen { "uid", 0, fetch_uid },
5494a6bc149da8f02fd25c0434a9d612ac33f659Timo Sirainen { "guid", 0, fetch_guid },
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen { "flags", MAIL_FETCH_FLAGS, fetch_flags },
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen { "hdr", MAIL_FETCH_STREAM_HEADER, fetch_hdr },
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen { "body", MAIL_FETCH_STREAM_BODY, fetch_body },
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen { "text", MAIL_FETCH_STREAM_HEADER |
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen MAIL_FETCH_STREAM_BODY, fetch_text },
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen { "size.physical", MAIL_FETCH_PHYSICAL_SIZE, fetch_size_physical },
94b0ff77495c3ed14bdd4b5d7ae1eb37e8c9efb5Timo Sirainen { "size.virtual", MAIL_FETCH_VIRTUAL_SIZE, fetch_size_virtual },
02e61e13a8360a9d3ec92c5fa5ae60c0f0181b71Timo Sirainen { "date.received", MAIL_FETCH_RECEIVED_DATE, fetch_date_received },
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen { "date.sent", MAIL_FETCH_DATE, fetch_date_sent },
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen { "date.saved", MAIL_FETCH_SAVE_DATE, fetch_date_saved },
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen { "imap.envelope", MAIL_FETCH_IMAP_ENVELOPE, fetch_imap_envelope },
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen { "imap.body", MAIL_FETCH_IMAP_BODY, fetch_imap_body },
b365bd121cdc87f63e1dd47c5085a27091118e00Timo Sirainen { "imap.bodystructure", MAIL_FETCH_IMAP_BODYSTRUCTURE, fetch_imap_bodystructure }
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen};
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainen
adb6413686e52e00dded4932babcc08ff041876bTimo Sirainenstatic const struct fetch_field *fetch_field_find(const char *name)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen unsigned int i;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (i = 0; i < N_ELEMENTS(fetch_fields); i++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (strcmp(fetch_fields[i].name, name) == 0)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return &fetch_fields[i];
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen }
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen return NULL;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainenstatic void print_fetch_fields(void)
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen{
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen unsigned int i;
1433bf361ddb0bba8878c8ada5726d0284edad57Timo Sirainen
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen fprintf(stderr, "Available fetch fields: %s", fetch_fields[0].name);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (i = 1; i < N_ELEMENTS(fetch_fields); i++)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen fprintf(stderr, " %s", fetch_fields[i].name);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen fprintf(stderr, "\n");
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen}
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainenstatic void parse_fetch_fields(struct fetch_cmd_context *ctx, const char *str)
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen{
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen const char *const *fields, *name;
4a514fb20e04df397842cde11cc9ea92abfe9728Timo Sirainen const struct fetch_field *field;
94d8e51119003d2bc5a100c663f90141f297385dTimo Sirainen struct fetch_field hdr_field;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen memset(&hdr_field, 0, sizeof(hdr_field));
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen hdr_field.print = fetch_hdr_field;
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen t_array_init(&ctx->fields, 32);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen t_array_init(&ctx->header_fields, 32);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen fields = t_strsplit_spaces(str, " ");
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen for (; *fields != NULL; fields++) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen name = t_str_lcase(*fields);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen doveadm_print_header_simple(name);
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen if (strncmp(name, "hdr.", 4) == 0) {
0b4e1043e596bfb36d999dacbf1d4d63ee96d75fTimo Sirainen name += 4;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen hdr_field.name = name;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen array_append(&ctx->fields, &hdr_field, 1);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen array_append(&ctx->header_fields, &name, 1);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen } else {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen field = fetch_field_find(name);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (field == NULL) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen print_fetch_fields();
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_fatal("Unknown fetch field: %s", name);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen ctx->wanted_fields |= field->wanted_fields;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen array_append(&ctx->fields, field, 1);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen (void)array_append_space(&ctx->header_fields);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen ctx->print_field_prefix = array_count(&ctx->fields) > 1;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenstatic void cmd_fetch_mail(struct fetch_cmd_context *ctx)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen{
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen const struct fetch_field *field;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen struct mail *mail = ctx->mail;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen array_foreach(&ctx->fields, field) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen ctx->cur_field = field;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen if (field->print(ctx) < 0) {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen struct mail_storage *storage =
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen mailbox_get_storage(mail->box);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen i_error("fetch(%s) failed for box=%s uid=%u: %s",
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen field->name, mailbox_get_vname(mail->box),
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen mail->uid, mail_storage_get_last_error(storage, NULL));
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenstatic int
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainencmd_fetch_box(struct fetch_cmd_context *ctx, const struct mailbox_info *info)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen struct doveadm_mail_iter *iter;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen struct mailbox_transaction_context *trans;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct mail *mail;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct mailbox_header_lookup_ctx *headers = NULL;
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen if (doveadm_mail_iter_init(info, ctx->ctx.search_args,
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen &trans, &iter) < 0)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return -1;
494a5de15db3b2806ab31d5ecc3e1c306ae14d06Timo Sirainen
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen if (array_count(&ctx->header_fields) > 1) {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen headers = mailbox_header_lookup_init(
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen mailbox_transaction_get_mailbox(trans),
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen array_idx(&ctx->header_fields, 0));
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen }
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen mail = mail_alloc(trans, ctx->wanted_fields, headers);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (headers != NULL)
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen mailbox_header_lookup_unref(&headers);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen while (doveadm_mail_iter_next(iter, mail)) {
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen ctx->mail = mail;
08ed4ab71fd2a4e800d9025a736f0f46b771ea90Timo Sirainen T_BEGIN {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen cmd_fetch_mail(ctx);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen } T_END;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen ctx->mail = NULL;
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen }
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen mail_free(&mail);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen return doveadm_mail_iter_deinit(&iter);
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen}
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainen
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainenstatic void
1c1cecd3dfaf71b0c9499b044023e631841e88aaTimo Sirainencmd_fetch_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct fetch_cmd_context *ctx = (struct fetch_cmd_context *)_ctx;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const enum mailbox_list_iter_flags iter_flags =
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen MAILBOX_LIST_ITER_VIRTUAL_NAMES |
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen MAILBOX_LIST_ITER_NO_AUTO_INBOX |
0bd259973f98837cf0e41fdee3e2a578e51ad09eTimo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
0bd259973f98837cf0e41fdee3e2a578e51ad09eTimo Sirainen struct doveadm_mail_list_iter *iter;
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen const struct mailbox_info *info;
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen iter = doveadm_mail_list_iter_init(user, _ctx->search_args, iter_flags);
e4cb3bfcd42f1f2c9e676ece6f7f53803f5c6a16Timo Sirainen while ((info = doveadm_mail_list_iter_next(iter)) != NULL) T_BEGIN {
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen (void)cmd_fetch_box(ctx, info);
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen } T_END;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen doveadm_mail_list_iter_deinit(&iter);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenstatic void cmd_fetch_deinit(struct doveadm_mail_cmd_context *_ctx)
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct fetch_cmd_context *ctx = (struct fetch_cmd_context *)_ctx;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
636f017be100bce67d66fd3ae1544a47681efd33Timo Sirainen o_stream_unref(&ctx->output);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen}
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainenstatic void cmd_fetch_init(struct doveadm_mail_cmd_context *_ctx,
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *const args[])
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen{
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen struct fetch_cmd_context *ctx = (struct fetch_cmd_context *)_ctx;
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen const char *fetch_fields = args[0];
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen if (fetch_fields == NULL || args[1] == NULL)
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen doveadm_mail_help_name("fetch");
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen parse_fetch_fields(ctx, fetch_fields);
c0a87e5f3316a57e6f915882fa1951d0fbb74a61Timo Sirainen _ctx->search_args = doveadm_mail_build_search_args(args + 1);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen ctx->output = o_stream_create_fd(STDOUT_FILENO, 0, FALSE);
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_fetch_alloc(void)
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen{
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen struct fetch_cmd_context *ctx;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct fetch_cmd_context);
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen ctx->ctx.v.init = cmd_fetch_init;
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen ctx->ctx.v.run = cmd_fetch_run;
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen ctx->ctx.v.deinit = cmd_fetch_deinit;
8f70c97f7ab7b7e1683ed5cfcd96721a899c2520Timo Sirainen doveadm_print_init("pager");
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen return &ctx->ctx;
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen}
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainenstruct doveadm_mail_cmd cmd_fetch = {
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen cmd_fetch_alloc, "fetch", "<fields> <search query>"
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen};
dc5606fb66d30a659459446b6ca1a8b4f1146052Timo Sirainen