Mailex.AddressParser (Mailex v0.1.3)

Copy Markdown View Source

RFC 5322 email address parser using NimbleParsec.

Parses email addresses according to RFC 5322 §3.4, including:

  • addr-spec (simple address like user@domain)
  • mailbox (with optional display-name)
  • group (named list of mailboxes)
  • address-list (comma-separated addresses)

Supports obsolete syntax (RFC 5322 §4.4):

  • obs-phrase (periods in display names)
  • obs-local-part (CFWS between parts)

Supports RFC 6532 internationalized email addresses (EAI):

  • UTF-8 characters in local-part
  • UTF-8 characters in domain (internationalized domain names)
  • UTF-8 characters in display-name

Summary

Functions

Parses the given binary as do_parse_address_list.

Parses an addr-spec (bare email address without display name).

Parses a single address (either a mailbox or a group).

Parses a comma-separated list of addresses.

Parses an RFC 5322 group (named list of mailboxes).

Parses a mailbox (email address with optional display name).

Functions

build_addr_spec(rest, args, context, line, offset)

build_bare_mailbox(rest, args, context, line, offset)

build_group(rest, args, context, line, offset)

build_name_addr(rest, args, context, line, offset)

collect_list(rest, args, context, line, offset)

do_parse_address_list(binary, opts \\ [])

@spec do_parse_address_list(binary(), keyword()) ::
  {:ok, [term()], rest, context, line, byte_offset}
  | {:error, reason, rest, context, line, byte_offset}
when line: {pos_integer(), byte_offset},
     byte_offset: non_neg_integer(),
     rest: binary(),
     reason: String.t(),
     context: map()

Parses the given binary as do_parse_address_list.

Returns {:ok, [token], rest, context, position, byte_offset} or {:error, reason, rest, context, line, byte_offset} where position describes the location of the do_parse_address_list (start position) as {line, offset_to_start_of_line}.

To column where the error occurred can be inferred from byte_offset - offset_to_start_of_line.

Options

  • :byte_offset - the byte offset for the whole binary, defaults to 0
  • :line - the line and the byte offset into that line, defaults to {1, byte_offset}
  • :context - the initial context value. It will be converted to a map

join_phrase(parts)

parse_addr_spec(input)

@spec parse_addr_spec(binary()) :: {:ok, map()} | {:error, term()}

Parses an addr-spec (bare email address without display name).

Returns {:ok, map} with :local_part and :domain keys on success.

Examples

iex> Mailex.AddressParser.parse_addr_spec("user@example.com")
{:ok, %{local_part: "user", domain: "example.com"}}

iex> Mailex.AddressParser.parse_addr_spec(""quoted.user"@example.com")
{:ok, %{local_part: "quoted.user", domain: "example.com"}}

parse_address(input)

@spec parse_address(binary()) :: {:ok, map()} | {:error, term()}

Parses a single address (either a mailbox or a group).

Returns {:ok, map} on success. The result has :type key that is either :mailbox or :group.

Examples

iex> Mailex.AddressParser.parse_address("user@example.com")
{:ok, %{type: :mailbox, name: nil, address: "user@example.com"}}

iex> Mailex.AddressParser.parse_address("Team: user@example.com;")
{:ok, %{type: :group, name: "Team", members: [...]}}

parse_address_list(input)

@spec parse_address_list(binary()) :: {:ok, [map()]} | {:error, term()}

Parses a comma-separated list of addresses.

Returns {:ok, list} where each element is a mailbox or group map.

Examples

iex> Mailex.AddressParser.parse_address_list("alice@example.com, bob@example.com")
{:ok, [
  %{type: :mailbox, name: nil, address: "alice@example.com"},
  %{type: :mailbox, name: nil, address: "bob@example.com"}
]}

iex> Mailex.AddressParser.parse_address_list("Alice <alice@example.com>, Team: bob@example.com;")
{:ok, [
  %{type: :mailbox, name: "Alice", address: "alice@example.com"},
  %{type: :group, name: "Team", members: [...]}
]}

parse_group(input)

@spec parse_group(binary()) :: {:ok, map()} | {:error, term()}

Parses an RFC 5322 group (named list of mailboxes).

Returns {:ok, map} with :type, :name, and :members keys on success.

Examples

iex> Mailex.AddressParser.parse_group("Team: alice@example.com, bob@example.com;")
{:ok, %{type: :group, name: "Team", members: [
  %{type: :mailbox, name: nil, address: "alice@example.com"},
  %{type: :mailbox, name: nil, address: "bob@example.com"}
]}}

iex> Mailex.AddressParser.parse_group("Empty:;")
{:ok, %{type: :group, name: "Empty", members: []}}

parse_mailbox(input)

@spec parse_mailbox(binary()) :: {:ok, map()} | {:error, term()}

Parses a mailbox (email address with optional display name).

Returns {:ok, map} with :type, :name, and :address keys on success.

Examples

iex> Mailex.AddressParser.parse_mailbox("user@example.com")
{:ok, %{type: :mailbox, name: nil, address: "user@example.com"}}

iex> Mailex.AddressParser.parse_mailbox("John Doe <john@example.com>")
{:ok, %{type: :mailbox, name: "John Doe", address: "john@example.com"}}

iex> Mailex.AddressParser.parse_mailbox(""John Doe" <john@example.com>")
{:ok, %{type: :mailbox, name: "John Doe", address: "john@example.com"}}