summaryrefslogtreecommitdiffstats
path: root/src/lib-mail/message-parser.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib-mail/message-parser.h112
1 files changed, 112 insertions, 0 deletions
diff --git a/src/lib-mail/message-parser.h b/src/lib-mail/message-parser.h
new file mode 100644
index 0000000..f19e526
--- /dev/null
+++ b/src/lib-mail/message-parser.h
@@ -0,0 +1,112 @@
+#ifndef MESSAGE_PARSER_H
+#define MESSAGE_PARSER_H
+
+#include "message-header-parser.h"
+#include "message-part.h"
+
+enum message_parser_flags {
+ /* Don't return message bodies in message_blocks. */
+ MESSAGE_PARSER_FLAG_SKIP_BODY_BLOCK = 0x01,
+ /* Buggy software creates Content-Type: headers without Mime-Version:
+ header. By default we allow this and assume message is MIME if
+ Content-Type: is found. This flag disables this. */
+ MESSAGE_PARSER_FLAG_MIME_VERSION_STRICT = 0x02,
+ /* Return multipart (preamble and epilogue) blocks */
+ MESSAGE_PARSER_FLAG_INCLUDE_MULTIPART_BLOCKS = 0x04,
+ /* Return --boundary lines */
+ MESSAGE_PARSER_FLAG_INCLUDE_BOUNDARIES = 0x08
+};
+
+#define MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS 100
+#define MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS 10000
+
+struct message_parser_settings {
+ enum message_header_parser_flags hdr_flags;
+ enum message_parser_flags flags;
+
+ /* Maximum nested MIME parts.
+ 0 = MESSAGE_PARSER_DEFAULT_MAX_NESTED_MIME_PARTS. */
+ unsigned int max_nested_mime_parts;
+ /* Maximum MIME parts in total.
+ 0 = MESSAGE_PARSER_DEFAULT_MAX_TOTAL_MIME_PARTS. */
+ unsigned int max_total_mime_parts;
+};
+
+struct message_parser_ctx;
+
+struct message_block {
+ /* Message part this block belongs to */
+ struct message_part *part;
+
+ /* non-NULL if a header line was read */
+ struct message_header_line *hdr;
+
+ /* hdr = NULL, size = 0 block returned at the end of headers for the
+ empty line between header and body (unless the header is truncated).
+ Later on data and size>0 is returned for blocks of mail body that
+ is read (see message_parser_flags for what is actually returned) */
+ const unsigned char *data;
+ size_t size;
+};
+
+/* called once with hdr = NULL at the end of headers */
+typedef void message_part_header_callback_t(struct message_part *part,
+ struct message_header_line *hdr,
+ void *context);
+
+extern message_part_header_callback_t *null_message_part_header_callback;
+
+/* Initialize message parser. part_spool specifies where struct message_parts
+ are allocated from. */
+struct message_parser_ctx *
+message_parser_init(pool_t part_pool, struct istream *input,
+ const struct message_parser_settings *set);
+/* Deinitialize message parser. The ctx must NOT have been created by
+ message_parser_init_from_parts(). */
+void message_parser_deinit(struct message_parser_ctx **ctx,
+ struct message_part **parts_r);
+/* Use preparsed parts to speed up parsing. */
+struct message_parser_ctx *
+message_parser_init_from_parts(struct message_part *parts,
+ struct istream *input,
+ const struct message_parser_settings *set);
+/* Same as message_parser_deinit(), but return an error message describing
+ why the preparsed parts didn't match the message. This can also safely be
+ called even when preparsed parts weren't used - it'll always just return
+ success in that case. */
+int message_parser_deinit_from_parts(struct message_parser_ctx **_ctx,
+ struct message_part **parts_r,
+ const char **error_r);
+
+/* Read the next block of a message. Returns 1 if block is returned, 0 if
+ input stream is non-blocking and more data needs to be read, -1 when all is
+ done or error occurred (see stream's error status). */
+int message_parser_parse_next_block(struct message_parser_ctx *ctx,
+ struct message_block *block_r);
+
+/* Read and parse header. */
+void message_parser_parse_header(struct message_parser_ctx *ctx,
+ struct message_size *hdr_size,
+ message_part_header_callback_t *callback,
+ void *context) ATTR_NULL(4);
+#define message_parser_parse_header(ctx, hdr_size, callback, context) \
+ message_parser_parse_header(ctx, hdr_size - \
+ CALLBACK_TYPECHECK(callback, void (*)( \
+ struct message_part *, \
+ struct message_header_line *, typeof(context))), \
+ (message_part_header_callback_t *)callback, context)
+
+/* Read and parse body. If message is a MIME multipart or message/rfc822
+ message, hdr_callback is called for all headers. body_callback is called
+ for the body content. */
+void message_parser_parse_body(struct message_parser_ctx *ctx,
+ message_part_header_callback_t *hdr_callback,
+ void *context) ATTR_NULL(3);
+#define message_parser_parse_body(ctx, callback, context) \
+ message_parser_parse_body(ctx, \
+ (message_part_header_callback_t *)callback, \
+ (void *)((uintptr_t)context - CALLBACK_TYPECHECK(callback, \
+ void (*)(struct message_part *, \
+ struct message_header_line *, typeof(context)))))
+
+#endif