diff options
Diffstat (limited to '')
-rw-r--r-- | src/lib-mail/message-parser.h | 112 |
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 |