### Install Mua Elixir Package Source: https://github.com/ruslandoga/mua/blob/master/README.md This snippet shows how to add the Mua package as a project dependency in Elixir's `mix.exs` file. It specifies the Mua version to be used. ```elixir defp deps do [ {:mua, "~> 0.2.0"} ] end ``` -------------------------------- ### Connect to SMTP Server with Mua Elixir Source: https://context7.com/ruslandoga/mua/llms.txt Establishes a connection to an SMTP server using TCP or SSL/TLS. It returns the socket and the initial server greeting. Supports various connection options including SSL versions, peer verification, IPv6, and timeouts. Includes examples for handling different connection errors like timeouts and refused connections. ```elixir # TCP connection (usually port 25 or 587) {:ok, socket, banner} = Mua.connect(:tcp, "smtp.gmail.com", 587) IO.puts("Server greeting: #{banner}") # Direct SSL connection (usually port 465) {:ok, ssl_socket, banner} = Mua.connect( :ssl, "smtp.gmail.com", 465, [versions: [:"tlsv1.3", :"tlsv1.2"], verify: :verify_peer], 30_000 ) # IPv6 support {:ok, socket, banner} = Mua.connect( :tcp, "smtp.example.com", 25, [inet6: true], 30_000 ) # Handle connection errors case Mua.connect(:tcp, "smtp.example.com", 587) do {:ok, socket, banner} -> IO.puts("Connected: #{banner}") {:error, %Mua.TransportError{reason: :timeout}} -> IO.puts("Connection timed out") {:error, %Mua.TransportError{reason: :econnrefused}} -> IO.puts("Connection refused") {:error, %Mua.SMTPError{code: code}} -> IO.puts("SMTP error on connect: #{code}") end ``` -------------------------------- ### EHLO Command with Mua Elixir Source: https://context7.com/ruslandoga/mua/llms.txt Sends the EHLO (Extended Hello) command to an SMTP server to identify the client and retrieve server capabilities. Returns a list of supported SMTP extensions. Useful for checking features like STARTTLS, 8BITMIME, and authentication methods. Provides examples of checking for specific extensions and parsing AUTH methods. ```elixir {:ok, socket, _banner} = Mua.connect(:tcp, "smtp.gmail.com", 587) {:ok, extensions} = Mua.ehlo(socket, "mydomain.com", 30_000) # Check for specific capabilities if "STARTTLS" in extensions do IO.puts("Server supports STARTTLS") end if "8BITMIME" in extensions do IO.puts("Server supports 8-bit MIME") end # Parse AUTH methods auth_ext = Enum.find(extensions, &String.starts_with?(&1, "AUTH ")) # Returns something like: "AUTH PLAIN LOGIN XOAUTH2" # Example extensions list: # [ # "SIZE 35882577", # "8BITMIME", # "STARTTLS", # "AUTH PLAIN LOGIN", # "ENHANCEDSTATUSCODES", # "PIPELINING", # "CHUNKING", # "SMTPUTF8" # ] ``` -------------------------------- ### Easy Send Email with Mua Elixir Source: https://context7.com/ruslandoga/mua/llms.txt High-level function to send emails through an SMTP relay or directly to a recipient's mail server. Handles connection, authentication, and message transmission. Supports various options like port, authentication credentials, timeout, and MX record lookup. Includes examples for successful sending and error handling for SMTP and transport errors. ```elixir message = "" Date: Mon, 25 Dec 2023 06:52:15 +0000\r\nFrom: Mua \r\nSubject: Welcome to Mua\r\nTo: Mr Receiver \r\nCC: Ms Receiver \r\n\r\nHello from Mua SMTP client!" {:ok, receipt} = Mua.easy_send( "smtp.gmail.com", "sender@gmail.com", ["receiver1@example.com", "receiver2@example.com"], message, port: 587, auth: [username: "sender@gmail.com", password: "app-password"], timeout: 30_000 ) # Direct send to recipient's mail server (requires SPF/DKIM setup) {:ok, receipt} = Mua.easy_send( "gmail.com", "sender@mydomain.com", ["support@gmail.com"], message, port: 25, mx: true # Lookup MX records for the domain ) # Error handling case Mua.easy_send(host, sender, recipients, message, opts) do {:ok, receipt} -> IO.puts("Email sent successfully: #{receipt}") {:error, %Mua.SMTPError{code: code, lines: lines}} -> IO.puts("SMTP error #{code}: #{IO.iodata_to_binary(lines)}") {:error, %Mua.TransportError{reason: reason}} -> IO.puts("Transport error: #{reason}") end ``` -------------------------------- ### Send Email Message Content (Mua Elixir) Source: https://context7.com/ruslandoga/mua/llms.txt Sends the actual email message content, including headers and body. The function automatically handles dot stuffing for lines starting with a dot. It returns a receipt string from the server upon successful transmission and includes error handling. ```elixir {:ok, socket, _banner} = Mua.connect(:tcp, "localhost", 1025) {:ok, _extensions} = Mua.ehlo(socket, "mydomain.com") :ok = Mua.mail_from(socket, "sender@mydomain.com") :ok = Mua.rcpt_to(socket, "recipient@example.com") message = """ Date: Mon, 25 Dec 2023 06:52:15 +0000\r From: Sender Name \r To: Recipient Name \r Subject: Test Message\r Content-Type: text/plain; charset=utf-8\r \r This is the message body. It can contain multiple lines. """ {:ok, receipt} = Mua.data(socket, message, 30_000) IO.puts("Message accepted: #{receipt}") # Dot stuffing is handled automatically message_with_dots = """ Date: Mon, 25 Dec 2023 06:52:15 +0000\r From: sender@test.com\r Subject: Dots\r \r Line starting with dot: .This will be automatically escaped ..This already escaped line is preserved """ {:ok, receipt} = Mua.data(socket, message_with_dots) ``` -------------------------------- ### Run Mailpit Docker Container Source: https://github.com/ruslandoga/mua/blob/master/README.md This console command demonstrates how to run Mailpit, a local SMTP server, using Docker. It maps the necessary ports and configures authentication to accept any credentials for testing purposes. ```bash $ docker run -d --rm -p 1025:1025 -p 8025:8025 -e "MP_SMTP_AUTH_ACCEPT_ANY=1" -e "MP_SMTP_AUTH_ALLOW_INSECURE=1" --name mailpit axllent/mailpit $ open http://localhost:8025 ``` -------------------------------- ### STARTTLS Upgrade with Mua Elixir Source: https://context7.com/ruslandoga/mua/llms.txt Upgrades an existing plain TCP connection to a secure TLS/SSL connection using the STARTTLS command. This is typically used with submission ports like 587. After upgrading, the EHLO command must be sent again, and then authentication can proceed over the secure channel. Includes options for TLS versions and verification. ```elixir {:ok, socket, _banner} = Mua.connect(:tcp, "smtp.gmail.com", 587) {:ok, extensions} = Mua.ehlo(socket, "mydomain.com") if "STARTTLS" in extensions do {:ok, ssl_socket} = Mua.starttls( socket, "smtp.gmail.com", [ versions: [:"tlsv1.3", :"tlsv1.2"], verify: :verify_peer, depth: 4 ], 30_000 ) # Must send EHLO again after STARTTLS {:ok, new_extensions} = Mua.ehlo(ssl_socket, "mydomain.com") # Now authenticate over secure connection :ok = Mua.auth(ssl_socket, :plain, username: "user@gmail.com", password: "app-password" ) end ``` -------------------------------- ### Complete Low-Level Workflow Source: https://context7.com/ruslandoga/mua/llms.txt Demonstrates a full, manual control over each SMTP command for maximum flexibility in email sending. ```APIDOC ## Complete Low-Level Workflow ### Description Full example showing manual control over each SMTP command for maximum flexibility. ### Method GET, POST (Implicit within Mua functions) ### Endpoint N/A (This is a sequence of commands over an established socket) ### Parameters None directly for the workflow, but individual commands like `connect`, `ehlo`, `auth`, `mail_from`, `rcpt_to`, and `data` take specific parameters. ### Request Example ```elixir # Connect to the server {:ok, socket, _banner} = Mua.connect(:tcp, "smtp.example.com", 587) # Perform EHLO handshake {:ok, extensions} = Mua.ehlo(socket, "example.com") # Authenticate (if required) auth_method = Mua.pick_auth_method(extensions) :ok = Mua.auth(socket, auth_method, [username: "user@example.com", password: "password"]) # Specify sender :ok = Mua.mail_from(socket, "sender@example.com") # Specify recipients :ok = Mua.rcpt_to(socket, "recipient1@example.com") :ok = Mua.rcpt_to(socket, "recipient2@example.com") # Prepare and send message content message = """ From: Sender \r To: Recipient1 \r Subject: Test Email\r \r This is the body of the email.\n""") {:ok, receipt} = Mua.data(socket, message) IO.puts("Message sent: #{receipt}") # Optionally send QUIT command :ok = Mua.quit(socket) ``` ### Response Responses vary based on the individual commands executed. Success is typically indicated by `:ok` or a server response string, while errors are returned as `{:error, %Mua.SMTPError{...}}`. ### Response Example (See individual command responses for detailed examples) ``` -------------------------------- ### Elixir: Utility SMTP Commands (VRFY, RSET, NOOP, QUIT) Source: https://context7.com/ruslandoga/mua/llms.txt This Elixir code demonstrates the usage of several utility SMTP commands provided by the Mua library. It covers connecting to a server, performing an EHLO, verifying recipient existence with `vrfy` (noting that many servers disable this), sending a no-operation command (`noop`) to keep the connection alive, resetting a mail transaction with `rset`, and gracefully closing the connection with `quit` and `close`. ```elixir {:ok, socket, _banner} = Mua.connect(:tcp, "localhost", 1025) {:ok, _extensions} = Mua.ehlo(socket, "mydomain.com") # Verify if a recipient exists (many servers disable this) {:ok, exists?} = Mua.vrfy(socket, "user@example.com") if exists?, do: IO.puts("Recipient verified") # Send no-operation (keep connection alive) :ok = Mua.noop(socket) # Reset current mail transaction without closing :ok = Mua.mail_from(socket, "sender@test.com") :ok = Mua.rcpt_to(socket, "wrong@test.com") :ok = Mua.rset(socket) # Cancel the above transaction # Start a new transaction on the same socket :ok = Mua.mail_from(socket, "sender@test.com") :ok = Mua.rcpt_to(socket, "correct@test.com") {:ok, receipt} = Mua.data(socket, message) # Gracefully close connection :ok = Mua.quit(socket) :ok = Mua.close(socket) ``` -------------------------------- ### Elixir: Complete Email Sending Workflow with Error Handling Source: https://context7.com/ruslandoga/mua/llms.txt This snippet demonstrates a full email sending process using Elixir and the Mua library. It includes connecting to an SMTP server, identifying the client, upgrading to TLS if available, authenticating, sending the email envelope and message, and gracefully closing the connection. Error handling is managed using a try-after block to ensure the socket is closed. ```elixir defmodule EmailSender do def send_email(host, port, from, to_list, message_body) do # 1. Connect {:ok, socket, banner} = Mua.connect(:tcp, host, port) IO.puts("Connected: #{banner}") try do # 2. Identify ourselves [_, domain] = String.split(from, "@") {:ok, extensions} = Mua.ehlo(socket, domain) IO.puts("Extensions: #{inspect(extensions)}") # 3. Upgrade to TLS if available socket = if "STARTTLS" in extensions do {:ok, ssl_socket} = Mua.starttls(socket, host) {:ok, _new_ext} = Mua.ehlo(ssl_socket, domain) ssl_socket else socket end # 4. Authenticate if required if auth_method = Mua.pick_auth_method(extensions) do :ok = Mua.auth( socket, auth_method, [username: from, password: System.get_env("SMTP_PASSWORD")] ) IO.puts("Authenticated") end # 5. Send envelope :ok = Mua.mail_from(socket, from) for recipient <- to_list do :ok = Mua.rcpt_to(socket, recipient) end # 6. Send message {:ok, receipt} = Mua.data(socket, message_body) # 7. Close gracefully :ok = Mua.quit(socket) {:ok, receipt} after Mua.close(socket) end end end # Usage {:ok, receipt} = EmailSender.send_email( "smtp.gmail.com", 587, "sender@gmail.com", ["recipient1@example.com", "recipient2@example.com"], """ Date: #{DateTime.utc_now() |> DateTime.to_string()}\r From: sender@gmail.com\r To: recipient1@example.com, recipient2@example.com\r Subject: Test Email\r \r This is a test email sent via Mua. """ ) ``` -------------------------------- ### Elixir: MX Lookup for Mail Servers Source: https://context7.com/ruslandoga/mua/llms.txt This code snippet shows how to use the Mua library in Elixir to perform MX (Mail Exchanger) lookups for a given domain. It demonstrates finding mail servers and then attempting to send an email by iterating through the discovered MX records, falling back to backup servers if the primary fails. It also shows how to use the `mx: true` option with `easy_send` for automatic MX lookup. ```elixir # Find Gmail's mail servers mx_servers = Mua.mxlookup("gmail.com") # Returns: ["gmail-smtp-in.l.google.com", "alt1.gmail-smtp-in.l.google.com", ...] # Try sending to each MX server in order [primary_mx | backup_mx] = Mua.mxlookup("example.com") case Mua.easy_send(primary_mx, sender, recipients, message, port: 25) do {:ok, receipt} -> {:ok, receipt} {:error, _} -> # Try backup servers Enum.find_value(backup_mx, fn mx_host -> case Mua.easy_send(mx_host, sender, recipients, message, port: 25) do {:ok, receipt} -> {:ok, receipt} {:error, _} -> nil end end) end # Use with easy_send {:ok, receipt} = Mua.easy_send( "gmail.com", "sender@mydomain.com", ["user@gmail.com"], message, mx: true, # Automatically lookup and try MX servers port: 25 ) ``` -------------------------------- ### Send Email with Mua Low-Level API Source: https://github.com/ruslandoga/mua/blob/master/README.md This Elixir code demonstrates Mua's low-level API for sending an email. It establishes a TCP connection, performs EHLO, handles STARTTLS if available, authenticates, and then sends the mail command with the message data, finally closing the connection. ```elixir {:ok, socket, _banner} = Mua.connect(:tcp, "localhost", _port = 1025) {:ok, extensions} = Mua.ehlo(socket, _sending_domain = "github.com") {:ok, socket} = if "STARTTLS" in extensions do Mua.starttls(socket, "localhost") else {:ok, socket} end :plain = Mua.pick_auth_method(extensions) :ok = Mua.auth(socket, :plain, username: "username", password: "password") :ok = Mua.mail_from(socket, "mua@github.com") :ok = Mua.rcpt_to(socket, "receiver@mailpit.example") message = """ Date: Mon, 25 Dec 2023 06:52:15 +0000\r From: Mua \r Subject: How was your day?\r To: Mr Receiver \r \r Mine was fine. """ {:ok, _receipt} = Mua.data(socket, message) :ok = Mua.close(socket) ``` -------------------------------- ### Authentication - AUTH Command Source: https://context7.com/ruslandoga/mua/llms.txt Authenticate with the SMTP server using PLAIN or LOGIN methods. This is required by most relay servers before allowing message transmission. ```APIDOC ## AUTH Command ### Description Authenticate with the SMTP server using PLAIN or LOGIN methods. Required by most relay servers before allowing message transmission. ### Method POST (Implicit within Mua.auth) ### Endpoint N/A (This is a command sent over an established socket) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body `Mua.auth(socket, method, credentials, timeout)` - **socket** (pid) - The socket connection to the SMTP server. - **method** (:plain | :login) - The authentication method to use. - **credentials** (map) - A map containing `username` and `password`. - **timeout** (integer) - Optional timeout in milliseconds for the operation. ### Request Example ```elixir # PLAIN authentication :ok = Mua.auth(socket, :plain, [username: "user@gmail.com", password: "app-password"], 30_000) # LOGIN authentication :ok = Mua.auth(socket, :login, [username: "user@example.com", password: "secret"], 30_000) ``` ### Response #### Success Response (200 OK) - **:ok** - Indicates successful authentication. #### Error Response - **{:error, %Mua.SMTPError{code: 535}}** - Invalid credentials. - **{:error, %Mua.SMTPError{code: 534}}** - Authentication mechanism not supported. #### Response Example ```elixir case Mua.auth(socket, :plain, username: user, password: pass) do :ok -> IO.puts("Authentication successful") {:error, %Mua.SMTPError{code: 535}} -> IO.puts("Invalid credentials") end ``` ``` -------------------------------- ### MAIL FROM - Specify Sender Source: https://context7.com/ruslandoga/mua/llms.txt Specify the email address of the sender. This command must be called before any RCPT TO commands. ```APIDOC ## MAIL FROM Command ### Description Specify the email address of the sender. This must be called before RCPT TO. ### Method POST (Implicit within Mua.mail_from) ### Endpoint N/A (This is a command sent over an established socket) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body `Mua.mail_from(socket, sender_address, timeout)` - **socket** (pid) - The socket connection to the SMTP server. - **sender_address** (string) - The email address of the sender. Angle brackets are optional and will be added if missing. - **timeout** (integer) - Optional timeout in milliseconds for the operation. ### Request Example ```elixir :ok = Mua.mail_from(socket, "sender@mydomain.com", 30_000) # With angle brackets (automatically added if not present) :ok = Mua.mail_from(socket, "") ``` ### Response #### Success Response (250 OK) - **:ok** - Indicates the sender address was accepted. #### Error Response - **{:error, %Mua.SMTPError{code: 553}}** - Sender address not allowed. - **{:error, %Mua.SMTPError{code: 501}}** - Syntax error in sender address. #### Response Example ```elixir case Mua.mail_from(socket, "invalid@domain") do :ok -> :ok {:error, %Mua.SMTPError{code: 553}} -> IO.puts("Sender address not allowed") end ``` ``` -------------------------------- ### Authenticate with SMTP Server (Mua Elixir) Source: https://context7.com/ruslandoga/mua/llms.txt Authenticates with the SMTP server using PLAIN or LOGIN methods. This is a prerequisite for most relay servers before message transmission. It supports automatic selection of supported authentication methods and handles specific authentication errors. ```elixir {:ok, socket, _banner} = Mua.connect(:tcp, "smtp.gmail.com", 587) {:ok, extensions} = Mua.ehlo(socket, "gmail.com") # Automatically pick supported auth method auth_method = Mua.pick_auth_method(extensions) # Returns :plain, :login, or nil # PLAIN authentication (most common) :ok = Mua.auth( socket, :plain, [username: "user@gmail.com", password: "app-password"], 30_000 ) # LOGIN authentication :ok = Mua.auth( socket, :login, [username: "user@example.com", password: "secret"], 30_000 ) # Handle auth errors case Mua.auth(socket, :plain, username: user, password: pass) do :ok -> IO.puts("Authentication successful") {:error, %Mua.SMTPError{code: 535}} -> IO.puts("Invalid credentials") {:error, %Mua.SMTPError{code: 534}} -> IO.puts("Authentication mechanism not supported") end ``` -------------------------------- ### Implement Retry Logic with Exponential Backoff in Elixir Source: https://context7.com/ruslandoga/mua/llms.txt This Elixir module, Mailer, demonstrates how to implement email sending with automatic retries using exponential backoff. The `send_with_retry` function manages attempts, and the private `send_attempt` function recursively calls itself with increasing delays upon encountering specific retryable SMTP errors (4xx codes). It limits retries to a maximum number of attempts. ```elixir # Retry logic with exponential backoff defmodule Mailer do def send_with_retry(host, from, to, message, opts, max_attempts \ 3) do send_attempt(host, from, to, message, opts, 1, max_attempts) end defp send_attempt(host, from, to, message, opts, attempt, max_attempts) do case Mua.easy_send(host, from, to, message, opts) do {:ok, receipt} = success -> success {:error, %Mua.SMTPError{code: code}} when code in [421, 450, 451, 452] -> if attempt < max_attempts do backoff = :math.pow(2, attempt) * 1000 |> round() Process.sleep(backoff) send_attempt(host, from, to, message, opts, attempt + 1, max_attempts) else {:error, :max_retries_exceeded} end {:error, _} = error -> error end end end ``` -------------------------------- ### DATA - Send Message Content Source: https://context7.com/ruslandoga/mua/llms.txt Send the actual email message content, including headers and body. The server will acknowledge receipt. ```APIDOC ## DATA Command ### Description Send the actual email message content. The message should be properly formatted with headers and body separated by a blank line. Returns a receipt string from the server. ### Method POST (Implicit within Mua.data) ### Endpoint N/A (This is a command sent over an established socket) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body `Mua.data(socket, message, timeout)` - **socket** (pid) - The socket connection to the SMTP server. - **message** (string) - The complete email message, including headers and body, with CRLF line endings. - **timeout** (integer) - Optional timeout in milliseconds for the operation. ### Request Example ```elixir message = """ Date: Mon, 25 Dec 2023 06:52:15 +0000\r From: Sender Name \r To: Recipient Name \r Subject: Test Message\r Content-Type: text/plain; charset=utf-8\r \r This is the message body.\nIt can contain multiple lines.\n" {:ok, receipt} = Mua.data(socket, message, 30_000) IO.puts("Message accepted: #{receipt}") ``` ### Response #### Success Response (250 OK) - **{:ok, receipt_string}** - A string indicating the server accepted the message. #### Response Example ```elixir # Example of successful response {:ok, "250 2.0.0 Ok: queued as abcdef12345"} # Dot stuffing is handled automatically message_with_dots = """ Date: Mon, 25 Dec 2023 06:52:15 +0000\r From: sender@test.com\r Subject: Dots\r \r Line starting with dot:\n.This will be automatically escaped\n..This already escaped line is preserved\n" {:ok, receipt} = Mua.data(socket, message_with_dots) ``` ``` -------------------------------- ### Send Email with Mua High-Level API Source: https://github.com/ruslandoga/mua/blob/master/README.md This Elixir code uses Mua's high-level API to send an email. It constructs a raw email message and calls `Mua.easy_send` with server details, sender, recipients, and optional authentication. ```elixir message = """ Date: Mon, 25 Dec 2023 06:52:15 +0000\r From: Mua \r Subject: README\r To: Mr Receiver \r CC: Ms Receiver \r \r like and subscribe """ {:ok, _receipt} = Mua.easy_send( _host = "localhost", _mail_from = "mua@github.com", _rcpt_to = ["receiver1@mailpit.example", "receiver2@mailpit.example"], message, port: 1025, auth: [username: "username", password: "password"] ) ``` -------------------------------- ### RCPT TO - Specify Recipients Source: https://context7.com/ruslandoga/mua/llms.txt Specify one or more recipient email addresses for the email. This command can be called multiple times to add multiple recipients. ```APIDOC ## RCPT TO Command ### Description Specify one or more recipient email addresses. Can be called multiple times for multiple recipients. ### Method POST (Implicit within Mua.rcpt_to) ### Endpoint N/A (This is a command sent over an established socket) ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body `Mua.rcpt_to(socket, recipient_address, timeout)` - **socket** (pid) - The socket connection to the SMTP server. - **recipient_address** (string) - The email address of the recipient. - **timeout** (integer) - Optional timeout in milliseconds for the operation. ### Request Example ```elixir :ok = Mua.rcpt_to(socket, "recipient1@example.com", 30_000) :ok = Mua.rcpt_to(socket, "recipient2@example.com", 30_000) ``` ### Response #### Success Response (250 OK) - **:ok** - Indicates the recipient address was accepted. #### Error Response - **{:error, %Mua.SMTPError{code: 550}}** - Recipient mailbox unavailable. - **{:error, %Mua.SMTPError{code: 551}}** - User not local, relay denied. - **{:error, %Mua.SMTPError{code: 552}}** - Mailbox full. #### Response Example ```elixir case Mua.rcpt_to(socket, "user@example.com") do :ok -> :ok {:error, %Mua.SMTPError{code: 550}} -> IO.puts("Recipient mailbox unavailable") end ``` ``` -------------------------------- ### Specify Sender Email Address (Mua Elixir) Source: https://context7.com/ruslandoga/mua/llms.txt Specifies the email address of the sender. This command must be issued before any RCPT TO commands. The function automatically adds angle brackets if they are not provided. Error handling for common SMTP error codes is included. ```elixir {:ok, socket, _banner} = Mua.connect(:tcp, "localhost", 1025) {:ok, _extensions} = Mua.ehlo(socket, "mydomain.com") :ok = Mua.mail_from(socket, "sender@mydomain.com", 30_000) # With angle brackets (automatically added if not present) :ok = Mua.mail_from(socket, "") # Handle errors case Mua.mail_from(socket, "invalid@domain") do :ok -> :ok {:error, %Mua.SMTPError{code: 553}} -> IO.puts("Sender address not allowed") {:error, %Mua.SMTPError{code: 501}} -> IO.puts("Syntax error in sender address") end ``` -------------------------------- ### Handle SMTP and Transport Errors in Elixir Source: https://context7.com/ruslandoga/mua/llms.txt This Elixir module, EmailHandler, provides a function to process the results of email sending operations. It distinguishes between SMTP protocol errors (e.g., 4xx and 5xx codes) and transport-level failures (e.g., timeouts, connection errors), returning specific retry or error messages. This helps in implementing robust error recovery strategies. ```elixir defmodule EmailHandler do def handle_send_result(result) do case result do {:ok, receipt} -> {:ok, receipt} # SMTP protocol errors {:error, %Mua.SMTPError{code: 421}} -> {:retry, "Service not available, try later"} {:error, %Mua.SMTPError{code: 450}} -> {:retry, "Mailbox unavailable temporarily"} {:error, %Mua.SMTPError{code: 451}} -> {:retry, "Action aborted, error in processing"} {:error, %Mua.SMTPError{code: 452}} -> {:retry, "Insufficient system storage"} {:error, %Mua.SMTPError{code: 500}} -> {:error, "Syntax error, command unrecognized"} {:error, %Mua.SMTPError{code: 535}} -> {:error, "Authentication failed"} {:error, %Mua.SMTPError{code: 550}} -> {:error, "Mailbox unavailable (not found or rejected)"} # Transport errors {:error, %Mua.TransportError{reason: :timeout}} -> {:retry, "Connection timeout"} {:error, %Mua.TransportError{reason: :closed}} -> {:retry, "Connection closed unexpectedly"} {:error, %Mua.TransportError{reason: :econnrefused}} -> {:error, "Connection refused"} {:error, %Mua.TransportError{reason: :nxdomain}} -> {:error, "Domain does not exist"} {:error, error} -> {:error, "Unknown error: #{inspect(error)}"} end end end ``` -------------------------------- ### Specify Recipient Email Addresses (Mua Elixir) Source: https://context7.com/ruslandoga/mua/llms.txt Specifies one or more recipient email addresses for the email. This function can be called multiple times to add several recipients. It includes error handling for common SMTP error codes related to recipients. ```elixir {:ok, socket, _banner} = Mua.connect(:tcp, "localhost", 1025) {:ok, _extensions} = Mua.ehlo(socket, "mydomain.com") :ok = Mua.mail_from(socket, "sender@mydomain.com") # Add multiple recipients :ok = Mua.rcpt_to(socket, "recipient1@example.com", 30_000) :ok = Mua.rcpt_to(socket, "recipient2@example.com", 30_000) :ok = Mua.rcpt_to(socket, "recipient3@example.com", 30_000) # Handle recipient errors case Mua.rcpt_to(socket, "user@example.com") do :ok -> :ok {:error, %Mua.SMTPError{code: 550}} -> IO.puts("Recipient mailbox unavailable") {:error, %Mua.SMTPError{code: 551}} -> IO.puts("User not local, relay denied") {:error, %Mua.SMTPError{code: 552}} -> IO.puts("Mailbox full") end ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.