View Source Mua (Mua v0.1.6)

Minimal SMTP client.

Summary

Functions

Sends AUTH extension command and authenticates the sender.

Closes connection to the SMTP server.

Connects to an SMTP server and receives its banner.

Sends DATA command that specifies the beginning of the mail, and then sends the message.

Utility function to send a message to a list of recipients on a host.

Sends EHLO command which provides the identification of the sender i.e. the host name, and receives the list of extensions the server supports.

Utility function to guess the local hostname to use for HELO/EHLO.

Sends HELO command which provides the identification of the sender i.e. the host name.

Sends MAIL FROM command that specifies the originator of the mail.

Utility function to lookup MX servers for a domain.

Sends NOOP command that does nothing.

Utility function to pick a supported auth method from a list of extensions.

Sends QUIT command that make the server close the connection.

Sends RCPT TO command that specify the recipient of the mail.

Sends RSET command that aborts the current mail transaction but keeps the socket open.

Sends STARTTLS extension command and starts TLS session negotiation.

Sends VRFY command that confirms or verifies the user name.

Types

@type auth_credentials() :: [username: String.t(), password: String.t()]
@type auth_method() :: :login | :plain
@type error() :: {:error, Mua.SMTPError.t() | Mua.TransportError.t()}
@type host() :: :inet.socket_address() | :inet.hostname() | String.t()
@type option() ::
  {:timeout, timeout()}
  | {:protocol, proto()}
  | {:auth, auth_credentials()}
  | {:port, :inet.port_number()}
  | {:transport_opts, transport_opts()}
@type proto() :: :tcp | :ssl
@type socket() :: :gen_tcp.socket() | :ssl.sslsocket()
@type transport_opts() :: [:gen_tcp.connect_option() | :ssl.tls_client_option()]

Functions

Link to this function

auth(socket, kind, opts \\ [], timeout \\ 30000)

View Source
@spec auth(socket(), auth_method(), auth_credentials(), timeout()) :: :ok | error()

Sends AUTH extension command and authenticates the sender.

:ok = auth(socket, :login, username: username, password: password)
:ok = auth(socket, :plain, username: username, password: password)
@spec close(socket()) :: :ok | {:error, Mua.TransportError.t()}

Closes connection to the SMTP server.

:ok = close(socket)
Link to this function

connect(protocol, address, port, opts \\ [], timeout \\ 30000)

View Source
@spec connect(proto(), host(), :inet.port_number(), transport_opts(), timeout()) ::
  {:ok, socket(), banner :: String.t()} | error()

Connects to an SMTP server and receives its banner.

{:ok, socket, _banner} = connect(:tcp, host, _port = 25)
{:ok, socket, _banner} = connect(:ssl, host, _port = 465, versions: [:"tlsv1.3"])
Link to this function

data(socket, message, timeout \\ 30000)

View Source
@spec data(socket(), iodata(), timeout()) :: {:ok, receipt :: String.t()} | error()

Sends DATA command that specifies the beginning of the mail, and then sends the message.

{:ok, _receipt} = data(socket, "Date: Sat, 24 Jun 2023 13:43:57 +0000\r\n...")
Link to this function

easy_send(host, sender, recipients, message, opts \\ [])

View Source
@spec easy_send(String.t() | :inet.ip_address(), String.t(), [String.t()], iodata(), [
  option()
]) ::
  {:ok, receipt :: String.t()} | error()

Utility function to send a message to a list of recipients on a host.

{:ok, _receipt} =
  easy_send(
    _host = "gmail.com",
    _sender = "mua@github.com",
    _recipients = ["support@gmail.com"],
    _message = "Date: Sat, 24 Jun 2023 13:43:57 +0000\r\n..."
  )
Link to this function

ehlo(socket, hostname, timeout \\ 30000)

View Source
@spec ehlo(socket(), String.t(), timeout()) :: {:ok, [String.t()]} | error()

Sends EHLO command which provides the identification of the sender i.e. the host name, and receives the list of extensions the server supports.

{:ok, _extensions = ["STARTTLS" | _rest]} = ehlo(socket, _our_hostname = "copycat.fun")
@spec guess_sender_hostname() :: {:ok, String.t()} | {:error, :inet.posix()}

Utility function to guess the local hostname to use for HELO/EHLO.

{:ok, "mac3"} = guess_sender_hostname()
Link to this function

helo(socket, hostname, timeout \\ 30000)

View Source
@spec helo(socket(), String.t(), timeout()) :: :ok | error()

Sends HELO command which provides the identification of the sender i.e. the host name.

:ok = helo(socket, _our_hostname = "copycat.fun")
Link to this function

mail_from(socket, address, timeout \\ 30000)

View Source
@spec mail_from(socket(), String.t(), timeout()) :: :ok | error()

Sends MAIL FROM command that specifies the originator of the mail.

:ok = mail_from(socket, "hey@copycat.fun")
@spec mxlookup(String.t()) :: [String.t()]

Utility function to lookup MX servers for a domain.

["gmail-smtp-in.l.google.com" | _rest] = mxlookup("gmail.com")
Link to this function

noop(socket, timeout \\ 30000)

View Source
@spec noop(socket(), timeout()) :: :ok | error()

Sends NOOP command that does nothing.

:ok = noop(socket)
Link to this function

pick_auth_method(extensions)

View Source
@spec pick_auth_method([String.t()]) :: auth_method() | nil

Utility function to pick a supported auth method from a list of extensions.

{:ok, extensions} = ehlo(socket, hostname)
maybe_method = pick_auth_method(extensions)
true = maybe_method in [nil, :plain, :login]
Link to this function

quit(socket, timeout \\ 30000)

View Source
@spec quit(socket(), timeout()) :: :ok | error()

Sends QUIT command that make the server close the connection.

:ok = quit(socket)
Link to this function

rcpt_to(socket, address, timeout \\ 30000)

View Source
@spec rcpt_to(socket(), String.t(), timeout()) :: :ok | error()

Sends RCPT TO command that specify the recipient of the mail.

:ok = rcpt_to(socket, "world@hey.com")
Link to this function

rset(socket, timeout \\ 30000)

View Source
@spec rset(socket(), timeout()) :: :ok | error()

Sends RSET command that aborts the current mail transaction but keeps the socket open.

:ok = rset(socket)
Link to this function

starttls(socket, address, opts \\ [], timeout \\ 30000)

View Source
@spec starttls(:gen_tcp.socket(), host(), transport_opts(), timeout()) ::
  {:ok, :ssl.sslsocket()} | error()

Sends STARTTLS extension command and starts TLS session negotiation.

{:ok, sslsocket} = starttls(socket, host, versions: [:"tlsv1.3"])
Link to this function

vrfy(socket, address, timeout \\ 30000)

View Source
@spec vrfy(socket(), String.t(), timeout()) :: {:ok, boolean()} | error()

Sends VRFY command that confirms or verifies the user name.

{:ok, true} = vrfy(socket, "dogaruslan@gmail.com")