From 5430411539347357344f6bf2552731b62f0a14fd Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Wed, 7 Jun 2017 15:33:42 +0300 Subject: [PATCH] lib-mail: message_address_parse() - Handle invalid standalone phrases better We'll treat "local-part" (without quotes) as a mailbox even without @domain, but if it continues with anything or if it's a quoted-string, we'll treat it as a display-name instead. This is probably better than just converting everything to display-name, since there are likely to exist headers like "To: localuser" --- src/lib-mail/message-address.c | 23 ++++++++++++++++++++++- src/lib-mail/test-message-address.c | 20 ++++++++++++++++++++ 2 files changed, 42 insertions(+), 1 deletion(-) diff --git a/src/lib-mail/message-address.c b/src/lib-mail/message-address.c index 56f2707252..a5d840dec8 100644 --- a/src/lib-mail/message-address.c +++ b/src/lib-mail/message-address.c @@ -209,10 +209,13 @@ static int parse_name_addr(struct message_address_parser_context *ctx) static int parse_addr_spec(struct message_address_parser_context *ctx) { /* addr-spec = local-part "@" domain */ - int ret, ret2; + int ret, ret2 = -2; + + i_assert(ctx->parser.data != ctx->parser.end); str_truncate(ctx->parser.last_comment, 0); + bool quoted_string = *ctx->parser.data == '"'; ret = parse_local_part(ctx); if (ret <= 0) { /* end of input or parsing local-part failed */ @@ -226,6 +229,24 @@ static int parse_addr_spec(struct message_address_parser_context *ctx) if (str_len(ctx->parser.last_comment) > 0) ctx->addr.name = p_strdup(ctx->pool, str_c(ctx->parser.last_comment)); + else if (ret2 == -2) { + /* So far we've read user without @domain and without + (Display Name). We'll assume that a single "user" (already + read into addr.mailbox) is a mailbox, but if it's followed + by anything else it's a display-name. */ + str_append_c(ctx->str, ' '); + size_t orig_str_len = str_len(ctx->str); + (void)rfc822_parse_phrase(&ctx->parser, ctx->str); + if (str_len(ctx->str) != orig_str_len) { + ctx->addr.mailbox = NULL; + ctx->addr.name = p_strdup(ctx->pool, str_c(ctx->str)); + } else { + if (!quoted_string) + ctx->addr.domain = ""; + } + ctx->addr.invalid_syntax = TRUE; + ret = -1; + } return ret; } diff --git a/src/lib-mail/test-message-address.c b/src/lib-mail/test-message-address.c index d0de25750a..c9231d23a3 100644 --- a/src/lib-mail/test-message-address.c +++ b/src/lib-mail/test-message-address.c @@ -49,9 +49,23 @@ static void test_message_address(void) { NULL, NULL, NULL, "user\"name", "domain", FALSE } }, { "\"\"@domain", "<\"\"@domain>", { NULL, NULL, NULL, "", "domain", FALSE } }, + { "user", "", + { NULL, NULL, NULL, "user", "", TRUE } }, { "@domain", "<\"\"@domain>", { NULL, NULL, NULL, "", "domain", TRUE } }, + /* Display Name -> Display Name */ + { "Display Name", "\"Display Name\"", + { NULL, "Display Name", NULL, "", "", TRUE } }, + { "\"Display Name\"", "\"Display Name\"", + { NULL, "Display Name", NULL, "", "", TRUE } }, + { "Display \"Name\"", "\"Display Name\"", + { NULL, "Display Name", NULL, "", "", TRUE } }, + { "\"Display\" \"Name\"", "\"Display Name\"", + { NULL, "Display Name", NULL, "", "", TRUE } }, + { "\"\"", "", + { NULL, "", NULL, "", "", TRUE } }, + /* -> */ { "", NULL, { NULL, NULL, NULL, "user", "domain", FALSE } }, @@ -65,6 +79,8 @@ static void test_message_address(void) { NULL, NULL, NULL, "user\"name", "domain", FALSE } }, { "<\"\"@domain>", NULL, { NULL, NULL, NULL, "", "domain", FALSE } }, + { "", NULL, + { NULL, NULL, NULL, "user", "", TRUE } }, { "<@route>", "<@route:\"\">", { NULL, NULL, "@route", "", "", TRUE } }, @@ -79,6 +95,8 @@ static void test_message_address(void) { NULL, "Display Name", NULL, "user", "", TRUE } }, { "@domain (Display Name)", "\"Display Name\" <\"\"@domain>", { NULL, "Display Name", NULL, "", "domain", TRUE } }, + { "user@domain ()", "", + { NULL, NULL, NULL, "user", "domain", FALSE } }, /* Display Name -> "Display Name" */ { "DisplayName ", NULL, @@ -91,6 +109,8 @@ static void test_message_address(void) { NULL, "Display\"Name", NULL, "user", "domain", FALSE } }, { "Display Name ", "\"Display Name\" ", { NULL, "Display Name", NULL, "user", "", TRUE } }, + { "\"\" ", "", + { NULL, NULL, NULL, "user", "domain", FALSE } }, /* <@route:user@domain> -> <@route:user@domain> */ { "<@route:user@domain>", NULL, -- 2.47.3