summaryrefslogtreecommitdiffstats
path: root/src/lib-smtp/smtp-address.h
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/lib-smtp/smtp-address.h214
1 files changed, 214 insertions, 0 deletions
diff --git a/src/lib-smtp/smtp-address.h b/src/lib-smtp/smtp-address.h
new file mode 100644
index 0000000..326a673
--- /dev/null
+++ b/src/lib-smtp/smtp-address.h
@@ -0,0 +1,214 @@
+#ifndef SMTP_ADDRESS_H
+#define SMTP_ADDRESS_H
+
+#include "array-decl.h"
+
+struct message_address;
+
+enum smtp_address_parse_flags {
+ /* Strictly enforce the RFC 5321 syntax */
+ SMTP_ADDRESS_PARSE_FLAG_STRICT = BIT(0),
+ /* Allow an empty/NULL address */
+ SMTP_ADDRESS_PARSE_FLAG_ALLOW_EMPTY = BIT(1),
+ /* Allow an address without a domain part */
+ SMTP_ADDRESS_PARSE_FLAG_ALLOW_LOCALPART = BIT(2),
+ /* Allow omission of the <...> brackets in a path. This flag is only
+ relevant for smtp_address_parse_path(). */
+ SMTP_ADDRESS_PARSE_FLAG_BRACKETS_OPTIONAL = BIT(3),
+ /* Allow localpart to have all kinds of bad unquoted characters by
+ parsing the last '@' in the string directly as the localpart/domain
+ separator. Addresses starting with `<' or `"' are parsed as normal.
+ The address is rejected when the resulting localpart and domain
+ cannot be used to construct a valid RFC 5321 address.
+ */
+ SMTP_ADDRESS_PARSE_FLAG_ALLOW_BAD_LOCALPART = BIT(4),
+ /* Store an unparsed copy of the address in the `raw' field of struct
+ smtp_address. When combined with SMTP_ADDRESS_PARSE_FLAG_SKIP_BROKEN,
+ the broken address will be stored there. This flag is only relevant
+ for smtp_address_parse_path(). */
+ SMTP_ADDRESS_PARSE_FLAG_PRESERVE_RAW = BIT(5),
+ /* Try to skip over a broken address to allow working around syntax
+ errors in e.g. the sender address for the MAIL command. This flag is
+ only relevant for smtp_address_parse_path*(). The parser will return
+ failure, but it will return a broken address which is be equivalent
+ to <>. The raw broken address string is available in the address->raw
+ field. When the broken address contains control characters or is
+ badly delimited, parsing will still fail completely. */
+ SMTP_ADDRESS_PARSE_FLAG_IGNORE_BROKEN = BIT(6),
+};
+
+struct smtp_address {
+ /* Localpart */
+ const char *localpart;
+ /* Domain */
+ const char *domain;
+ /* Raw, unparsed address. If localpart == NULL, the value of this field
+ is syntactically invalid and MUST NOT be used for any purposes that
+ may be visible to external systems. It can be e.g. used for logging.
+ This is always in mailbox format, meaning that there are no
+ surrounding '<' and '>'.
+ */
+ const char *raw;
+};
+
+ARRAY_DEFINE_TYPE(smtp_address, struct smtp_address *);
+ARRAY_DEFINE_TYPE(smtp_address_const, const struct smtp_address *);
+
+/*
+ * SMTP address parsing
+ */
+
+
+/* Parse the RFC 5321 address from the provided mailbox string. Returns 0 when
+ the address was parsed successfully and -1 upon error. The address is
+ returned in address_r. When address_r is NULL, the provided string will be
+ verified for validity as a mailbox only. */
+int smtp_address_parse_mailbox(pool_t pool, const char *mailbox,
+ enum smtp_address_parse_flags flags,
+ struct smtp_address **address_r,
+ const char **error_r) ATTR_NULL(4, 5);
+/* Parse the RFC 5321 address from the provided path string. Returns 0 when
+ the address was parsed successfully and -1 upon error. The address is
+ returned in address_r. When address_r is NULL, the provided string will be
+ verified for validity as a path only. The endp_r parameter is used to
+ return a pointer to the end of the path string, so that the caller can
+ continue parsing from there. When the SMTP_ADDRESS_PARSE_FLAG_IGNORE_BROKEN
+ flag is set, a broken address will be returned, even when the return value
+ is -1 (see above). If it is totally broken, *endp_r will be then be NULL.
+ */
+int smtp_address_parse_path_full(pool_t pool, const char *path,
+ enum smtp_address_parse_flags flags,
+ struct smtp_address **address_r,
+ const char **error_r, const char **endp_r)
+ ATTR_NULL(4, 5, 6);
+/* Parse the RFC 5321 address from the provided path string. Returns 0 when
+ the address was parsed successfully and -1 upon error. The address is
+ returned in address_r. When address_r is NULL, the provided string will be
+ verified for validity as a path only. When the
+ SMTP_ADDRESS_PARSE_FLAG_IGNORE_BROKEN flag is set, a broken address will be
+ returned, even when the return value is -1 (see above). */
+int smtp_address_parse_path(pool_t pool, const char *path,
+ enum smtp_address_parse_flags flags,
+ struct smtp_address **address_r,
+ const char **error_r) ATTR_NULL(4, 5);
+/* Parse the RFC 5321 address from the provided username string. A username
+ string is not strictly parsed as an RFC 5321 mailbox; it allows a more
+ lenient syntax. If the address obtained from splitting the string at the last
+ `@' can be encoded back into a valid RFC 5321 mailbox string, parsing the
+ username will succeeded. Returns 0 when the address was parsed successfully
+ and -1 upon error. The address is returned in address_r. When address_r is
+ NULL, the provided string will be verified for validity as a username only.
+ */
+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 pool, 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);
+
+/* Parse any (possibly broken) address on the input to the best of our ability
+ until end of input or unquoted ` '. Things that are truly evil (unending
+ quoted string, control characters and a path without a closing '>') will
+ still fail and return -1. If the parse was successful, it will return 0.
+ The parsed address string is returned in address_r. Any outer < and > are
+ omitted in the parsed address. The endp_r parameter is used to return a
+ pointer to the end of the path string, so that the caller can continue
+ parsing from there.*/
+int smtp_address_parse_any(const char *in, const char **address_r,
+ const char **endp_r) ATTR_NULL(2, 3);
+
+/*
+ * SMTP address construction
+ */
+
+void smtp_address_write(string_t *out, const struct smtp_address *address)
+ ATTR_NULL(2);
+void smtp_address_write_path(string_t *out, const struct smtp_address *address)
+ ATTR_NULL(2);
+
+const char *smtp_address_encode(const struct smtp_address *address)
+ ATTR_NULL(1);
+const char *smtp_address_encode_path(const struct smtp_address *address)
+ ATTR_NULL(1);
+
+const char *
+smtp_address_encode_raw(const struct smtp_address *address) ATTR_NULL(1);
+const char *
+smtp_address_encode_raw_path(const struct smtp_address *address) ATTR_NULL(1);
+
+/*
+ * SMTP address manipulation
+ */
+
+void smtp_address_init(struct smtp_address *address,
+ const char *localpart, const char *domain)
+ ATTR_NULL(2,3);
+int smtp_address_init_from_msg(struct smtp_address *address,
+ const struct message_address *msg_addr);
+
+struct smtp_address *
+smtp_address_clone(pool_t pool, const struct smtp_address *address)
+ ATTR_NULL(2);
+struct smtp_address *
+smtp_address_create(pool_t pool, const char *localpart, const char *domain)
+ ATTR_NULL(2, 3);
+int smtp_address_create_from_msg(pool_t pool,
+ const struct message_address *msg_addr,
+ struct smtp_address **address_r);
+
+struct smtp_address *
+smtp_address_clone_temp(const struct smtp_address *address) ATTR_NULL(1);
+struct smtp_address *
+smtp_address_create_temp(const char *localpart, const char *domain)
+ ATTR_NULL(2, 3);
+int smtp_address_create_from_msg_temp(const struct message_address *msg_addr,
+ struct smtp_address **address_r);
+
+struct smtp_address *
+smtp_address_add_detail(pool_t pool, const struct smtp_address *address,
+ const char *detail, char delim_c);
+struct smtp_address *
+smtp_address_add_detail_temp(const struct smtp_address *address,
+ const char *detail, char delim_c);
+
+int smtp_address_cmp(const struct smtp_address *address1,
+ const struct smtp_address *address2) ATTR_NULL(1, 2);
+int smtp_address_cmp_icase(const struct smtp_address *address1,
+ const struct smtp_address *address2) ATTR_NULL(1, 2);
+
+static inline bool ATTR_NULL(1, 2)
+smtp_address_equals(const struct smtp_address *address1,
+ const struct smtp_address *address2)
+{
+ return (smtp_address_cmp(address1, address2) == 0);
+}
+static inline bool ATTR_NULL(1, 2)
+smtp_address_equals_icase(const struct smtp_address *address1,
+ const struct smtp_address *address2)
+{
+ return (smtp_address_cmp_icase(address1, address2) == 0);
+}
+
+static inline bool ATTR_NULL(1) ATTR_PURE
+smtp_address_isnull(const struct smtp_address *address)
+{
+ return (address == NULL || address->localpart == NULL);
+}
+
+static inline bool ATTR_NULL(1) ATTR_PURE
+smtp_address_is_broken(const struct smtp_address *address)
+{
+ return (address != NULL &&
+ smtp_address_isnull(address) &&
+ (address->raw != NULL && *address->raw != '\0'));
+}
+
+#endif