mail

package module
v2.16.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 17, 2023 License: MIT Imports: 24 Imported by: 445

README

Go Simple Mail

The best way to send emails in Go with SMTP Keep Alive and Timeout for Connect and Send.

Go Report Card go.dev

IMPORTANT

Examples in this README are for v2.2.0 and above. Examples for older versions can be found here.

Go 1.13+ is required.

Breaking change in 2.2.0: The signature of SetBody and AddAlternative used to accept strings ("text/html" and "text/plain") and not require on of the contentType constants (TextHTML or TextPlain). Upgrading, while not quite following semantic versioning, is quite simple:

  email := mail.NewMSG()
- email.SetBody("text/html", htmlBody)
- email.AddAlternative("text/plain", plainBody)
+ email.SetBody(mail.TextHTML, htmlBody)
+ email.AddAlternative(mail.TextPlain, plainBody)

Introduction

Go Simple Mail is a simple and efficient package to send emails. It is well tested and documented.

Go Simple Mail can only send emails using an SMTP server. But the API is flexible and it is easy to implement other methods for sending emails using a local Postfix, an API, etc.

This package contains (and is based on) two packages by Joe Grasse:

A lot of changes in Go Simple Mail were sent with not response.

Features

Go Simple Mail supports:

  • Multiple Attachments with path
  • Multiple Attachments in base64
  • Multiple Attachments from bytes (since v2.6.0)
  • Inline attachments from file, base64 and bytes (bytes since v2.6.0)
  • Multiple Recipients
  • Priority
  • Reply to
  • Set sender
  • Set from
  • Allow sending mail with different envelope from (since v2.7.0)
  • Embedded images
  • HTML and text templates
  • Automatic encoding of special characters
  • SSL/TLS and STARTTLS
  • Unencrypted connection (not recommended)
  • Sending multiple emails with the same SMTP connection (Keep Alive or Persistent Connection)
  • Timeout for connect to a SMTP Server
  • Timeout for send an email
  • Return Path
  • Alternative Email Body
  • CC and BCC
  • Add Custom Headers in Message
  • Send NOOP, RESET, QUIT and CLOSE to SMTP client
  • PLAIN, LOGIN and CRAM-MD5 Authentication (since v2.3.0)
  • AUTO Authentication (since v2.14.0)
  • Allow connect to SMTP without authentication (since v2.10.0)
  • Custom TLS Configuration (since v2.5.0)
  • Send a RFC822 formatted message (since v2.8.0)
  • Send from localhost (yes, Go standard SMTP package cannot do that because... WTF Google!)
  • Support text/calendar content type body (since v2.11.0)
  • Support add a List-Unsubscribe header (since v2.11.0)
  • Support to add a DKIM signarure (since v2.11.0)
  • Support to send using custom connection, ideal for proxy (since v2.15.0)
  • Support Delivery Status Notification (DSN) (since v2.16.0)
  • Support text/x-amp-html content type body (since v2.16.0)

Documentation

https://pkg.go.dev/github.com/xhit/go-simple-mail/v2?tab=doc

Note 1: by default duplicated recipients throws an error, from v2.13.0 you can use email.AllowDuplicateAddress = true to avoid the check.

Note 2: by default Bcc header is not set in email. From v2.14.0 you can use email.AddBccToHeader = true to add this.

Download

This package uses go modules.

$ go get github.com/xhit/go-simple-mail/v2

Usage

package main

import (
	"log"

	mail "github.com/xhit/go-simple-mail/v2"
	"github.com/toorop/go-dkim"
)

const htmlBody = `<html>
	<head>
		<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
		<title>Hello Gophers!</title>
	</head>
	<body>
		<p>This is the <b>Go gopher</b>.</p>
		<p><img src="cid:Gopher.png" alt="Go gopher" /></p>
		<p>Image created by Renee French</p>
	</body>
</html>`

const privateKey = `-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAwGrscUxi9zEa9oMOJbS0kLVHZXNIW+EBjY7KFWIZSxuGAils
wBVl+s5mMRrR5VlkyLQNulAdNemg6OSeB0R+2+8/lkHiMrimqQckZ5ig8slBoZhZ
wUoL/ZkeQa1bacbdww5TuWkiVPD9kooT/+TZW1P/ugd6oYjpOI56ZjsXzJw5pz7r
DiwcIJJaaDIqvvc5C4iW94GZjwtmP5pxhvBZ5D6Uzmh7Okvi6z4QCKzdJQLdVmC0
CMiFeh2FwqMkVpjZhNt3vtCo7Z51kwHVscel6vl51iQFq/laEzgzAWOUQ+ZEoQpL
uTaUiYzzNyEdGEzZ2CjMMoO8RgtXnUo2qX2FDQIDAQABAoIBAHWKW3kycloSMyhX
EnNSGeMz+bMtYwxNPMeebC/3xv+shoYXjAkiiTNWlfJ1MbbqjrhT1Pb1LYLbfqIF
1csWum/bjHpbMLRPO++RH1nxUJA/BMqT6HA8rWpy+JqiLW9GPf2DaP2gDYrZ0+yK
UIFG6MfzXgnju7OlkOItlvOQMY+Y501u/h6xnN2yTeRqXXJ1YlWFPRIeFdS6UOtL
J2wSxRVdymHbGwf+D7zet7ngMPwFBsbEN/83KGLRjkt8+dMQeUeob+nslsQofCZx
iokIAvByTugmqrB4JqhNkAlZhC0mqkRQh7zUFrxSj5UppMWlxLH+gPFZHKAsUJE5
mqmylcECgYEA8I/f90cpF10uH4NPBCR4+eXq1PzYoD+NdXykN65bJTEDZVEy8rBO
phXRNfw030sc3R0waQaZVhFuSgshhRuryfG9c1FP6tQhqi/jiEj9IfCW7zN9V/P2
r16pGjLuCK4SyxUC8H58Q9I0X2CQqFamtkLXC6Ogy86rZfIc8GcvZ9UCgYEAzMQZ
WAiLhRF2MEmMhKL+G3jm20r+dOzPYkfGxhIryluOXhuUhnxZWL8UZfiEqP5zH7Li
NeJvLz4pOL45rLw44qiNu6sHN0JNaKYvwNch1wPT/3/eDNZKKePqbAG4iamhjLy5
gjO1KgA5FBbcNN3R6fuJAg1e4QJCOuo55eW6vFkCgYEA7UBIV72D5joM8iFzvZcn
BPdfqh2QnELxhaye3ReFZuG3AqaZg8akWqLryb1qe8q9tclC5GIQulTInBfsQDXx
MGLNQL0x/1ylsw417kRl+qIoidMTTLocUgse5erS3haoDEg1tPBaKB1Zb7NyF8QV
+W1kX2NKg5bZbdrh9asekt0CgYA6tUam7NxDrLv8IDo/lRPSAJn/6cKG95aGERo2
k+MmQ5XP+Yxd+q0LOs24ZsZyRXHwdrNQy7khDGt5L2EN23Fb2wO3+NM6zrGu/WbX
nVbAdQKFUL3zZEUjOYtuqBemsJH27e0qHXUls6ap0dwU9DxJH6sqgXbggGtIxPsQ
pQsjEQKBgQC9gAqAj+ZtMXNG9exVPT8I15reox9kwxGuvJrRu/5eSi6jLR9z3x9P
2FrgxQ+GCB2ypoOUcliXrKesdSbolUilA8XQn/M113Lg8oA3gJXbAKqbTR/EgfUU
kvYaR/rTFnivF4SL/P4k/gABQoJuFUtSKdouELqefXB+e94g/G++Bg==
-----END RSA PRIVATE KEY-----`

func main() {
	server := mail.NewSMTPClient()

	// SMTP Server
	server.Host = "smtp.example.com"
	server.Port = 587
	server.Username = "test@example.com"
	server.Password = "examplepass"
	server.Encryption = mail.EncryptionSTARTTLS

	// You can specified authentication type:
	// - AUTO (default)
	// - PLAIN
	// - LOGIN
	// - CRAM-MD5
	// - None
	// server.Authentication = mail.AuthAuto

	// Variable to keep alive connection
	server.KeepAlive = false

	// Timeout for connect to SMTP Server
	server.ConnectTimeout = 10 * time.Second

	// Timeout for send the data and wait respond
	server.SendTimeout = 10 * time.Second

	// Set TLSConfig to provide custom TLS configuration. For example,
	// to skip TLS verification (useful for testing):
	server.TLSConfig = &tls.Config{InsecureSkipVerify: true}

	// SMTP client
	smtpClient,err := server.Connect()

	if err != nil{
		log.Fatal(err)
	}

	// New email simple html with inline and CC
	email := mail.NewMSG()
	email.SetFrom("From Example <nube@example.com>").
		AddTo("xhit@example.com").
		AddCc("otherto@example.com").
		SetSubject("New Go Email").
		SetListUnsubscribe("<mailto:unsubscribe@example.com?subject=https://example.com/unsubscribe>")

	email.SetBody(mail.TextHTML, htmlBody)

	// also you can add body from []byte with SetBodyData, example:
	// email.SetBodyData(mail.TextHTML, []byte(htmlBody))
	// or alternative part
	// email.AddAlternativeData(mail.TextHTML, []byte(htmlBody))

	// add inline
	email.Attach(&mail.File{FilePath: "/path/to/image.png", Name:"Gopher.png", Inline: true})

	// also you can set Delivery Status Notification (DSN) (only is set when server supports DSN)
	email.SetDSN([]mail.DSN{mail.SUCCESS, mail.FAILURE}, false)

	// you can add dkim signature to the email. 
	// to add dkim, you need a private key already created one.
	if privateKey != "" {
		options := dkim.NewSigOptions()
		options.PrivateKey = []byte(privateKey)
		options.Domain = "example.com"
		options.Selector = "default"
		options.SignatureExpireIn = 3600
		options.Headers = []string{"from", "date", "mime-version", "received", "received"}
		options.AddSignatureTimestamp = true
		options.Canonicalization = "relaxed/relaxed"

		email.SetDkim(options)
	}

	// always check error after send
	if email.Error != nil{
		log.Fatal(email.Error)
	}

	// Call Send and pass the client
	err = email.Send(smtpClient)
	if err != nil {
		log.Println(err)
	} else {
		log.Println("Email Sent")
	}
}

Send multiple emails in same connection

	//Set your smtpClient struct to keep alive connection
	server.KeepAlive = true

	for _, to := range []string{
		"to1@example1.com",
		"to3@example2.com",
		"to4@example3.com",
	} {
		// New email simple html with inline and CC
		email := mail.NewMSG()
		email.SetFrom("From Example <nube@example.com>").
			AddTo(to).
			SetSubject("New Go Email")

		email.SetBody(mail.TextHTML, htmlBody)

		// add inline
		email.Attach(&mail.File{FilePath: "/path/to/image.png", Name:"Gopher.png", Inline: true})

		// always check error after send
		if email.Error != nil{
			log.Fatal(email.Error)
		}

		// Call Send and pass the client
		err = email.Send(smtpClient)
		if err != nil {
			log.Println(err)
		} else {
			log.Println("Email Sent")
		}
	}

Send with custom connection

It's possible to use a custom connection with custom dieler, like a dialer that uses a proxy server, etc...

With this, these servers params are ignored: Host, Port. You have total control of the connection.

Example using a conn for proxy:

package main

import (
	"crypto/tls"
	"fmt"
	"log"
	"net"

	mail "github.com/xhit/go-simple-mail/v2"
	"golang.org/x/net/proxy"
)

func main() {
	server := mail.NewSMTPClient()

	host := "smtp.example.com"
	port := 587
	proxyAddr := "proxy.server"

	conn, err := getCustomConnWithProxy(proxyAddr, host, port)
	if err != nil {
		log.Fatal(err)
	}

	server.Username = "test@example.com"
	server.Password = "examplepass"
	server.Encryption = mail.EncryptionSTARTTLS
	server.CustomConn = conn

	smtpClient, err := server.Connect()
	if err != nil {
		log.Fatal(err)
	}

	email := mail.NewMSG()

	err = email.SetFrom("From Example <nube@example.com>").AddTo("xhit@example.com").Send(smtpClient)
	if err != nil {
		log.Fatal(err)
	}

}

func getCustomConnWithProxy(proxyAddr, host string, port int) (net.Conn, error) {
	dial, err := proxy.SOCKS5("tcp", proxyAddr, nil, proxy.Direct)
	if err != nil {
		return nil, err
	}

	dialer, err := dial.Dial("tcp", fmt.Sprintf("%s:%d", host, port))
	if err != nil {
		return nil, err
	}

	conf := &tls.Config{ServerName: host}
	conn := tls.Client(dialer, conf)

	return conn, nil
}

More examples

See example/example_test.go.

Documentation

Index

Constants

View Source
const (
	// EncodingNone turns off encoding on the message body
	EncodingNone encoding = iota
	// EncodingBase64 sets the message body encoding to base64
	EncodingBase64
	// EncodingQuotedPrintable sets the message body encoding to quoted-printable
	EncodingQuotedPrintable
)

Variables

This section is empty.

Functions

func SendMessage added in v2.8.0

func SendMessage(from string, recipients []string, msg string, client *SMTPClient) error

SendMessage sends a message (a RFC822 formatted message) 'from' must be an email address, recipients must be a slice of email address

Types

type AuthType added in v2.10.0

type AuthType int
const (
	// AuthPlain implements the PLAIN authentication
	AuthPlain AuthType = iota
	// AuthLogin implements the LOGIN authentication
	AuthLogin
	// AuthCRAMMD5 implements the CRAM-MD5 authentication
	AuthCRAMMD5
	// AuthNone for SMTP servers without authentication
	AuthNone
	// AuthAuto (default) use the first AuthType of the list of returned types supported by SMTP
	AuthAuto
)

func (AuthType) String added in v2.14.0

func (at AuthType) String() string

type ContentType added in v2.12.0

type ContentType int
const (
	// TextPlain sets body type to text/plain in message body
	TextPlain ContentType = iota
	// TextHTML sets body type to text/html in message body
	TextHTML
	// TextCalendar sets body type to text/calendar in message body
	TextCalendar
	// TextAMP sets body type to text/x-amp-html in message body
	TextAMP
)

type DSN added in v2.16.0

type DSN int
DSN notifications

- 'NEVER' under no circumstances a DSN must be returned to the sender. If you use NEVER all other notifications will be ignored.

- 'SUCCESS' will notify you when your mail has arrived at its destination.

- 'FAILURE' will arrive if an error occurred during delivery.

- 'DELAY' will notify you if there is an unusual delay in delivery, but the actual delivery's outcome (success or failure) is not yet decided.

see https://tools.ietf.org/html/rfc3461 See section 4.1 for more information about NOTIFY

const (
	NEVER DSN = iota
	FAILURE
	DELAY
	SUCCESS
)

func (DSN) String added in v2.16.0

func (dsn DSN) String() string

type Email

type Email struct {
	Charset               string
	Encoding              encoding
	Error                 error
	SMTPServer            *smtpClient
	DkimMsg               string
	AllowDuplicateAddress bool
	AddBccToHeader        bool
	// contains filtered or unexported fields
}

Email represents an email message.

func NewMSG

func NewMSG() *Email

NewMSG creates a new email. It uses UTF-8 by default. All charsets: http://webcheatsheet.com/HTML/character_sets_list.php

func (*Email) AddAddresses

func (email *Email) AddAddresses(header string, addresses ...string) *Email

AddAddresses allows you to add addresses to the specified address header.

func (*Email) AddAlternative

func (email *Email) AddAlternative(contentType ContentType, body string) *Email

AddAlternative allows you to add alternative parts to the body of the email message. This is most commonly used to add an html version in addition to a plain text version that was already added with SetBody.

func (*Email) AddAlternativeData added in v2.11.0

func (email *Email) AddAlternativeData(contentType ContentType, body []byte) *Email

AddAlternativeData allows you to add alternative parts to the body of the email message. This is most commonly used to add an html version in addition to a plain text version that was already added with SetBody.

func (*Email) AddAttachment

func (email *Email) AddAttachment(file string, name ...string) *Email

AddAttachment. DEPRECATED. Use Attach method. Allows you to add an attachment to the email message. You can optionally provide a different name for the file.

func (*Email) AddAttachmentBase64

func (email *Email) AddAttachmentBase64(b64File, name string) *Email

AddAttachmentBase64. DEPRECATED. Use Attach method. Allows you to add an attachment in base64 to the email message. You need provide a name for the file.

func (*Email) AddAttachmentData added in v2.6.0

func (email *Email) AddAttachmentData(data []byte, filename, mimeType string) *Email

AddAttachmentData. DEPRECATED. Use Attach method. Allows you to add an in-memory attachment to the email message.

func (*Email) AddBcc

func (email *Email) AddBcc(addresses ...string) *Email

AddBcc adds a Bcc address. You can provide multiple addresses at the same time.

func (*Email) AddCc

func (email *Email) AddCc(addresses ...string) *Email

AddCc adds a Cc address. You can provide multiple addresses at the same time.

func (*Email) AddHeader

func (email *Email) AddHeader(header string, values ...string) *Email

AddHeader adds the given "header" with the passed "value".

func (*Email) AddHeaders

func (email *Email) AddHeaders(headers textproto.MIMEHeader) *Email

AddHeaders is used to add multiple headers at once

func (*Email) AddInline

func (email *Email) AddInline(file string, name ...string) *Email

AddInline. DEPRECATED. Use Attach method. Allows you to add an inline attachment to the email message. You can optionally provide a different name for the file.

func (*Email) AddInlineBase64 added in v2.9.0

func (email *Email) AddInlineBase64(b64File, name, mimeType string) *Email

AddInlineBase64. DEPRECATED. Use Attach method. Allows you to add an inline in-memory base64 encoded attachment to the email message. You need provide a name for the file. If mimeType is an empty string, attachment mime type will be deduced from the file name extension and defaults to application/octet-stream.

func (*Email) AddInlineData added in v2.6.0

func (email *Email) AddInlineData(data []byte, filename, mimeType string) *Email

AddInlineData. DEPRECATED. Use Attach method. Allows you to add an inline in-memory attachment to the email message.

func (*Email) AddTo

func (email *Email) AddTo(addresses ...string) *Email

AddTo adds a To address. You can provide multiple addresses at the same time.

func (*Email) Attach added in v2.9.0

func (email *Email) Attach(file *File) *Email

Attach allows you to add an attachment to the email message. The attachment can be inlined

func (*Email) GetError

func (email *Email) GetError() error

GetError returns the first email error encountered

func (*Email) GetFrom added in v2.5.1

func (email *Email) GetFrom() string

GetFrom returns the sender of the email, if any

func (*Email) GetMessage

func (email *Email) GetMessage() string

GetMessage builds and returns the email message (RFC822 formatted message)

func (*Email) GetRecipients added in v2.8.0

func (email *Email) GetRecipients() []string

GetRecipients returns a slice of recipients emails

func (*Email) Send

func (email *Email) Send(client *SMTPClient) error

Send sends the composed email

func (*Email) SendEnvelopeFrom added in v2.7.0

func (email *Email) SendEnvelopeFrom(from string, client *SMTPClient) error

SendEnvelopeFrom sends the composed email with envelope sender. 'from' must be an email address.

func (*Email) SetBody

func (email *Email) SetBody(contentType ContentType, body string) *Email

SetBody sets the body of the email message.

func (*Email) SetBodyData added in v2.9.0

func (email *Email) SetBodyData(contentType ContentType, body []byte) *Email

SetBodyData sets the body of the email message from []byte

func (*Email) SetDSN added in v2.16.0

func (email *Email) SetDSN(dsn []DSN, preserveOriginalRecipient bool) *Email

SetDSN sets the delivery status notification list, only is set when SMTP server supports DSN extension

To preserve the original recipient of an email message, for example, if it is forwarded to another address, set preserveOriginalRecipient to true

func (*Email) SetDate

func (email *Email) SetDate(dateTime string) *Email

SetDate sets the date header to the provided date/time. The format of the string should be YYYY-MM-DD HH:MM:SS Time Zone.

Example: SetDate("2015-04-28 10:32:00 CDT")

func (*Email) SetDkim added in v2.11.0

func (email *Email) SetDkim(options dkim.SigOptions) *Email

SetDkim adds DomainKey signature to the email message (header+body)

func (*Email) SetFrom

func (email *Email) SetFrom(address string) *Email

SetFrom sets the From address.

func (*Email) SetListUnsubscribe added in v2.11.0

func (email *Email) SetListUnsubscribe(address string) *Email

SetListUnsubscribe sets the Unsubscribe address.

func (*Email) SetPriority

func (email *Email) SetPriority(priority Priority) *Email

SetPriority sets the email message Priority. Use with either "High" or "Low".

func (*Email) SetReplyTo

func (email *Email) SetReplyTo(address string) *Email

SetReplyTo sets the Reply-To address.

func (*Email) SetReturnPath

func (email *Email) SetReturnPath(address string) *Email

SetReturnPath sets the Return-Path address. This is most often used to send bounced emails to a different email address.

func (*Email) SetSender

func (email *Email) SetSender(address string) *Email

SetSender sets the Sender address.

func (*Email) SetSubject

func (email *Email) SetSubject(subject string) *Email

SetSubject sets the subject of the email message.

type Encryption added in v2.8.0

type Encryption int

Encryption type to enum encryption types (None, SSL/TLS, STARTTLS)

const (
	// EncryptionNone uses no encryption when sending email
	EncryptionNone Encryption = iota
	// EncryptionSSL: DEPRECATED. Use EncryptionSSLTLS. Sets encryption type to SSL/TLS when sending email
	EncryptionSSL
	// EncryptionTLS: DEPRECATED. Use EncryptionSTARTTLS. sets encryption type to STARTTLS when sending email
	EncryptionTLS
	// EncryptionSSLTLS sets encryption type to SSL/TLS when sending email
	EncryptionSSLTLS
	// EncryptionSTARTTLS sets encryption type to STARTTLS when sending email
	EncryptionSTARTTLS
)

func (Encryption) String added in v2.8.0

func (encryption Encryption) String() string

type File added in v2.9.0

type File struct {
	// FilePath is the path of the file to attach.
	FilePath string
	// Name is the name of file in attachment. Required for Data and B64Data. Optional for FilePath.
	Name string
	// MimeType of attachment. If empty then is obtained from Name (if not empty) or FilePath. If cannot obtained, application/octet-stream is set.
	MimeType string
	// B64Data is the base64 string to attach.
	B64Data string
	// Data is the []byte of file to attach.
	Data []byte
	// Inline defines if attachment is inline or not.
	Inline bool
}

File represents the file that can be added to the email message. You can add attachment from file in path, from base64 string or from []byte. You can define if attachment is inline or not. Only one, Data, B64Data or FilePath is supported. If multiple are set, then the first in that order is used.

type Priority added in v2.16.0

type Priority int
const (
	// PriorityLow sets the email Priority to Low
	PriorityLow Priority = iota
	// PriorityHigh sets the email Priority to High
	PriorityHigh
)

type SMTPClient

type SMTPClient struct {
	Client      *smtpClient
	SendTimeout time.Duration
	KeepAlive   bool
	// contains filtered or unexported fields
}

SMTPClient represents a SMTP Client for send email

func (*SMTPClient) Close

func (smtpClient *SMTPClient) Close() error

Close closes the connection

func (*SMTPClient) Noop

func (smtpClient *SMTPClient) Noop() error

Noop send NOOP command to smtp client

func (*SMTPClient) Quit

func (smtpClient *SMTPClient) Quit() error

Quit send QUIT command to smtp client

func (*SMTPClient) Reset

func (smtpClient *SMTPClient) Reset() error

Reset send RSET command to smtp client

type SMTPServer

type SMTPServer struct {
	Authentication AuthType
	Encryption     Encryption
	Username       string
	Password       string
	Helo           string
	ConnectTimeout time.Duration
	SendTimeout    time.Duration
	Host           string
	Port           int
	KeepAlive      bool
	TLSConfig      *tls.Config

	// use custom dialer
	CustomConn net.Conn
}

SMTPServer represents a SMTP Server If authentication is CRAM-MD5 then the Password is the Secret

func NewSMTPClient

func NewSMTPClient() *SMTPServer

NewSMTPClient returns the client for send email

func (*SMTPServer) Connect

func (server *SMTPServer) Connect() (*SMTPClient, error)

Connect returns the smtp client

func (*SMTPServer) GetEncryptionType added in v2.8.0

func (server *SMTPServer) GetEncryptionType() Encryption

GetEncryptionType returns the encryption type used to connect to SMTP server

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL