go-smtp

repository·master·Indexed 24 days ago

https://github.com/emersion/go-smtp

A Go library providing ESMTP client and server implementations. Designed as a feature-complete alternative to net/smtp, it implements RFC 5321 and supports extensions such as AUTH (RFC 4954), PIPELINING (RFC 2920), UTF-8 support, and LMTP (RFC 2033). The library includes tools for implementing SMTP backends and sessions, handling SASL authentication, and managing secure connections via DialTLS and STARTTLS.

Tokens
3.9K
Snippets
10
Records
38
Agent score
84%

What's inside go-smtp

  1. Overview of go-smtp

    master

    go-smtp is an ESMTP client and server library written in Go. It implements [RFC 5321] and provides support for several SMTP extensions and protocols, including:

    • AUTH (RFC 4954)
    • PIPELINING (RFC 2920)
    • UTF-8 support for subjects and messages
    • LMTP (Local Mail Transfer Protocol, RFC 2033)
  2. Comparison between go-smtp and net/smtp

    master
    While the Go standard library includes a client implementation in net/smtp, that package is considered frozen and does not receive new features. go-smtp is intended as a more feature-rich alternative, providing a full server implementation and various client improvements over the standard library's offering.
  3. Understand EnhancedCode values

    master

    The EnhancedCode type is a [3]int used for RFC 6411 enhanced status codes. The library provides two special constants for managing these codes:

    • NoEnhancedCode: {-1, -1, -1}. Use this when you want to explicitly indicate that an enhanced code should not be included in a response. Note that RFC 2034 generally requires enhanced codes for 2xx, 4xx, and 5xx responses.
    • EnhancedCodeNotSet: {0, 0, 0}. Use this when a backend failed to provide an enhanced status code. In such cases, the server will typically use X.0.0 (where X is derived from the primary error code).
  4. Use the Client type for advanced SMTP transactions

    master

    If you need fine-grained control over the SMTP transaction (e.g., custom MAIL options, specific RCPT parameters, or manual DATA handling), use the Client type instead of the package-level SendMail functions.

    A typical manual transaction follows this sequence:

    1. Mail(from string, opts *MailOptions)
    2. One or more Rcpt(to string, opts *RcptOptions) calls.
    3. Data() to get a DataCommand writer.
    4. Close() the DataCommand writer to finish the transmission.
  5. Connect to an SMTP server using Dial functions

    master

    The smtp package provides several ways to establish a connection to an SMTP server depending on the required security level:

    • Plaintext: Use Dial(addr) to connect via a standard TCP connection. This does not enable TLS.
    • Implicit TLS: Use DialTLS(addr, tlsConfig) to connect to a server that expects TLS from the start (e.g., SMTPS on port 465).
    • STARTTLS: Use DialStartTLS(addr, tlsConfig) to connect via plaintext and then upgrade the connection to TLS using the STARTTLS command.

    All addr strings must include a port (e.g., mail.example.com:smtp). A nil tlsConfig is treated as an empty tls.Config.

  6. Configure Client timeouts and debugging

    master

    The Client struct provides fields to control network behavior:

    • CommandTimeout: The duration to wait for command responses (default is 5 minutes). This includes the 3xx reply to the DATA command.
    • SubmissionTimeout: The duration to wait for responses after the final dot in a DATA command (default is 12 minutes).
    • DebugWriter: An io.Writer used to log all network activity. Setting this allows you to inspect the raw SMTP traffic.
  7. Configure the SMTP Server settings

    master

    The Server struct provides several fields to customize the server's behavior, limits, and advertised capabilities.

    Network and Address

    • Network: The network type, either "tcp" or "unix".
    • Addr: The TCP or Unix address to listen on.
    • LMTP: Boolean to enable LMTP mode (RFC 2033), which uses the "unix" network.
    • TLSConfig: The *tls.Config for TLS connections.

    Limits and Timeouts

    • MaxRecipients: Maximum number of recipients allowed.
    • MaxMessageBytes: Maximum size of a message in bytes.
    • MaxLineLength: Maximum length of a single line (defaults to 2000).
    • ReadTimeout: Duration for read timeouts.
    • WriteTimeout: Duration for write timeouts.

    Capabilities (RFC Support)

    Set these to true to advertise support to clients, but only if your Backend implementation actually supports them:

    • EnableSMTPUTF8: RFC 6531
    • EnableREQUIRETLS: RFC 8689
    • EnableBINARYMIME: RFC 3030
    • EnableDSN: RFC 3461
    • EnableRRVS: RFC 7293
    • EnableDELIVERBY: RFC 2852 (requires MinimumDeliverByTime to be set)
    • EnableMTPRIORITY: RFC 6710 (requires MtPriorityProfile to be set)

    Logging and Debugging

    • Debug: An io.Writer for debug output.
    • ErrorLog: A Logger interface for reporting unexpected internal errors.
  8. Send a simple email with SendMail

    master

    For simple use cases, use the package-level SendMail or SendMailTLS functions. These functions handle the entire lifecycle: connecting, upgrading to TLS, authenticating (if a SASL client is provided), and sending the message.

    Note: The r parameter must be an RFC 822-style email containing headers first, followed by a blank line, and then the message body. All lines must be CRLF terminated. This package does not handle DKIM signing or MIME multipart construction.

  9. Implement LMTP support with LMTPSession

    master

    For Local Mail Transfer Protocol (LMTP) servers, implement the LMTPSession interface. This extends the standard Session with recipient-specific status reporting.

    • LMTPData(r io.Reader, status StatusCollector) error: The LMTP-specific version of the Data method. It uses a StatusCollector to provide per-recipient status information. The backend should call SetStatus once for each AddRcpt call. The return value of LMTPData serves as the status for recipients that did not receive an explicit status via the collector.
    type LMTPSession interface {
    	Session
    	LMTPData(r io.Reader, status StatusCollector) error
    }
    
    type StatusCollector interface {
    	SetStatus(rcptTo string, err error)
    }
  10. Access the SMTP connection and session

    master
    The Conn type represents an active SMTP/LMTP connection. You can retrieve the underlying net.Conn or the current Session associated with the connection. The Session is the primary interface for interacting with the mail transaction (e.g., Mail, Rcpt, Data).
  11. Check SMTP server extensions

    master

    Use Client.Extension(ext string) to check if the server supports a specific SMTP extension (e.g., AUTH, STARTTLS, SIZE, 8BITMIME). The method returns a boolean indicating support and a string containing any parameters associated with that extension.

    Additionally, use Client.SupportsAuth(mech string) to specifically check if a particular SASL mechanism is supported by the server.