doveadm-mail-fetch.c revision 23878bd03d1de531e3261a25598beec621351910
76b43e4417bab52e913da39b5f5bc2a130d3f149Timo Sirainen/* Copyright (c) 2010 Dovecot authors, see the included COPYING file */
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen#include "lib.h"
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen#include "array.h"
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen#include "istream.h"
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen#include "ostream.h"
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen#include "base64.h"
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen#include "randgen.h"
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen#include "str.h"
1098fc409a45e7603701dc94635927a673bee0c1Timo Sirainen#include "message-size.h"
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen#include "imap-util.h"
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen#include "mail-storage.h"
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen#include "mail-search.h"
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen#include "doveadm-mail.h"
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen#include "doveadm-mail-list-iter.h"
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen#include "doveadm-mail-iter.h"
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen#include <stdio.h>
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainenstruct fetch_cmd_context {
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen struct doveadm_mail_cmd_context ctx;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen struct mail_search_args *search_args;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen struct ostream *output;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen struct mail *mail;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen ARRAY_DEFINE(fields, const struct fetch_field);
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen enum mail_fetch_field wanted_fields;
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen string_t *hdr;
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen const char *prefix;
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen bool print_field_prefix;
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen};
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainenstatic int fetch_mailbox(struct fetch_cmd_context *ctx)
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen{
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen const char *value;
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_MAILBOX_NAME, &value) < 0)
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen return -1;
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen str_append(ctx->hdr, value);
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen return 0;
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen}
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainenstatic int fetch_mailbox_guid(struct fetch_cmd_context *ctx)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen uint8_t guid[MAIL_GUID_128_SIZE];
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (mailbox_get_guid(ctx->mail->box, guid) < 0)
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen return -1;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen str_append(ctx->hdr, mail_guid_128_to_string(guid));
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return 0;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen}
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainenstatic int fetch_seq(struct fetch_cmd_context *ctx)
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen{
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen str_printfa(ctx->hdr, "%u", ctx->mail->seq);
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen return 0;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen}
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic int fetch_uid(struct fetch_cmd_context *ctx)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen str_printfa(ctx->hdr, "%u", ctx->mail->seq);
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen return 0;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic int fetch_guid(struct fetch_cmd_context *ctx)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen const char *value;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen if (mail_get_special(ctx->mail, MAIL_FETCH_GUID, &value) < 0)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return -1;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen str_append(ctx->hdr, value);
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return 0;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen}
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
1171f0abf442638bac1827bb24a0b6b8eb682a82Timo Sirainenstatic int fetch_flags(struct fetch_cmd_context *ctx)
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen imap_write_flags(ctx->hdr, mail_get_flags(ctx->mail),
dd4b5f14b71b01a84af942e720a2d6e5f15ee1a7Timo Sirainen mail_get_keywords(ctx->mail));
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return 0;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic void flush_hdr(struct fetch_cmd_context *ctx)
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen{
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen o_stream_send(ctx->output, str_data(ctx->hdr), str_len(ctx->hdr));
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen str_truncate(ctx->hdr, 0);
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen}
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainenstatic int fetch_hdr(struct fetch_cmd_context *ctx)
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen{
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen struct istream *input;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen struct message_size hdr_size;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen int ret = 0;
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (mail_get_stream(ctx->mail, &hdr_size, NULL, &input) < 0)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen return -1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen if (ctx->print_field_prefix)
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen str_append_c(ctx->hdr, '\n');
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen flush_hdr(ctx);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen input = i_stream_create_limit(input, hdr_size.physical_size);
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen while (!i_stream_is_eof(input)) {
6237f743bbaf74de5a2d2051672baed87023657bTimo Sirainen if (o_stream_send_istream(ctx->output, input) <= 0)
6237f743bbaf74de5a2d2051672baed87023657bTimo Sirainen i_fatal("write(stdout) failed: %m");
6237f743bbaf74de5a2d2051672baed87023657bTimo Sirainen }
6237f743bbaf74de5a2d2051672baed87023657bTimo Sirainen if (input->stream_errno != 0) {
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen i_error("read() failed: %m");
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen ret = -1;
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen }
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen i_stream_unref(&input);
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen o_stream_flush(ctx->output);
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen return ret;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen}
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
fd44baee6e92f13d42ff711895d6510067f70955Timo Sirainenstatic int fetch_body(struct fetch_cmd_context *ctx)
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen{
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen struct istream *input;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen struct message_size hdr_size;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen int ret = 0;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen if (mail_get_stream(ctx->mail, &hdr_size, NULL, &input) < 0)
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen return -1;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen if (ctx->print_field_prefix)
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen str_append_c(ctx->hdr, '\n');
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen flush_hdr(ctx);
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen i_stream_skip(input, hdr_size.physical_size);
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen while (!i_stream_is_eof(input)) {
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen if (o_stream_send_istream(ctx->output, input) <= 0)
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen i_fatal("write(stdout) failed: %m");
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen }
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen if (input->stream_errno != 0) {
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen i_error("read() failed: %m");
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen ret = -1;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen }
fd44baee6e92f13d42ff711895d6510067f70955Timo Sirainen o_stream_flush(ctx->output);
fd44baee6e92f13d42ff711895d6510067f70955Timo Sirainen return ret;
fd44baee6e92f13d42ff711895d6510067f70955Timo Sirainen}
fd44baee6e92f13d42ff711895d6510067f70955Timo Sirainen
fd44baee6e92f13d42ff711895d6510067f70955Timo Sirainenstatic int fetch_text(struct fetch_cmd_context *ctx)
fd44baee6e92f13d42ff711895d6510067f70955Timo Sirainen{
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen struct istream *input;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen int ret = 0;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen if (mail_get_stream(ctx->mail, NULL, NULL, &input) < 0)
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen return -1;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen if (ctx->print_field_prefix)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen str_append_c(ctx->hdr, '\n');
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen flush_hdr(ctx);
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen while (!i_stream_is_eof(input)) {
c740209eb3db031022c6fd436fa2ef1aa0ec46b8Timo Sirainen if (o_stream_send_istream(ctx->output, input) <= 0)
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen i_fatal("write(stdout) failed: %m");
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen if (input->stream_errno != 0) {
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen i_error("read() failed: %m");
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen ret = -1;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen }
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen o_stream_flush(ctx->output);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return ret;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen}
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainenstatic int fetch_size_physical(struct fetch_cmd_context *ctx)
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen{
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen uoff_t size;
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen if (mail_get_physical_size(ctx->mail, &size) < 0)
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return -1;
93fa87cf1a96c4f279ec4f5c311820313ba12c34Timo Sirainen str_printfa(ctx->hdr, "%"PRIuUOFF_T, size);
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen return 0;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen}
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen
811f2e26d9782d9cb99fdf82e18ffa0a77564fe2Timo Sirainenstatic int fetch_size_virtual(struct fetch_cmd_context *ctx)
2d49f150b4bce6f2f59a84e268e4777901c3e42cTimo Sirainen{
6a19e109ee8c5a6f688da83a86a7f6abeb71abddTimo Sirainen uoff_t size;
4bbee99b3aef449a9a2a11a5b5cf1ca486915c49Timo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (mail_get_virtual_size(ctx->mail, &size) < 0)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen return -1;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen str_printfa(ctx->hdr, "%"PRIuUOFF_T, size);
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen return 0;
4b058f90f9e8a2c6b2eed275de4eb8cc5195a71dTimo Sirainen}
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainenstatic int fetch_date_received(struct fetch_cmd_context *ctx)
7d75b95c260e58ee5039fa3afd79e9fda3bc8002Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen time_t t;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen if (mail_get_received_date(ctx->mail, &t) < 0)
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen return -1;
8d77ab87a57ae98532c62e5d1548bd131dee3074Timo Sirainen str_printfa(ctx->hdr, "%s", unixdate2str(t));
8d77ab87a57ae98532c62e5d1548bd131dee3074Timo Sirainen return 0;
6157a322f2ac1ea1332d9003ecb0b11466aa8fe7Timo Sirainen}
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainenstatic int fetch_date_sent(struct fetch_cmd_context *ctx)
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen{
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen time_t t;
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen int tz;
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen char chr;
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen if (mail_get_date(ctx->mail, &t, &tz) < 0)
b8d232d88018c5cafd2f3be5a181d318137a45f2Timo Sirainen return -1;
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen
cc3ccdab8a510d88fecedf95187465bf84833711Timo Sirainen chr = tz < 0 ? '-' : '+';
b8d232d88018c5cafd2f3be5a181d318137a45f2Timo Sirainen if (tz < 0) tz = -tz;
cc3ccdab8a510d88fecedf95187465bf84833711Timo Sirainen str_printfa(ctx->hdr, "%s (%c%02u%02u)", unixdate2str(t),
cc3ccdab8a510d88fecedf95187465bf84833711Timo Sirainen chr, tz/60, tz%60);
cc3ccdab8a510d88fecedf95187465bf84833711Timo Sirainen return 0;
cc3ccdab8a510d88fecedf95187465bf84833711Timo Sirainen}
b8d232d88018c5cafd2f3be5a181d318137a45f2Timo Sirainen
b8d232d88018c5cafd2f3be5a181d318137a45f2Timo Sirainenstatic int fetch_date_saved(struct fetch_cmd_context *ctx)
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen{
b8d232d88018c5cafd2f3be5a181d318137a45f2Timo Sirainen time_t t;
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen if (mail_get_save_date(ctx->mail, &t) < 0)
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen return -1;
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen str_printfa(ctx->hdr, "%s", unixdate2str(t));
b8d232d88018c5cafd2f3be5a181d318137a45f2Timo Sirainen return 0;
b8d232d88018c5cafd2f3be5a181d318137a45f2Timo Sirainen}
b8d232d88018c5cafd2f3be5a181d318137a45f2Timo Sirainen
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainenstruct fetch_field {
ddbad7a661c0663fafd2b79393efa85f840d6af6Timo Sirainen const char *name;
b8d232d88018c5cafd2f3be5a181d318137a45f2Timo Sirainen enum mail_fetch_field wanted_fields;
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen int (*print)(struct fetch_cmd_context *ctx);
fe6cf42464c36ab281c0e0740f0255be77453670Timo Sirainen};
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainenstatic const struct fetch_field fetch_fields[] = {
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen { "mailbox", 0, fetch_mailbox },
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen { "mailbox-guid", 0, fetch_mailbox_guid },
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen { "seq", 0, fetch_seq },
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen { "uid", 0, fetch_uid },
956f7778e413d3184d69e7b96e4a6b3cd5570bcdTimo Sirainen { "guid", 0, fetch_guid },
3140537477eecdc5ea0a99f77df233c297dae58dTimo Sirainen { "flags", MAIL_FETCH_FLAGS, fetch_flags },
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen { "hdr", MAIL_FETCH_STREAM_HEADER, fetch_hdr },
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen { "body", MAIL_FETCH_STREAM_BODY, fetch_body },
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen { "text", MAIL_FETCH_STREAM_HEADER |
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen MAIL_FETCH_STREAM_BODY, fetch_text },
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen { "size.physical", MAIL_FETCH_PHYSICAL_SIZE, fetch_size_physical },
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen { "size.virtual", MAIL_FETCH_VIRTUAL_SIZE, fetch_size_virtual },
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen { "date.received", MAIL_FETCH_RECEIVED_DATE, fetch_date_received },
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen { "date.sent", MAIL_FETCH_DATE, fetch_date_sent },
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen { "date.saved", MAIL_FETCH_SAVE_DATE, fetch_date_saved }
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen};
8d80659e504ffb34bb0c6a633184fece35751b18Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic const struct fetch_field *fetch_field_find(const char *name)
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen{
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen unsigned int i;
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen for (i = 0; i < N_ELEMENTS(fetch_fields); i++) {
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen if (strcmp(fetch_fields[i].name, name) == 0)
992a13add4eea0810e4db0f042a595dddf85536aTimo Sirainen return &fetch_fields[i];
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen }
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen return NULL;
6b85bc4b03e552cfaeeae872d63c2d8ac5fcb7c4Timo Sirainen}
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen
aff7542e1d2f48b030560a4f01096a2cc3f671ceTimo Sirainenstatic void print_fetch_fields(void)
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen{
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen unsigned int i;
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen fprintf(stderr, "Available fetch fields: %s", fetch_fields[0].name);
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen for (i = 1; i < N_ELEMENTS(fetch_fields); i++)
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen fprintf(stderr, " %s", fetch_fields[i].name);
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen fprintf(stderr, "\n");
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen}
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen
aff7542e1d2f48b030560a4f01096a2cc3f671ceTimo Sirainenstatic void parse_fetch_fields(struct fetch_cmd_context *ctx, const char *str)
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen{
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen const char *const *fields, *name;
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen const struct fetch_field *field;
4edf90751f075cc6ab3d6f53fc78b656efa80922Timo Sirainen
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen t_array_init(&ctx->fields, 32);
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen fields = t_strsplit_spaces(str, " ");
9a583c7a827f7a4d89ee43774f2d51ea6a214543Timo Sirainen for (; *fields != NULL; fields++) {
4edf90751f075cc6ab3d6f53fc78b656efa80922Timo Sirainen name = t_str_lcase(*fields);
a40d26f83af808a0ea1e212c001d682a96d870b0Timo Sirainen
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen field = fetch_field_find(name);
0f66f12eb4cdbf47670975044c88d8f388bf92dfTimo Sirainen if (field == NULL) {
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen print_fetch_fields();
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen i_fatal("Unknown fetch field: %s", name);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen ctx->wanted_fields |= field->wanted_fields;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen array_append(&ctx->fields, field, 1);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen }
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen ctx->print_field_prefix = array_count(&ctx->fields) > 1;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen}
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen
3140537477eecdc5ea0a99f77df233c297dae58dTimo Sirainenstatic void cmd_fetch_mail(struct fetch_cmd_context *ctx)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen{
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen const struct fetch_field *field;
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen struct mail *mail = ctx->mail;
aff7542e1d2f48b030560a4f01096a2cc3f671ceTimo Sirainen
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen array_foreach(&ctx->fields, field) {
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (ctx->print_field_prefix)
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen str_printfa(ctx->hdr, "%s: ", field->name);
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen if (field->print(ctx) < 0) {
cd56a23e21f1df3f79648cf07e2f4385e2fadebbTimo Sirainen struct mail_storage *storage =
fd2f5fbc1f07aa93e2214a28cdf02437fb7d06c8Timo Sirainen mailbox_get_storage(mail->box);
959a66f100887ce0acf442a397cfaec89570436aTimo Sirainen
369a1084c500a9df7448ffa9409ce32e42060bc2Timo Sirainen i_error("fetch(%s) failed for box=%s uid=%u: %s",
369a1084c500a9df7448ffa9409ce32e42060bc2Timo Sirainen field->name, mailbox_get_vname(mail->box),
3140537477eecdc5ea0a99f77df233c297dae58dTimo Sirainen mail->uid, mail_storage_get_last_error(storage, NULL));
369a1084c500a9df7448ffa9409ce32e42060bc2Timo Sirainen }
369a1084c500a9df7448ffa9409ce32e42060bc2Timo Sirainen str_append_c(ctx->hdr, '\n');
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen flush_hdr(ctx);
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen}
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainenstatic int
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainencmd_fetch_box(struct fetch_cmd_context *ctx, const struct mailbox_info *info)
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen{
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen struct doveadm_mail_iter *iter;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen struct mailbox_transaction_context *trans;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen struct mail *mail;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen if (doveadm_mail_iter_init(info, ctx->search_args, &trans, &iter) < 0)
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen return -1;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen mail = mail_alloc(trans, ctx->wanted_fields, NULL);
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen while (doveadm_mail_iter_next(iter, mail)) {
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen str_truncate(ctx->hdr, 0);
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen str_append(ctx->hdr, ctx->prefix);
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen ctx->mail = mail;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen cmd_fetch_mail(ctx);
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen ctx->mail = NULL;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen }
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen mail_free(&mail);
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen return doveadm_mail_iter_deinit(&iter);
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen}
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainenstatic bool search_args_have_unique_fetch(struct mail_search_args *args)
c18e2301f4c81f2819711661890db7796d4450c3Timo Sirainen{
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen struct mail_search_arg *arg;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen const struct seq_range *seqset;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen unsigned int count;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen bool have_mailbox = FALSE, have_msg = FALSE;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen for (arg = args->args; arg != NULL; arg = arg->next) {
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen switch (arg->type) {
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen case SEARCH_MAILBOX:
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen case SEARCH_MAILBOX_GUID:
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen if (!arg->not)
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen have_mailbox = TRUE;
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen break;
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen case SEARCH_SEQSET:
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen case SEARCH_UIDSET:
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen seqset = array_get(&arg->value.seqset, &count);
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen if (count == 1 && seqset->seq1 == seqset->seq2 &&
f1700e6d755306a2b137fad88ea5bf8b9fc6ec4fTimo Sirainen !arg->not)
f1700e6d755306a2b137fad88ea5bf8b9fc6ec4fTimo Sirainen have_msg = TRUE;
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen break;
c740209eb3db031022c6fd436fa2ef1aa0ec46b8Timo Sirainen default:
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen break;
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen }
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen }
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen return have_mailbox && have_msg;
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainen}
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainenstatic void
e015e2f7e7f48874495f9df8b0dd192b7ffcb5ccTimo Sirainencmd_fetch_run(struct doveadm_mail_cmd_context *_ctx, struct mail_user *user)
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen{
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen struct fetch_cmd_context *ctx = (struct fetch_cmd_context *)_ctx;
d0bbbc7057aa33b52ee378196dee7d773437468fTimo Sirainen const enum mailbox_list_iter_flags iter_flags =
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen MAILBOX_LIST_ITER_VIRTUAL_NAMES |
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen MAILBOX_LIST_ITER_NO_AUTO_INBOX |
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen MAILBOX_LIST_ITER_RETURN_NO_FLAGS;
d0bbbc7057aa33b52ee378196dee7d773437468fTimo Sirainen struct doveadm_mail_list_iter *iter;
d0bbbc7057aa33b52ee378196dee7d773437468fTimo Sirainen const struct mailbox_info *info;
8aacc9e7c84f8376822823ec98c2f551d4919b2eTimo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen iter = doveadm_mail_list_iter_init(user, ctx->search_args, iter_flags);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen while ((info = doveadm_mail_list_iter_next(iter)) != NULL) T_BEGIN {
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen (void)cmd_fetch_box(ctx, info);
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen } T_END;
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen doveadm_mail_list_iter_deinit(&iter);
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen}
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainenstatic void cmd_fetch_deinit(struct doveadm_mail_cmd_context *_ctx)
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen{
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen struct fetch_cmd_context *ctx = (struct fetch_cmd_context *)_ctx;
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen o_stream_unref(&ctx->output);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen str_free(&ctx->hdr);
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen}
d9fdacd5fb3e07997e5c389739d2054f0c8441d8Timo Sirainen
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainenstatic void cmd_fetch_init(struct doveadm_mail_cmd_context *_ctx,
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen const char *const args[])
58be9d6bcc3800f5b3d76a064ee767fbe31a5a8aTimo Sirainen{
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen struct fetch_cmd_context *ctx = (struct fetch_cmd_context *)_ctx;
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen const char *fetch_fields = args[0];
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen unsigned char prefix_buf[9];
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen if (fetch_fields == NULL || args[1] == NULL)
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen doveadm_mail_help_name("fetch");
d22390f33eedbd2413debabc0662dde5241b1aa6Timo Sirainen
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen parse_fetch_fields(ctx, fetch_fields);
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen ctx->search_args = doveadm_mail_build_search_args(args + 1);
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->output = o_stream_create_fd(STDOUT_FILENO, 0, FALSE);
0cb2e8eb55e70f8ebe1e8349bdf49e4cbe5d8834Timo Sirainen ctx->hdr = str_new(default_pool, 512);
f1700e6d755306a2b137fad88ea5bf8b9fc6ec4fTimo Sirainen if (search_args_have_unique_fetch(ctx->search_args))
f1700e6d755306a2b137fad88ea5bf8b9fc6ec4fTimo Sirainen ctx->prefix = "";
f1700e6d755306a2b137fad88ea5bf8b9fc6ec4fTimo Sirainen else {
f1700e6d755306a2b137fad88ea5bf8b9fc6ec4fTimo Sirainen random_fill_weak(prefix_buf, sizeof(prefix_buf));
f1700e6d755306a2b137fad88ea5bf8b9fc6ec4fTimo Sirainen str_append(ctx->hdr, "===");
f1700e6d755306a2b137fad88ea5bf8b9fc6ec4fTimo Sirainen base64_encode(prefix_buf, sizeof(prefix_buf), ctx->hdr);
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen str_append_c(ctx->hdr, '\n');
13c6532dc104d23061e6901783ceb1ff8872c206Timo Sirainen ctx->prefix = t_strdup(str_c(ctx->hdr));
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen str_truncate(ctx->hdr, 0);
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen }
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen}
3140537477eecdc5ea0a99f77df233c297dae58dTimo Sirainen
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainenstatic struct doveadm_mail_cmd_context *cmd_fetch_alloc(void)
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen{
6fdf8b5e4e71a69f5974f59eec2b8c19bc421fe2Timo Sirainen struct fetch_cmd_context *ctx;
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen ctx = doveadm_mail_cmd_alloc(struct fetch_cmd_context);
6e07b4251bf6a3cf34019c351a32a65c08392e58Timo Sirainen ctx->ctx.init = cmd_fetch_init;
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen ctx->ctx.run = cmd_fetch_run;
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen ctx->ctx.deinit = cmd_fetch_deinit;
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen return &ctx->ctx;
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen}
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainenstruct doveadm_mail_cmd cmd_fetch = {
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen cmd_fetch_alloc, "fetch", "<fields> <search query>"
3140537477eecdc5ea0a99f77df233c297dae58dTimo Sirainen};
7ca9da144f79317f9a0d3b0b5cc1fe21e44a5bf4Timo Sirainen