Skip to content

Commit

Permalink
lib-smtp: address: Created SMTP address detail parsing function from …
Browse files Browse the repository at this point in the history
…message_detail_address_parse().
  • Loading branch information
stephanbosch authored and sirainen committed Nov 26, 2017
1 parent 03f08e4 commit 61ae3dd
Show file tree
Hide file tree
Showing 3 changed files with 132 additions and 0 deletions.
52 changes: 52 additions & 0 deletions src/lib-smtp/smtp-address.c
Expand Up @@ -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)
Expand Down Expand Up @@ -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
*/
Expand Down
9 changes: 9 additions & 0 deletions src/lib-smtp/smtp-address.h
Expand Up @@ -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
*/
Expand Down
71 changes: 71 additions & 0 deletions src/lib-smtp/test-smtp-address.c
Expand Up @@ -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
*/
Expand All @@ -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);
Expand Down

0 comments on commit 61ae3dd

Please sign in to comment.