]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
lib-smtp: address: Created SMTP address detail parsing function from message_detail_a...
authorStephan Bosch <stephan.bosch@dovecot.fi>
Sun, 29 Oct 2017 22:37:47 +0000 (23:37 +0100)
committerTimo Sirainen <timo.sirainen@dovecot.fi>
Sun, 26 Nov 2017 20:30:01 +0000 (22:30 +0200)
src/lib-smtp/smtp-address.c
src/lib-smtp/smtp-address.h
src/lib-smtp/test-smtp-address.c

index d29eb2649f41de279dd98df063bb9b4c2093a8dd..77342082ef616562444083a4e450f810a8994552 100644 (file)
@@ -309,6 +309,9 @@ int smtp_address_parse_mailbox(pool_t pool,
        if (error_r != NULL)
                *error_r = NULL;
 
+       if (error_r != NULL)
+               *error_r = NULL;
+
        if ((mailbox == NULL || *mailbox == '\0')) {
                if ((flags & SMTP_ADDRESS_PARSE_FLAG_ALLOW_EMPTY) == 0) {
                        if (error_r != NULL)
@@ -438,6 +441,55 @@ int smtp_address_parse_username(pool_t pool, const char *username,
        return 1;
 }
 
+void smtp_address_detail_parse(pool_t pool, const char *delimiters,
+       struct smtp_address *address, const char **username_r,
+       char *delim_r, const char **detail_r)
+{
+       const char *localpart = address->localpart;
+       const char *user, *p;
+       size_t idx;
+
+       user = localpart;
+       *detail_r = "";
+       *delim_r = '\0';
+
+       /* first character that matches the recipient_delimiter */
+       idx = strcspn(localpart, delimiters);
+       p = (localpart[idx] != '\0' ? &localpart[idx] : NULL);
+
+       if (p != NULL) {
+               *delim_r = *p;
+               /* user+detail */
+               user = p_strdup_until(pool, localpart, p);
+               *detail_r = p+1;
+       }
+
+       if (address->domain == NULL)
+               *username_r = user;
+       else if (strchr(user, '@') == NULL ) {
+               /* username is just glued to the domain... no SMTP escaping */
+               *username_r = p_strconcat(pool,
+                       user, "@", address->domain, NULL);
+       } else {
+               struct smtp_address uaddr;
+
+               /* username contains '@'; apply escaping */
+               smtp_address_init(&uaddr, user, address->domain);
+               if (pool->datastack_pool)
+                       *username_r = smtp_address_encode(&uaddr);
+               else
+                       *username_r = p_strdup(pool, smtp_address_encode(&uaddr));
+       }
+}
+
+void smtp_address_detail_parse_temp(const char *delimiters,
+       struct smtp_address *address, const char **username_r,
+       char *delim_r, const char **detail_r)
+{
+       smtp_address_detail_parse(pool_datastack_create(), delimiters,
+                                 address, username_r, delim_r, detail_r);
+}
+
 /*
  * SMTP address construction
  */
index 01b499ad062fef38735168fff2a930bb48a32b8b..18703d86a325dfd6a61ac54cf35a1ee3fad6a014 100644 (file)
@@ -48,6 +48,15 @@ int smtp_address_parse_username(pool_t pool, const char *username,
        struct smtp_address **address_r, const char **error_r)
        ATTR_NULL(3, 4);
 
+/* Parse address+detail@domain into address@domain and detail
+   using given delimiters. Returns used delimiter. */
+void smtp_address_detail_parse(pool_t poo, const char *delimiters,
+       struct smtp_address *address, const char **username_r,
+       char *delim_r, const char **detail_r);
+void smtp_address_detail_parse_temp(const char *delimiters,
+       struct smtp_address *address, const char **username_r,
+       char *delim_r, const char **detail_r);
+
 /*
  * SMTP address construction
  */
index c0a22bd596af4adf7aa0849e1b91f9d8075f0784..2ae59deed7d510fe80f301707ed5701f8e618cde 100644 (file)
@@ -732,6 +732,76 @@ static void test_smtp_username_parse_invalid(void)
        } T_END;
 }
 
+/*
+ * Address detail parsing
+ */
+
+struct address_detail_parse_test {
+               const char *delimiters;
+               const char *address;
+               const char *username;
+               const char *detail;
+               char delim;
+};
+
+static const struct address_detail_parse_test
+address_detail_parse_tests[] = {
+       { "", "test", "test", "", '\0' },
+       { "", "test+address", "test+address", "", '\0' },
+       { "", "\"test:address\"", "test:address", "", '\0' },
+       { "", "\"test-address:another+delim\"", "test-address:another+delim", "", '\0' },
+       { "", "test@domain", "test@domain", "", '\0' },
+       { "", "test+address@domain", "test+address@domain", "", '\0' },
+       { "", "\"test:address\"@domain", "test:address@domain", "", '\0' },
+       { "", "\"test-address:another+delim\"@domain", "test-address:another+delim@domain", "", '\0' },
+
+       { "+-:", "test", "test", "", '\0' },
+       { "+-:", "test+address", "test", "address", '+' },
+       { "+-:", "\"test:address\"", "test", "address", ':' },
+       { "+-:", "\"test-address:another+delim\"", "test", "address:another+delim", '-' },
+       { "+-:", "test@domain", "test@domain", "", '\0' },
+       { "+-:", "test+address@domain", "test@domain", "address", '+' },
+       { "+-:", "\"test:address\"@domain", "test@domain", "address", ':' },
+       { "+-:", "\"test-address:another+delim\"@domain", "test@domain", "address:another+delim", '-' }
+};
+
+unsigned int addresss_detail_parse_test_count =
+       N_ELEMENTS(address_detail_parse_tests);
+
+static void test_smtp_address_detail_parse(void)
+{
+       unsigned int i;
+
+
+       for (i = 0; i < N_ELEMENTS(address_detail_parse_tests); i++) T_BEGIN {
+               const struct address_detail_parse_test *test =
+                       &address_detail_parse_tests[i];
+               struct smtp_address *address;
+               const char *username, *detail, *error;
+               char delim;
+               int ret;
+
+               test_begin(t_strdup_printf(
+                       "smtp address detail parsing [%d]", i));
+
+               ret = smtp_address_parse_path(pool_datastack_create(), test->address,
+                       SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART |
+                       SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL,
+                       &address, &error);
+               test_out_reason("address parse", ret > 0, error);
+
+               if (!test_has_failed()) {
+                       smtp_address_detail_parse_temp(test->delimiters, address,
+                                                 &username, &delim, &detail);
+                       test_assert(strcmp(username, test->username) == 0);
+                       test_assert(strcmp(detail, test->detail) == 0);
+                       test_assert(delim == test->delim);
+               }
+
+               test_end();
+       } T_END;
+}
+
 /*
  * Tests
  */
@@ -745,6 +815,7 @@ int main(void)
                test_smtp_mailbox_parse_invalid,
                test_smtp_path_parse_invalid,
                test_smtp_username_parse_invalid,
+               test_smtp_address_detail_parse,
                NULL
        };
        return test_run(test_functions);