### Example Backend Implementation Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md An example implementation of the Backend interface. This struct holds a database connection and creates a new MySession for each incoming client connection, passing the client's hostname. ```go type MyBackend struct { db *Database } func (b *MyBackend) NewSession(c *smtp.Conn) (smtp.Session, error) { hostname := c.Hostname() session := &MySession{ db: b.db, clientHostname: hostname, } return session, nil } ``` -------------------------------- ### Build Connection with STARTTLS Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/README.md Example of establishing a client connection and upgrading it to TLS using STARTTLS. ```go conn, err := smtp.Dial(ctx, "smtp.example.com:25") if err != nil { log.Fatal(err) } client, err := conn.StartTLS(nil) if err != nil { log.Fatal(err) } ``` -------------------------------- ### Implement Session Data Method Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md Example implementation for the Data method, which receives the message content and processes it. This example reads all data and attempts to store the message for each recipient. ```go func (s *MySession) Data(r io.Reader) error { data, err := io.ReadAll(r) if err != nil { return err } // Try to deliver to all recipients for _, to := range s.recipients { if err := s.db.StoreMessage(s.from, to, data); err != nil { return fmt.Errorf("delivery failed: %w", err) } } return nil } ``` -------------------------------- ### Full Server Configuration Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/MANIFEST.txt Configure a comprehensive SMTP server with various options. This example demonstrates setting up network, TLS, limits, and extensions. ```go server := &smtp.Server{ Addr: ":25", Domain: "example.com", MaxMessageBytes: 10 * 1024 * 1024, // 10MB MaxRecipients: 100, MaxLineLength: 4096, AllowInsecureAuth: false, TLSConfig: &tls.Config{ Certificates: []tls.Certificate{cert}, }, Handler: &MyBackend{}, // ... other configuration options } go.ListenAndServe(server.Addr, server) ``` -------------------------------- ### Auth Implementation Example Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md Example of implementing the Auth method to handle SASL authentication. This implementation supports the PLAIN mechanism and authenticates users against a database. ```go func (s *MySession) Auth(mech string) (sasl.Server, error) { if mech != sasl.Plain { return nil, smtp.ErrAuthUnknownMechanism } return sasl.NewPlainServer(func(identity, username, password string) error { user, err := s.db.AuthenticateUser(username, password) if err != nil { return err } s.authenticatedUser = user return nil }), nil } ``` -------------------------------- ### Start Server and Listen for Connections Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/server.md Starts the SMTP server, making it listen on the configured address and accept incoming client connections. This method blocks until the server is shut down. Ensure the server address is correctly configured before calling. ```go server := smtp.NewServer(backend) server.Addr = "localhost:1025" log.Fatal(server.ListenAndServe()) ``` -------------------------------- ### Send Email with Custom Options Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/INDEX.md Send an email with custom options like UTF8 support and message size limits. This example demonstrates starting a TLS connection and authenticating. ```go client, _ := smtp.DialStartTLS("mail.example.com:25", nil) defer client.Close() client.Auth(sasl.NewPlainClient("", "user", "pass")) opts := &smtp.MailOptions{UTF8: true, Size: 1024000} client.Mail("from@example.com", opts) client.Rcpt("to@example.com", nil) writer, _ := client.Data() io.Copy(writer, messageReader) writer.Close() ``` -------------------------------- ### Quick Start: SMTP Server Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/INDEX.md Implement a basic SMTP server by defining a backend and session handlers. The server listens on the specified address. ```go type MyBackend struct{} func (b *MyBackend) NewSession(c *smtp.Conn) (smtp.Session, error) { return &MySession{}, nil } type MySession struct{} func (s *MySession) Mail(from string, opts *smtp.MailOptions) error { return nil } func (s *MySession) Rcpt(to string, opts *smtp.RcptOptions) error { return nil } func (s *MySession) Data(r io.Reader) error { io.ReadAll(r) return nil } func (s *MySession) Reset() {} func (s *MySession) Logout() error { return nil } server := smtp.NewServer(&MyBackend{}) server.Addr = ":1025" log.Fatal(server.ListenAndServe()) ``` -------------------------------- ### Full-Featured Server Configuration Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/MANIFEST.txt Set up a highly configurable SMTP server with numerous options. This example covers advanced settings for production environments. ```go server := &smtp.Server{ Addr: ":25", Domain: "mail.example.com", MaxMessageBytes: 20 * 1024 * 1024, // 20MB MaxRecipients: 200, MaxLineLength: 8192, ReadTimeout: 5 * time.Minute, WriteTimeout: 5 * time.Minute, DebugWriter: os.Stdout, Handler: &AuthBackend{}, TLSConfig: &tls.Config{ Certificates: []tls.Certificate{cert}, }, // ESMTP extensions configuration... } go.ListenAndServe(server.Addr, server) ``` -------------------------------- ### Using BackendFunc as a Backend Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/server.md Demonstrates how to create a BackendFunc and use it to initialize a new SMTP server. This example shows a basic implementation that always returns a new MySession. ```go backend := smtp.BackendFunc(func(c *smtp.Conn) (smtp.Session, error) { return &MySession{}, nil }) server := smtp.NewServer(backend) ``` -------------------------------- ### Usage of RcptOptions with Client.Rcpt Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/types.md Example demonstrating how to set up and use RcptOptions when calling Client.Rcpt to specify delivery status notifications and message priority. ```go opts := &smtp.RcptOptions{ Notify: []smtp.DSNNotify{smtp.DSNNotifyFailure, smtp.DSNNotifySuccess}, MTPriority: &priority, // where priority is an int between -9 and 9 } if err := client.Rcpt("recipient@example.com", opts); err != nil { log.Fatal(err) } ``` -------------------------------- ### Start Server with TLS Encryption Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/server.md Starts the SMTP server with TLS enabled, securing all connections from the outset. Requires a valid TLS configuration, including certificates. Use this for secure email transport. ```go cert, _ := tls.LoadX509KeyPair("cert.pem", "key.pem") tlsConfig := &tls.Config{Certificates: []tls.Certificate{cert}} server := smtp.NewServer(backend) server.TLSConfig = tlsConfig log.Fatal(server.ListenAndServeTLS()) ``` -------------------------------- ### Build SMTP Server Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/QUICK-REFERENCE.md Implement a custom SMTP server by defining backend and session handlers. This example shows the basic structure for accepting mail. ```go type MyBackend struct{} func (b *MyBackend) NewSession(c *smtp.Conn) (smtp.Session, error) { return &MySession{}, nil } type MySession struct{} func (s *MySession) Mail(from string, opts *smtp.MailOptions) error { return nil // Accept sender } func (s *MySession) Rcpt(to string, opts *smtp.RcptOptions) error { return nil // Accept recipient } func (s *MySession) Data(r io.Reader) error { data, _ := io.ReadAll(r) return nil // Accept message } func (s *MySession) Reset() {} func (s *MySession) Logout() error { return nil } server := smtp.NewServer(&MyBackend{}) server.Addr = ":25" log.Fatal(server.ListenAndServe()) ``` -------------------------------- ### AuthMechanisms Implementation Example Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md Example of implementing the AuthMechanisms method to return a list of supported SASL authentication mechanisms. This example supports PLAIN and LOGIN. ```go func (s *MySession) AuthMechanisms() []string { return []string{sasl.Plain, sasl.Login} } ``` -------------------------------- ### Quick Start: SMTP Client Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/INDEX.md Connect to an SMTP server, send mail, and close the connection. Ensure the server address and port are correct. ```go client, _ := smtp.Dial("mail.example.com:25") defer client.Close() client.Mail("from@example.com", nil) client.Rcpt("to@example.com", nil) writer, _ := client.Data() fmt.Fprintf(writer, "To: to@example.com\r\nSubject: Test\r\n\r\nBody") writer.Close() client.Quit() ``` -------------------------------- ### ListenAndServe Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/server.md Starts the server, listening on the configured address and accepting connections. Blocks until the server is closed. ```APIDOC ## ListenAndServe ### Description Starts the server, listening on the configured address and accepting connections. Blocks until the server is closed. ### Return - `error`: Network error (failed to listen or serve) ### Behavior - If Addr is blank and LMTP is disabled, defaults to ":smtp" (port 25) - If LMTP is enabled, defaults to unix socket - Calls Serve internally with the listener ### Request Example ```go server := smtp.NewServer(backend) server.Addr = "localhost:1025" log.Fatal(server.ListenAndServe()) ``` ``` -------------------------------- ### SMTP Client STARTTLS Setup Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/QUICK-REFERENCE.md Initiate a STARTTLS handshake on an existing SMTP connection to upgrade to a secure TLS connection. Use this for servers that support STARTTLS on standard ports like 25 or 587. ```go client, _ := smtp.Dial("mail.example.com:25") // Server initially plaintext // Client can call STARTTLS to upgrade ``` -------------------------------- ### LMTPData Implementation Example Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md Example of implementing the LMTPData method to handle per-recipient delivery status reporting during LMTP sessions. Ensure SetStatus is called for each recipient before LMTPData returns. ```go func (s *MyLMTPSession) LMTPData(r io.Reader, status smtp.StatusCollector) error { data, _ := io.ReadAll(r) for _, to := range s.recipients { err := s.db.StoreMessage(s.from, to, data) status.SetStatus(to, err) // Per-recipient status } return nil // Return value unused if all recipients have status } ``` -------------------------------- ### Write Email Message with Headers and Body Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/data-command.md Example demonstrating how to use the Write method (via fmt.Fprintf) to send email headers, a blank line separator, and the message body. Also shows using io.Copy for larger messages. ```go writer, _ := client.Data() defer writer.Close() // Write headers fmt.Fprintf(writer, "From: sender@example.com\r\n") fmt.Fprintf(writer, "To: recipient@example.com\r\n") fmt.Fprintf(writer, "Subject: Test\r\n") // Write blank line separator fmt.Fprintf(writer, "\r\n") // Write body fmt.Fprintf(writer, "This is the message body.\r\n") // Can also use io.Copy with proper CRLF handling io.Copy(writer, messageReader) ``` -------------------------------- ### Set RcptOptions with DeliverByOptions Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/types.md Example of setting recipient options with delivery by deadline, specifying time, mode, and trace. ```go opts := &smtp.RcptOptions{ DeliverBy: &smtp.DeliverByOptions{ Time: 24 * time.Hour, Mode: smtp.DeliverByReturn, Trace: true, }, } client.Rcpt("recipient@example.com", opts) ``` -------------------------------- ### Implement Custom Logger Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/types.md Example implementation of the Logger interface for custom error logging with the server. ```go type MyLogger struct{} func (l *MyLogger) Printf(format string, v ...interface{}) { log.Printf(format, v...) } func (l *MyLogger) Println(v ...interface{}) { log.Println(v...) } server.ErrorLog = &MyLogger{} ``` -------------------------------- ### Send Email via SendMail Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/README.md A concise example for sending an email using the SendMail function. ```go client.SendMail(ctx, "sender@example.com", []string{"recipient@example.com"}, bytes.NewReader([]byte("Subject: Test\n\nHello World"))) ``` -------------------------------- ### Configure SMTP Server Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/INDEX.md Configure and start an SMTP server with various options including address, domain, message limits, TLS, DSN, and timeouts. This snippet shows how to set up the server instance. ```go server := smtp.NewServer(&MyBackend{}) server.Addr = "mail.example.com:25" server.Domain = "example.com" server.MaxMessageBytes = 1024 * 1024 * 50 server.MaxRecipients = 500 server.TLSConfig = tlsConfig server.EnableSMTPUTF8 = true server.EnableDSN = true server.ReadTimeout = 30 * time.Second server.WriteTimeout = 30 * time.Second log.Fatal(server.ListenAndServe()) ``` -------------------------------- ### ListenAndServeTLS Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/server.md Starts the server with TLS, listening on the configured address. Blocks until the server is closed. Requires TLSConfig to be set. ```APIDOC ## ListenAndServeTLS ### Description Starts the server with TLS, listening on the configured address. Blocks until the server is closed. Requires TLSConfig to be set. ### Return - `error`: Network or TLS error ### Behavior - If Addr is blank and LMTP is disabled, defaults to ":smtps" (port 465) - If LMTP is enabled, uses unix socket - Requires TLSConfig to be set (returns error if nil) - All connections are TLS-encrypted from the start ### Request Example ```go cert, _ := tls.LoadX509KeyPair("cert.pem", "key.pem") tlsConfig := &tls.Config{Certificates: []tls.Certificate{cert}} server := smtp.NewServer(backend) server.TLSConfig = tlsConfig log.Fatal(server.ListenAndServeTLS()) ``` ``` -------------------------------- ### Client.Mail Usage with MailOptions Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/types.md Example of using MailOptions with Client.Mail to specify UTF-8 support, message size, and TLS requirement for sending an email. ```go opts := &smtp.MailOptions{ UTF8: true, Size: messageSize, RequireTLS: true, } if err := client.Mail("sender@example.com", opts); err != nil { log.Fatal(err) } ``` -------------------------------- ### Send Simple Email Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/MANIFEST.txt Send a simple email using the go-smtp client. This is a basic example for sending a single email. ```go client.SendMail(ctx, "sender@example.com", []string{"recipient@example.com"}, bytes.NewBufferString("Subject: Test\n\nHello World")) ``` -------------------------------- ### Send Message Using io.Copy Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/data-command.md This example shows how to efficiently send message content from an io.Reader directly to the SMTP server using io.Copy. ```go writer, _ := client.Data() defer writer.Close() // messageReader is an io.Reader with RFC 822 formatted message // (headers with CRLF line endings, blank line, then body) io.Copy(writer, messageReader) ``` -------------------------------- ### Implement Session Mail Method Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md Example implementation for the Mail method, which sets the sender (return path) for an email transaction. It includes basic validation for the email address and stores message size. ```go func (s *MySession) Mail(from string, opts *smtp.MailOptions) error { if !isValidEmail(from) { return smtp.ErrAuthRequired } s.from = from s.messageSize = opts.Size return nil } ``` -------------------------------- ### Session.Mail Usage with MailOptions Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/types.md Example of a custom Session.Mail implementation that checks for TLS requirement when MailOptions are provided. ```go func (s *MySession) Mail(from string, opts *smtp.MailOptions) error { if opts != nil && opts.RequireTLS { // Verify TLS is active if state, ok := s.conn.TLSConnectionState(); !ok { return smtp.ErrAuthRequired } } return nil } ``` -------------------------------- ### SMTP Client Implicit TLS Setup Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/QUICK-REFERENCE.md Establish an immediate TLS connection using Implicit TLS. This is suitable for servers that expect TLS from the very beginning of the connection, typically on port 465. ```go client, _ := smtp.DialTLS("mail.example.com:465", nil) // Connection TLS from start ``` -------------------------------- ### Example Usage of SetStatus Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md Demonstrates how to use the SetStatus method to report success or failure for each recipient during email delivery. This pattern ensures that each recipient's status is correctly recorded. ```go for _, to := range recipients { if err := deliverTo(to); err != nil { status.SetStatus(to, err) } else { status.SetStatus(to, nil) } } ``` -------------------------------- ### Implement Session Logout Method Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md Example implementation for the Logout method, responsible for freeing session resources like database connections. This is the final method called on a session. ```go func (s *MySession) Logout() error { if s.db != nil { return s.db.Close() } return nil } ``` -------------------------------- ### Implement Session Rcpt Method Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md Example implementation for the Rcpt method, which adds a recipient to the current email transaction. It includes validation for the recipient address and appends it to a list. ```go func (s *MySession) Rcpt(to string, opts *smtp.RcptOptions) error { if !isValidRecipient(to, s.from) { return &smtp.SMTPError{ Code: 550, EnhancedCode: smtp.EnhancedCode{5, 1, 1}, Message: "User not found", } } s.recipients = append(s.recipients, to) return nil } ``` -------------------------------- ### Example: Using SubmissionTimeout with a Slow Server Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/data-command.md Demonstrates setting a custom SubmissionTimeout for a slow SMTP server and sending a message. The writer.Close() operation may take up to the specified timeout duration. ```go client, _ := smtp.Dial("slowserver.example.com:25") client.SubmissionTimeout = 30 * time.Minute // Slow server writer, _ := client.Data() fmt.Fprintf(writer, "Subject: Test\r\n\r\nLarge body") writer.Close() // May take up to 30 minutes ``` -------------------------------- ### Configure and Create Server Instance Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/server.md Demonstrates creating a new server instance and then customizing its address and maximum message size. Use this to set specific operational limits for your server. ```go backend := &MyBackend{} server := smtp.NewServer(backend) server.Addr = "localhost:1025" server.MaxMessageBytes = 1024 * 1024 // 1MB limit ``` -------------------------------- ### Close Data Command and Retrieve SMTP Response Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/data-command.md Example of using CloseWithResponse to get the server's status text after sending an email via an SMTP client. Handles potential errors during the process. ```go writer, _ := client.Data() fmt.Fprintf(writer, "Subject: Test\r\n\r\nBody") resp, err := writer.CloseWithResponse() if err != nil { log.Fatal(err) } fmt.Println("Server response:", resp.StatusText) // e.g., "OK id=12345" ``` -------------------------------- ### Handle Authentication Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/README.md Illustrates how to handle client authentication with the server. ```go auth := smtp.PlainAuth("", "user@example.com", "password", "smtp.example.com") client, err := smtp.Dial(ctx, "smtp.example.com:25") client.Auth(auth) ``` -------------------------------- ### SMTPS Server with TLS Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/README.md Configuration for an SMTPS server that uses TLS encryption from the start. ```go server := &smtp.Server{ Addr: ":465", Handler: smtp.HandlerFunc(func(client *smtp.Client) { defer client.Close() // Handle client connection }), TLSConfig: &tls.Config{ Certificates: []tls.Certificate{cert}, }, } log.Fatal(server.ListenAndServe()) } ``` -------------------------------- ### Configure TLS for Server Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/configuration.md Set up TLS configuration for STARTTLS or implicit TLS. Nil disables TLS. Ensure Certificates are configured for implicit TLS. ```go cert, _ := tls.LoadX509KeyPair("cert.pem", "key.pem") server.TLSConfig = &tls.Config{ Certificates: []tls.Certificate{cert}, } // For STARTTLS (port 25): server.ListenAndServe() // For implicit TLS (port 465): server.ListenAndServeTLS() ``` -------------------------------- ### Get Current Session from Conn Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md Retrieves the session associated with the connection. This method is thread-safe. ```go func (c *Conn) Session() Session ``` -------------------------------- ### Handle SMTP Errors Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/README.md Example of handling SMTP errors, including enhanced status codes. ```go err := client.SendMail(ctx, "sender@example.com", []string{"recipient@example.com"}, bytes.NewReader(msg)) if smtpErr, ok := err.(smtp.Error); ok { fmt.Printf("SMTP Error: %s (Code: %d.%d.%d)\n", smtpErr.Message, smtpErr.EnhancedCode.Code, smtpErr.EnhancedCode.Detail, smtpErr.EnhancedCode.Subject) } } ``` -------------------------------- ### NewClientStartTLS Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/client.md Creates a new Client from an existing connection and immediately performs STARTTLS upgrade. ```APIDOC ## NewClientStartTLS ### Description Creates a new Client from an existing connection and immediately performs STARTTLS upgrade. ### Method func NewClientStartTLS(conn net.Conn, tlsConfig *tls.Config) (*Client, error) ### Parameters #### Path Parameters - **conn** (net.Conn) - Required - An established plaintext network connection - **tlsConfig** (*tls.Config) - Optional - TLS configuration; nil is treated as zero value ### Request Example ```go conn, _ := net.Dial("tcp", "mail.example.com:25") client, err := smtp.NewClientStartTLS(conn, nil) if err != nil { log.Fatal(err) } defer client.Close() ``` ### Response #### Success Response - **Client**: A STARTTLS-upgraded SMTP client - **error**: nil #### Error Response - **Client**: nil - **error**: STARTTLS negotiation or TLS error ``` -------------------------------- ### Create Client with STARTTLS from Existing Connection Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/client.md Creates a new SMTP client from an existing plaintext connection and immediately performs a STARTTLS upgrade. Pass nil for default TLS configuration. ```go conn, _ := net.Dial("tcp", "mail.example.com:25") client, err := smtp.NewClientStartTLS(conn, nil) if err != nil { log.Fatal(err) } deffer client.Close() ``` -------------------------------- ### Create New SMTP Server Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/server.md Instantiates a new SMTP server with a given backend. Default configurations are applied, but can be overridden after creation. Useful for setting up a basic server instance. ```go func NewServer(be Backend) *Server { return &Server{ Backend: be, MaxLineLength: 2000, MaxRecipients: 0, MaxMessageBytes: 0, AllowInsecureAuth: false, Network: "tcp", Addr: ":smtp", ErrorLog: log.New(os.Stderr, "smtp/server ", 0), } } ``` -------------------------------- ### Get Underlying Network Connection Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md Access the raw network connection (`net.Conn`) associated with the SMTP connection. ```go addr := conn.Conn().RemoteAddr().String() ``` -------------------------------- ### Development Server Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/README.md A simple server configuration suitable for development environments. ```go server := &smtp.Server{ Addr: ":2525", Handler: smtp.HandlerFunc(func(client *smtp.Client) { defer client.Close() // Handle client connection }), } log.Fatal(server.ListenAndServe()) } ``` -------------------------------- ### Writing Message Content with DataCommand Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/data-command.md This example demonstrates how to use the DataCommand to write the message content and finalize the transaction by closing the writer. ```APIDOC ## DataCommand Usage ### Description Represents a pending DATA command. Implements `io.WriteCloser` for writing message content and supports SMTP/LMTP response handling. After calling `Client.Data()`, the returned `DataCommand` can be used to write the message body. The message must be RFC 822 formatted with CRLF line endings. Closing the writer sends the final dot and reads the server response. ### Method Signature `writer, err := client.Data()` ### Usage Example ```go writer, err := client.Data() if err != nil { log.Fatal(err) } defer writer.Close() fmt.Fprintf(writer, "To: recipient@example.com\r\n") fmt.Fprintf(writer, "Subject: Test\r\n") fmt.Fprintf(writer, "\r\n") fmt.Fprintf(writer, "Message body\r\n") ``` ### Closing the Writer Closing the `writer` (which is the `DataCommand`) finalizes the message transmission by sending the end-of-data marker (a single dot on a line by itself) and then reads the server's response to the DATA command. ``` -------------------------------- ### Configure Development Server (Insecure) Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/configuration.md Sets up a development SMTP server on localhost:1025, enabling insecure authentication for testing purposes. Debug output is directed to stderr. ```go server := smtp.NewServer(backend) server.Addr = "localhost:1025" server.Domain = "localhost" server.AllowInsecureAuth = true // For testing only server.Debug = os.Stderr log.Fatal(server.ListenAndServe()) ``` -------------------------------- ### SMTP Server on Port 25 Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/MANIFEST.txt Configure an SMTP server to listen on the standard port 25. This is a basic setup for a mail server. ```go server := &smtp.Server{ Addr: ":25", Domain: "example.com", Handler: &MyBackend{}, } go.ListenAndServe(server.Addr, server) ``` -------------------------------- ### Build Connection with STARTTLS Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/MANIFEST.txt Establish an SMTP connection using STARTTLS for secure communication. This involves initiating a connection and then upgrading it to TLS. ```go conn, err := smtp.Dial(ctx, "smtp.example.com:25") // ... handle error defer conn.Close() client, err := conn.StartTLS(ctx, &tls.Config{ // ... TLS config }) // ... handle error ``` -------------------------------- ### Implement Backend for Session Handling Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/configuration.md Provide a Backend implementation for session handling. The Backend must not be nil, and NewServer validates this requirement. ```go type MyBackend struct { db *Database } func (b *MyBackend) NewSession(c *smtp.Conn) (smtp.Session, error) { return &MySession{db: b.db}, nil } server := smtp.NewServer(&MyBackend{db: myDatabase}) ``` -------------------------------- ### Check Server Capabilities Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/README.md Shows how to check the supported ESMTP extensions advertised by the server. ```go conn, err := smtp.Dial(ctx, "smtp.example.com:25") if err != nil { log.Fatal(err) } capabilities := conn.Capabilities() ``` -------------------------------- ### Configure SMTP Server with STARTTLS on Port 25 Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/configuration.md Sets up an SMTP server on port 25 that supports STARTTLS for opportunistic TLS encryption. Requires certificate files. ```go cert, _ := tls.LoadX509KeyPair("cert.pem", "key.pem") server := smtp.NewServer(backend) server.Addr = ":25" server.Domain = "mail.example.com" server.TLSConfig = &tls.Config{ Certificates: []tls.Certificate{cert}, } log.Fatal(server.ListenAndServe()) // TLS via STARTTLS ``` -------------------------------- ### Basic Backend Server Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/README.md A minimal backend implementation for an SMTP server. ```go server := &smtp.Server{ Addr: ":25", Handler: smtp.HandlerFunc(func(client *smtp.Client) { defer client.Close() // Handle client connection }), } log.Fatal(server.ListenAndServe()) } ``` -------------------------------- ### Reset Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/client.md Sends an RSET command to abort the current mail transaction and reset the connection state. Allows starting a new mail transaction. ```APIDOC ## Reset ### Description Sends an RSET command to abort the current mail transaction and reset the connection state. Allows starting a new mail transaction. ### Method func (c *Client) Reset() error ### Parameters #### Path Parameters None #### Query Parameters None #### Request Body None ### Request Example ```go // After Mail/Rcpt, if we decide not to send if err := client.Reset(); err != nil { log.Fatal(err) } // Now can call Mail again ``` ### Response #### Success Response None #### Response Example None ### Error Handling - `error`: SMTPError from server - Throws SMTPError if server rejects RSET ``` -------------------------------- ### Basic Backend Implementation Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/MANIFEST.txt Implement the basic Backend interface for an SMTP server. This is the minimum required to handle incoming mail sessions. ```go type MyBackend struct {} func (b *MyBackend) NewSession(ctx context.Context) (smtp.Session, error) { return &MySession{}, nil } type MySession struct {} func (s *MySession) Mail(from string) error { // ... handle mail from return nil } func (s *MySession) Rcpt(to string) error { // ... handle recipient return nil } func (s *MySession) Data() (smtp.Message, error) { return &MyMessage{}, nil } func (s *MySession) Reset() error { return nil } func (s *MySession) Logout() error { return nil } type MyMessage struct {} func (m *MyMessage) Write(p []byte) (n int, err error) { // ... write message data return len(p), nil } func (m *MyMessage) Close() error { // ... close message return nil } ``` -------------------------------- ### Dial SMTP Server with STARTTLS Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/client.md Establishes a plaintext connection and then upgrades it to TLS using STARTTLS. This is useful when the server supports STARTTLS but not implicit TLS. ```go client, err := smtp.DialStartTLS("mail.example.com:25", nil) if err != nil { log.Fatal(err) } deffer client.Close() ``` -------------------------------- ### SendMail with STARTTLS Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/client.md Use this function to connect to an SMTP server using STARTTLS, authenticate, and send an email. It's intended for simple use cases where direct control over the client is not needed. Authentication is optional. ```go auth := sasl.NewPlainClient("", "user@example.com", "password") msg := strings.NewReader("To: recipient@example.com\r\n\r\nBody") if err := smtp.SendMail( "mail.example.com:25", auth, "sender@example.com", []string{"recipient@example.com"}, msg, ); err != nil { log.Fatal(err) } ``` -------------------------------- ### Handle Client Errors Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/MANIFEST.txt Implement error handling for SMTP client operations. This example shows how to check for and potentially recover from errors during email sending. ```go err := client.SendMail(ctx, "sender@example.com", []string{"recipient@example.com"}, msg) if err != nil { if smtpErr, ok := err.(smtp.Error); ok && smtpErr.Code == 550 { // Handle recipient not found error } else { // Handle other errors } } ``` -------------------------------- ### SMTP with STARTTLS Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/MANIFEST.txt Configure an SMTP server to support STARTTLS on a standard port (e.g., 587). This allows clients to upgrade to a TLS connection. ```go server := &smtp.Server{ Addr: ":587", Domain: "example.com", TLSConfig: &tls.Config{ Certificates: []tls.Certificate{cert}, }, Handler: &MyBackend{}, } go.ListenAndServe(server.Addr, server) ``` -------------------------------- ### Enable SMTP Client Debug Logging Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/client.md Set the DebugWriter field on the client to an io.Writer to log all network activity. This example logs traffic to standard error. ```go client, _ := smtp.Dial("mail.example.com:25") client.DebugWriter = os.Stderr // Log all traffic to stderr ``` -------------------------------- ### Server Backend Implementation Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/server.md Specifies the implementation of the Backend interface, required for creating new sessions. ```go Backend Backend ``` -------------------------------- ### Initiate Mail Transaction Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/client.md Sends the MAIL command to start an email transaction. Automatically enables 8BITMIME if supported by the server. Use when sending a new email. ```go opts := &smtp.MailOptions{ UTF8: true, Size: 1024000, } if err := client.Mail("sender@example.com", opts); err != nil { log.Fatal(err) } ``` -------------------------------- ### Get TLS Connection State Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md Retrieves the TLS connection state if the connection is encrypted using TLS. Returns the state and a boolean indicating if TLS is active. ```go if state, ok := conn.TLSConnectionState(); ok { fmt.Printf("TLS Version: %v\n", state.Version) } ``` -------------------------------- ### Get Client Hostname from Conn Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md Obtain the hostname or domain presented by the client during the HELO/EHLO/LHLO command. Returns an empty string if the client has not yet greeted the server. ```go if clientHostname := conn.Hostname(); clientHostname != "" { log.Printf("Client: %s", clientHostname) } ``` -------------------------------- ### Configure Basic SMTP Server on Port 25 Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/configuration.md Sets up a basic SMTP server on port 25 with domain and message size limits. Ensure a backend implementation is provided. ```go backend := &MyBackend{} server := smtp.NewServer(backend) server.Domain = "mail.example.com" server.MaxMessageBytes = 1024 * 1024 * 50 // 50 MB server.MaxRecipients = 100 server.MaxLineLength = 2000 log.Fatal(server.ListenAndServe()) ``` -------------------------------- ### Configure SMTP Server Settings Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/QUICK-REFERENCE.md Set up a new SMTP server instance with various configurations including network address, domain, size limits, TLS, extensions, timeouts, logging, and security options. Supports LMTP mode. ```go server := smtp.NewServer(backend) // Network server.Addr = "localhost:25" server.Domain = "mail.example.com" // Size limits server.MaxMessageBytes = 1024 * 1024 * 50 server.MaxRecipients = 500 server.MaxLineLength = 2000 // TLS cert, _ := tls.LoadX509KeyPair("cert.pem", "key.pem") server.TLSConfig = &tls.Config{Certificates: []tls.Certificate{cert}} // Extensions server.EnableSMTPUTF8 = true server.EnableDSN = true server.EnableDELIVERBY = true server.MinimumDeliverByTime = 30 * time.Minute server.EnableBINARYMIME = true server.EnableREQUIRETLS = true server.EnableRRVS = true server.EnableMTPRIORITY = true server.MtPriorityProfile = smtp.PriorityMIXER // Timeouts server.ReadTimeout = 30 * time.Second server.WriteTimeout = 30 * time.Second // Logging server.Debug = os.Stderr server.ErrorLog = customLogger // Security (testing only) server.AllowInsecureAuth = true // LMTP mode server.LMTP = true server.Network = "unix" server.Addr = "/var/run/lmtp.sock" ``` -------------------------------- ### Close Data Command with Error Handling Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/data-command.md Example of closing the DataCommand and checking for SMTP errors. If an error occurs, it can be type-asserted to an smtp.SMTPError to access the error code and message. ```go writer, _ := client.Data() fmt.Fprintf(writer, "Subject: Test\r\n\r\nBody") if err := writer.Close(); err != nil { if smtpErr, ok := err.(*smtp.SMTPError); ok { fmt.Printf("SMTP error %d: %s\n", smtpErr.Code, smtpErr.Message) } } ``` -------------------------------- ### Get TLS Connection State Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/client.md Retrieves the TLS connection state if the client's connection is encrypted with TLS. Returns zero values and false if TLS is not active. ```go func (c *Client) TLSConnectionState() (state tls.ConnectionState, ok bool) ``` ```go if state, ok := client.TLSConnectionState(); ok { fmt.Println("TLS Version:", state.Version) } ``` -------------------------------- ### Handling RcptOptions with DeliverBy in Session.Rcpt Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/types.md Illustrates how to access and handle the DeliverBy options within a custom Session.Rcpt implementation to manage delivery time limits. ```go func (s *MySession) Rcpt(to string, opts *smtp.RcptOptions) error { if opts != nil && opts.DeliverBy != nil { // Handle delivery time limit deadline := time.Now().Add(opts.DeliverBy.Time) } return nil } ``` -------------------------------- ### Send Email with Custom Options Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/README.md Demonstrates sending an email with custom mail options, such as specifying the body format. ```go opts := &smtp.MailOptions{ Body: smtp.Body8bit, } client.SendMail(ctx, "sender@example.com", []string{"recipient@example.com"}, bytes.NewReader([]byte("Subject: Test\n\nHello World")), smtp.WithMailOptions(opts)) ``` -------------------------------- ### Implement Session Reset Method Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/conn-and-backend.md Example implementation for the Reset method, which discards pending message state like sender, recipients, and message data. This is called on RSET or EHLO after a transaction. ```go func (s *MySession) Reset() { s.from = "" s.recipients = nil s.messageData = nil } ``` -------------------------------- ### Server TLS Configuration Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/server.md Configures TLS settings for STARTTLS and secure connections. Set to nil to disable TLS. ```go TLSConfig *tls.Config ``` -------------------------------- ### Set Per-Recipient LMTP Status (Server-Side) Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/errors.md This server-side example shows how to collect and set the delivery status for each recipient during an LMTP transaction. It logs success or failure for each recipient using the StatusCollector. ```go func (s *MyLMTPSession) LMTPData(r io.Reader, status smtp.StatusCollector) error { data, _ := io.ReadAll(r) for _, to := range s.recipients { err := s.deliver(to, data) if err != nil { status.SetStatus(to, &smtp.SMTPError{ Code: 550, EnhancedCode: smtp.EnhancedCode{5, 1, 1}, Message: "User not found", }) } else { status.SetStatus(to, nil) // Success } } return nil } ``` -------------------------------- ### Correct Dot Escaping for Lines Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/data-command.md Illustrates the correct method for handling lines that start with a dot. The SMTP protocol automatically escapes dots by doubling them; do not manually double dots in your code. ```go // CORRECT: Dot is automatically escaped fmt.Fprintf(writer, "This is a dot: .\r\n") // Sent as: "This is a dot: ..\r\n" // WRONG: Don't double the dot yourself fmt.Fprintf(writer, "This is a dot: ..\r\n") // Sent as: "This is a dot: .... \n" ``` -------------------------------- ### Configure go-smtp Server with TLS Source: https://github.com/emersion/go-smtp/wiki/Server Sets up a go-smtp server with TLS enabled for secure authentication. Loads the certificate and key pair. ```go func main() { be := &Backend{} s := smtp.NewServer(be) s.Addr = ":1025" s.Domain = "localhost" s.ReadTimeout = 10 * time.Second s.WriteTimeout = 10 * time.Second s.MaxMessageBytes = 1024 * 1024 s.MaxRecipients = 50 // force TLS for auth s.AllowInsecureAuth = false // Load the certificate and key cer, err := tls.LoadX509KeyPair("server.crt", "server.key") if err != nil { log.Fatal(err) return } // Configure the TLS support s.TLSConfig = &tls.Config{Certificates: []tls.Certificate{cer}} log.Println("Starting server at", s.Addr) if err := s.ListenAndServe(); err != nil { log.Fatal(err) } } ``` -------------------------------- ### SMTP Server STARTTLS Configuration Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/QUICK-REFERENCE.md Configure an SMTP server to support STARTTLS. This allows clients to initiate a TLS upgrade after connecting on a non-TLS port. Ensure your certificate and key files are correctly loaded. ```go cert, _ := tls.LoadX509KeyPair("cert.pem", "key.pem") server.TLSConfig = &tls.Config{ Certificates: []tls.Certificate{cert}, } server.ListenAndServe() // STARTTLS available ``` -------------------------------- ### Close Data Command and Handle LMTP Responses Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/data-command.md Example demonstrating how to use CloseWithLMTPResponse for LMTP clients. It shows handling potential LMTPDataError for individual recipient failures and iterating through successful deliveries. ```go writer, _ := client.Data() fmt.Fprintf(writer, "Subject: Test\r\n\r\nBody") resp, err := writer.CloseWithLMTPResponse() // Handle partial success if lmtpErr, ok := err.(smtp.LMTPDataError); ok { for _, e := range lmtpErr.Unwrap() { log.Println(e) // ": error" } } // Check successful deliveries for addr, response := range resp { fmt.Printf("%s: %s\n", addr, response.StatusText) } ``` -------------------------------- ### Reset Current Mail Transaction Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/client.md Sends an RSET command to abort the current mail transaction and reset the connection state. Allows starting a new mail transaction after an intermediate decision not to send. ```go // After Mail/Rcpt, if we decide not to send if err := client.Reset(); err != nil { log.Fatal(err) } // Now can call Mail again ``` -------------------------------- ### Enable Debug Logging Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/configuration.md Configure a writer for logging all network traffic. Set to a non-nil value to enable debug logging. Set to nil to disable. ```go server.Debug = os.Stderr // or server.Debug = file // to disable: server.Debug = nil ``` -------------------------------- ### Server with Authentication Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/README.md An SMTP server implementation that supports client authentication. ```go server := &smtp.Server{ Addr: ":25", Handler: smtp.HandlerFunc(func(client *smtp.Client) { defer client.Close() // Handle client connection }), Auth: smtp.LoginAuth("user", "password", nil), } log.Fatal(server.ListenAndServe()) } ``` -------------------------------- ### Handle SMTP Response After Sending Data Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/data-command.md This example demonstrates how to send the message body and then process the server's response, including checking for specific SMTP error codes like 'message too large'. ```go writer, err := client.Data() if err != nil { log.Fatal(err) } fmt.Fprintf(writer, "Subject: Test\r\n\r\nBody") resp, err := writer.CloseWithResponse() if err != nil { if smtpErr, ok := err.(*smtp.SMTPError); ok { if smtpErr.Code == 552 { // Message too large } } log.Fatal(err) } fmt.Println("Queue ID:", resp.StatusText) ``` -------------------------------- ### Get Maximum Message Size Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/client.md Retrieves the maximum message size accepted by the SMTP server. If the server advertises a size limit, this method returns the size in bytes and true; otherwise, it returns false. ```go if maxSize, ok := client.MaxMessageSize(); ok { if msgSize > int64(maxSize) { log.Fatal("Message exceeds maximum size") } } ``` -------------------------------- ### Send Email (Simple) Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/QUICK-REFERENCE.md Use this method for basic email sending with minimal configuration. Requires SASL authentication and a string reader for the message body. ```go import "github.com/emersion/go-sasl" import "github.com/emersion/go-smtp" auth := sasl.NewPlainClient("", "user@example.com", "password") msg := strings.NewReader("To: recipient@example.com\r\n\r\nBody") smtp.SendMail("mail.example.com:25", auth, "from@example.com", []string{"to@example.com"}, msg) ``` -------------------------------- ### Close Data Command and Get Per-Recipient Responses (LMTP) Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/data-command.md Closes the writer for LMTP clients, sends the final dot, and returns a map of per-recipient responses. It can return partial success with LMTPDataError for failed recipients. ```go func (cmd *DataCommand) CloseWithLMTPResponse() (map[string]*DataResponse, error) ``` -------------------------------- ### Write Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/data-command.md Writes message content bytes to the server. This method implements the io.Writer interface, allowing direct writing of message data. It handles automatic escaping of dots at the start of lines and preserves CRLF line endings. ```APIDOC ## Write ### Description Writes message content bytes. Implements the io.Writer interface. ### Method Signature ```go func (cmd *DataCommand) Write(b []byte) (int, error) ``` ### Parameters #### Path Parameters - None #### Query Parameters - None #### Request Body - **b** ([]byte) - Required - Bytes to write to the message ### Request Example ```go writer, _ := client.Data() defer writer.Close() // Write headers fmt.Fprintf(writer, "From: sender@example.com\r\n") fmt.Fprintf(writer, "To: recipient@example.com\r\n") fmt.Fprintf(writer, "Subject: Test\r\n") // Write blank line separator fmt.Fprintf(writer, "\r\n") // Write body fmt.Fprintf(writer, "This is the message body.\r\n") // Can also use io.Copy with proper CRLF handling io.Copy(writer, messageReader) ``` ### Response #### Success Response - **int**: Number of bytes written #### Error Response - **error**: Write error (connection closed, line too long, etc.) ### Behavior - Bytes are sent directly to the server. - No special escaping is performed. - Dots at line start are escaped automatically by the underlying text protocol. - CRLF line endings are preserved. - Single LF line endings are NOT converted to CRLF. ``` -------------------------------- ### Server Backend with Authentication Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/MANIFEST.txt Implement a backend for an SMTP server that supports authentication. This extends the basic backend to handle user credentials. ```go type AuthBackend struct { /* ... */ } func (b *AuthBackend) NewSession(ctx context.Context) (smtp.Session, error) { return &AuthSession{backend: b}, } type AuthSession struct { backend *AuthBackend // ... other fields } func (s *AuthSession) Auth(mechanism string, callback func(challenge []byte) ([]byte, error)) error { // ... handle authentication mechanism and callback return nil } func (s *AuthSession) Mail(from string) error { // ... return nil } func (s *AuthSession) Rcpt(to string) error { // ... return nil } func (s *AuthSession) Data() (smtp.Message, error) { // ... return nil } func (s *AuthSession) Reset() error { return nil } func (s *AuthSession) Logout() error { return nil } ``` -------------------------------- ### Close Data Command and Get Server Response (SMTP) Source: https://github.com/emersion/go-smtp/blob/master/_autodocs/api-reference/data-command.md Closes the writer for SMTP clients, sends the final dot, and returns the server's response message, which may include queue ID or tracking information. It waits for the response with a timeout. ```go func (cmd *DataCommand) CloseWithResponse() (*DataResponse, error) ```