/* Copyright (c) 2013-2018 Dovecot authors, see the included COPYING file */
#include "lib.h"
#include "str.h"
#include "message-address.h"
#include "smtp-parser.h"
#include "smtp-address.h"
/* From RFC 5321:
Reverse-path = Path / "<>"
Forward-path = Path
Path = "<" [ A-d-l ":" ] Mailbox ">"
A-d-l = At-domain *( "," At-domain )
; Note that this form, the so-called "source
; route", MUST BE accepted, SHOULD NOT be
; generated, and SHOULD be ignored.
At-domain = "@" Domain
Domain = sub-domain *("." sub-domain)
sub-domain = Let-dig [Ldh-str]
Let-dig = ALPHA / DIGIT
Ldh-str = *( ALPHA / DIGIT / "-" ) Let-dig
address-literal = "[" ( IPv4-address-literal /
IPv6-address-literal /
General-address-literal ) "]"
; See Section 4.1.3
Mailbox = Local-part "@" ( Domain / address-literal )
Local-part = Dot-string / Quoted-string
; MAY be case-sensitive
Dot-string = Atom *("." Atom)
Atom = 1*atext
*/
/*
* SMTP address parsing
*/
struct smtp_address_parser {
};
static int
const char **value_r)
{
/* Dot-string = Atom *("." Atom)
*/
/* NOTE: this deviates from Dot-String syntax to allow some Japanese
mail addresses with dots at non-standard places to be accepted. */
return 0;
return 1;
}
static int
const char **localpart_r)
{
int ret;
return ret;
}
static int
{
int ret;
/* Mailbox = Local-part "@" ( Domain / address-literal )
*/
return ret;
(flags & SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART) == 0) {
else
return -1;
}
return 1;
return -1;
} else {
return -1;
}
}
return ret;
}
static int
{
/* Source-route = [ A-d-l ":" ]
A-d-l = At-domain *( "," At-domain )
At-domain = "@" Domain
*/
/* "@" Domain */
return 0;
for (;;) {
/* Domain */
"Missing domain after '@' in source route";
return -1;
}
/* *( "," At-domain ) */
break;
/* "@" Domain */
return -1;
}
}
/* ":" */
return -1;
}
return 1;
}
static int
{
/* Path = "<" [ A-d-l ":" ] Mailbox ">"
*/
/* "<" */
} else if ((flags & SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL) == 0) {
return 0;
}
/* [ A-d-l ":" ] */
return -1;
/* Mailbox */
return -1;
if (ret == 0) {
if (sret > 0) {
"Path only consists of source route";
return -1;
}
== 0) {
return -1;
}
} else {
return -1;
}
}
/* ">" */
return -1;
}
return -1;
}
return 1;
}
static int
{
const unsigned char *p, *dp;
int ret;
/* Best-effort extraction of SMTP address from a user name.
*/
/* if the local part is a quoted string, parse it as any other
SMTP address */
return ret;
} else {
/* use the right-most '@' as separator */
dp--;
/* check whether the resulting localpart could be encoded as
quoted string */
if (!smtp_char_is_qtext(*p) || *p == ' ') {
"Invalid character in user name";
return -1;
}
}
}
}
return -1;
}
return 1;
return -1;
} else {
return -1;
}
}
return ret;
}
{
int ret;
if ((flags & SMTP_ADDRESS_PARSE_FLAG_ALLOW_EMPTY) == 0) {
*error_r = "Mailbox is empty string";
return -1;
}
return 1;
}
"Invalid character in localpart");
return -1;
}
*error_r = "Invalid character in mailbox";
return -1;
}
return 1;
}
const char **endp_r)
{
int ret;
if ((flags & SMTP_ADDRESS_PARSE_FLAG_ALLOW_EMPTY) == 0 ||
(flags & SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL) == 0) {
*error_r = "Path is empty string";
return -1;
}
return 1;
}
"Missing '<' at beginning of path");
}
return -1;
}
*error_r = "Invalid character in path";
return -1;
}
return 1;
}
{
}
{
int ret;
*error_r = "Username is empty string";
return -1;
}
"Invalid character in user name");
}
return -1;
}
*error_r = "Invalid character in user name";
return -1;
}
return 1;
}
{
const char *localpart;
const char *user, *p;
*detail_r = "";
*delim_r = '\0';
/* first character that matches the recipient_delimiter */
if (p != NULL) {
*delim_r = *p;
/* user+detail */
*detail_r = p+1;
}
*username_r = user;
/* username is just glued to the domain... no SMTP escaping */
} else {
/* username contains '@'; apply escaping */
if (pool->datastack_pool)
else
}
}
{
}
/*
* SMTP address construction
*/
{
if (smtp_address_isnull(address))
return;
/* encode localpart */
return;
pblock = p;
while (p < pend) {
while (p < pend && smtp_char_is_atext(*p))
p++;
}
if (p >= pend)
break;
if (!quoted) {
} else {
if (!smtp_char_is_qtext(*p))
str_append_c(out, *p);
}
p++;
pblock = p;
}
if (p == pblock) {
}
if (quoted)
return;
}
const struct smtp_address *address)
{
}
const char *
{
}
const char *
{
}
/*
* SMTP address manipulation
*/
{
}
const struct message_address *msg_addr)
{
}
struct smtp_address *
{
if (smtp_address_isnull(src))
return NULL;
/* @UNSAFE */
size = sizeof(struct smtp_address);
}
if (dsize > 0) {
}
return new;
}
struct smtp_address *
{
}
struct smtp_address *
const struct message_address *msg_addr)
{
}
struct smtp_address *
{
if (smtp_address_isnull(src))
return NULL;
return new;
}
struct smtp_address *
{
return smtp_address_clone_temp(&addr);
}
struct smtp_address *
{
return smtp_address_clone_temp(&addr);
}
struct smtp_address *
{
return new_addr;
}
struct smtp_address *
{
return new_addr;
}
const struct smtp_address *address2)
{
int ret;
if (null1)
return (null2 ? 0 : -1);
else if (null2)
return 1;
return ret;
}