smtp
Go library that improves and extends net/smtp.
The SMTP client in net/smtp already supports a number of features:
- Support for PLAIN authentication.
- Support for CRAM-MD5 authentication.
- Support for STARTTLS encryption.
But it also misses some features which limit it's application to simple forwarding scenarios.
This library adds the following features:
- Support binding to specific local IP.
- Use port 25 if no port specified instead of always requiring port.
- Use os.Hostname as default EHLO name instead of using "localhost" as default.
- Disable TLS domain verification, unless serverName is specified.
- Provide Session() and Transaction() members as intermediate level API.
- Support for PIPELINING extension.
- Send DATA if at least one RCPT is accepted instead of returning after the first failed recipient.
- Context information in SMTP errors showing the stage of the transaction.
TODOS:
- Do not send HELO after EHLO with 4XX error.
- Command-response timeouts according to RFC.
- Issue RSET before next transaction if last transaction failed.
- Less picky about response codes, the first digit is conclusive.
Usage
Forward one message
To connect to an MX, forward a message, and disconnect:
err = smtp.SendMail(mx, sender, recipients, message, nil)
Bulk email delivery
To connect to an MX from a specific local IP address:
client, err := smtp.DialFrom("gmail-smtp-in.l.google.com", net.ParseIP("1.2.3.4"))
To initiate a session, using "opportunistic" TLS and no authentication:
err := client.Session("mail.example.com", "", nil)
To start a transaction, using pipelining if available:
wc, err := client.Transaction(sender, recipients)
If multiple recipients are specified, some can be rejected and some can be accepted. If the transaction succeeds and at least one recipient was accepted a non-nil io.WriteCloser is returned. A non-nil err indicates that the transaction failed, or that at least one recipient was rejected.
To send the message from an io.Reader:
_, err := io.Copy(wc, reader)
if err != nil {
return err
}
err = wc.Close()
Then another transaction can be started or the session can be terminated:
client.Quit()
License
MIT