changeset 20258:a326b886ecbd

doveadm fetch: Added body.<section> and binary.<section> fields These correspond to IMAP BODY[<section>].
author Timo Sirainen <timo.sirainen@dovecot.fi>
date Tue, 03 May 2016 14:54:28 +0300
parents 7e6d01439d76
children 161d6407e613
files src/doveadm/Makefile.am src/doveadm/doveadm-mail-fetch.c
diffstat 2 files changed, 46 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/src/doveadm/Makefile.am	Wed Apr 20 14:33:57 2016 +0300
+++ b/src/doveadm/Makefile.am	Tue May 03 14:54:28 2016 +0300
@@ -20,6 +20,7 @@
 	-I$(top_srcdir)/src/lib-imap \
 	-I$(top_srcdir)/src/lib-index \
 	-I$(top_srcdir)/src/lib-storage \
+	-I$(top_srcdir)/src/lib-imap-storage \
 	-I$(top_srcdir)/src/lib-http \
 	-I$(top_srcdir)/src/auth \
 	-DMODULEDIR=\""$(moduledir)"\" \
--- a/src/doveadm/doveadm-mail-fetch.c	Wed Apr 20 14:33:57 2016 +0300
+++ b/src/doveadm/doveadm-mail-fetch.c	Tue May 03 14:54:28 2016 +0300
@@ -15,6 +15,7 @@
 #include "mail-storage.h"
 #include "mail-search.h"
 #include "mail-namespace.h"
+#include "imap-msgpart.h"
 #include "doveadm-print.h"
 #include "doveadm-mail.h"
 #include "doveadm-mailbox-list-iter.h"
@@ -186,6 +187,31 @@
 	return 0;
 }
 
+static int fetch_body_field(struct fetch_cmd_context *ctx)
+{
+	const char *name = ctx->cur_field->name;
+	struct imap_msgpart *msgpart;
+	struct imap_msgpart_open_result result;
+	bool binary;
+	int ret;
+
+	binary = strncmp(name, "binary.", 7) == 0;
+	name += binary ? 7 : 5;
+	if (imap_msgpart_parse(name, &msgpart) < 0)
+		i_unreached(); /* we already verified this was ok */
+	if (binary)
+		imap_msgpart_set_decode_to_binary(msgpart);
+
+	if (imap_msgpart_open(ctx->mail, msgpart, &result) < 0) {
+		imap_msgpart_free(&msgpart);
+		return -1;
+	}
+	ret = doveadm_print_istream(result.input);
+	i_stream_unref(&result.input);
+	imap_msgpart_free(&msgpart);
+	return ret;
+}
+
 static int fetch_body(struct fetch_cmd_context *ctx)
 {
 	struct istream *input;
@@ -476,7 +502,7 @@
 {
 	unsigned int i;
 
-	fprintf(stderr, "Available fetch fields: %s", fetch_fields[0].name);
+	fprintf(stderr, "Available fetch fields: hdr.<name> body.<section> binary.<section> %s", fetch_fields[0].name);
 	for (i = 1; i < N_ELEMENTS(fetch_fields); i++)
 		fprintf(stderr, " %s", fetch_fields[i].name);
 	fprintf(stderr, "\n");
@@ -486,11 +512,15 @@
 {
 	const char *const *fields, *name;
 	const struct fetch_field *field;
-	struct fetch_field hdr_field;
+	struct fetch_field hdr_field, body_field;
+	struct imap_msgpart *msgpart;
 
 	memset(&hdr_field, 0, sizeof(hdr_field));
 	hdr_field.print = fetch_hdr_field;
 
+	memset(&body_field, 0, sizeof(body_field));
+	body_field.print = fetch_body_field;
+
 	t_array_init(&ctx->fields, 32);
 	t_array_init(&ctx->header_fields, 32);
 	fields = t_strsplit_spaces(str, " ");
@@ -504,6 +534,19 @@
 			array_append(&ctx->fields, &hdr_field, 1);
 			name = t_strcut(name, '.');
 			array_append(&ctx->header_fields, &name, 1);
+		} else if (strncmp(name, "body.", 5) == 0 ||
+			   strncmp(name, "binary.", 7) == 0) {
+			bool binary = strncmp(name, "binary.", 7) == 0;
+			body_field.name = name;
+
+			name += binary ? 7 : 5;
+			if (imap_msgpart_parse(name, &msgpart) < 0) {
+				print_fetch_fields();
+				i_fatal("Unknown fetch section: %s", name);
+			}
+			array_append(&ctx->fields, &body_field, 1);
+			ctx->wanted_fields |= imap_msgpart_get_fetch_data(msgpart);
+			imap_msgpart_free(&msgpart);
 		} else {
 			field = fetch_field_find(name);
 			if (field == NULL) {