MIMEMail

package module
v1.4.0 Latest Latest
Warning

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

Go to latest
Published: Jul 31, 2020 License: BSD-4-Clause Imports: 17 Imported by: 0

README

MIMEMail

convenient formatting of MIME formatted emails

With MIMEMail you can easyly send MIME encoded emails. It supports HTML and Plaintext bodies created from go templates (or anything that can write to io.Writer). Adding attachments is of course supported, too.

How to

Simply create a new Mail struct with

  • NewMail()
  • Add Recipients (To, Cc, Bcc, etc).
  • Set the Subject
  • Add Attachments (by filename)
  • Get a Writer for the body by calling HTMLBody() or PlainTextBody()
  • Render your template into it.

Finally call

  • Bytes() to obtain the formatted email OR
  • WriteTo() to directly write it to a Writer OR
  • send it directly (via smtp.SendMail) through the Mail.SendMail() method.

See godoc for further details.

Documentation

Overview

Package MIMEMail provides convenient formatting (and sending) of MIME formatted emails.

Simply create a new Mail struct with NewMail(), add Recipients (To, Cc, Bcc, etc). Set the Subject, add Attachments (by filename), get a Writer for the body by calling HTMLBody() or PlainTextBody() and render your template into it. Finally call Bytes() to obtain the formatted email or WriteTo() to directly write it to a Writer or send it directly (via smtp.SendMail) through the Mail.SendMail() method.

You can put your mail templates into files and load / execute them using the NewTemplated() constructor (take a look at the templated package to get an an example of how to structure/organise your template folder.

Additionally an easy interface for encrypting the message using PGPMime is provided.

Example (Mime)
// create the Mail
m := NewMail()

// add Mail addresses to Address fields.
m.From("foobar", "foobar@example.com")

// you also can add mail.Address structs
addr := mail.Address{Name: "baz", Address: "baz@example.com"}
m.ToAddr(addr)

// set the subject
m.Subject = "你好 ma"

tmpl, err := template.ParseFiles("mailBody.html")
if err != nil {
	fmt.Println(err)
}

// render your template into the mail body
if err = tmpl.ExecuteTemplate(m.HTMLBody(), "body", nil); err != nil {
	fmt.Println(err)
}

auth := smtp.PlainAuth("", "foobar@example.com", "foobars password", "mail.example.com")

// directly send the mail via smtp.SendMail (uses StartTLS if available on the server).
if err := m.SendMail("mail.example.com:25", auth); err != nil {
	return
}

// alternatively, send the mail via TLSClient
cnf := &Account{
	Name: "foo bar",

	Address: "mail@example.com",
	Pass:    "foobars password",

	Server: &Server{
		Host: "mail.example.com",
		Port: "465",
	},
}

c, err := TLSClient(cnf)
if err != nil {
	fmt.Println(err)
}

if err := c.Send(m); err != nil {
	fmt.Println(err)
}
Output:

Example (Pgp)
sender := &Account{
	Name:    "Mr. Sender",
	Address: "sender@example.com",
	Pass:    "sender's mail account password",

	Key: &PGP{
		File: "sender.asc",
		Pass: "sender's key password",
	},

	Server: &Server{
		Host: "mail.example.com",
		Port: "465",
	},
}

recipient := &Account{
	Name:    "Mr. Receiver",
	Address: "receiver@example.com",

	Key: &PGP{
		File: "receiver.asc",
	},
}

m := NewMail()

// setup the mail, use which ever syntax fits you better
m.ToAddr(recipient.Addr())
m.From(sender.Name, sender.Address)
m.Subject = "PGP test mail"

bodyContent := `
	<html>
		<body>
			<h1>Hello Mr. Receiver!</h1>
		</body>
	</html>`
if _, err := m.HTMLBody().Write([]byte(bodyContent)); err != nil {
	fmt.Println(err)
}

cipherText, err := m.Encrypt(recipient, sender)
if err != nil {
	fmt.Println(err)
}

from, err := m.EffectiveSender()
if err != nil {
	fmt.Println(err)
}

c, err := TLSClient(sender)
if err != nil {
	fmt.Println(err)
}

if err := c.Write(from, m.Recipients(), cipherText); err != nil {
	fmt.Println(err)
}
Output:

Example (Templated)
sender := &Account{
	Name:    "Mr. Sender",
	Address: "sender@example.com",
	Pass:    "sender's mail account password",

	Key: &PGP{
		File: "sender.asc",
		Pass: "sender's key password",
	},

	Server: &Server{
		Host: "mail.example.com",
		Port: "465",
	},
}

cnf := templated.Config{Dir: "templated/example", Lang: "en_US"}
ctx := map[string]interface{}{
	"Name":    "Mr. Receiver",
	"Company": "MIMEMail",
}
m, err := NewTemplated(&cnf, "foo", ctx)
if err != nil {
	return
}
m.To("Mr. Receiver", "receiver@example.com")
m.From("Mr. Sender", "sender@example.com")

if err := m.SendMail("mail.example.com", sender.Auth()); err != nil {
	return
}
Output:

Index

Examples

Constants

View Source
const (
	SMTP         = "25"
	SMTPTLS      = "465"
	SMTPStartTLS = "587"
)

various smtp ports as a shorthand

Variables

This section is empty.

Functions

func CreateEntity added in v1.3.0

func CreateEntity(a *Account) (*openpgp.Entity, error)

CreateEntity creates a reciepient entity using the given account.

func CreateSigningEntity added in v1.3.0

func CreateSigningEntity(a *Account) (*openpgp.Entity, error)

CreateSigningEntity creates a signing entity for the given Account

func Encrypt added in v1.3.0

func Encrypt(out io.Writer, to *Account, signer *Account) (io.WriteCloser, error)

Encrypt encrypts (and ASCII armor encodes) the data written to the returned writer Remember to Close the writer when you are done.

func Sign added in v1.3.0

func Sign(out io.Writer, signer *Account) (io.WriteCloser, error)

Sign signs (and ASCII armor encodes) the data written to the returned writer Remember to Close the writer when you are done.

func UnPackPrivateKey added in v1.3.0

func UnPackPrivateKey(r io.Reader) (*packet.PrivateKey, error)

UnPackPrivateKey parses the ASCIIArmored data read from r as a private key.

func UnpackKey added in v1.3.0

func UnpackKey(r io.Reader) (*packet.PublicKey, error)

UnpackKey parses the ASCIIArmored data read from r.

Types

type Account added in v1.4.0

type Account struct {
	// Name will be used as the Name component of the "Name <address>" header field
	Name string

	// Address will be used as the Address component of the "Name <address>" header field
	Address string

	// Pass password to login to the server
	Pass string

	// Key holds PGP related values.
	Key *PGP

	// Server infos used to send mail from this account.
	Server *Server
}

Account holds values for a mail account

func (Account) Addr added in v1.4.0

func (a Account) Addr() mail.Address

Addr returns a mail.Address

func (Account) Auth added in v1.4.0

func (a Account) Auth() smtp.Auth

Auth returns a smtp.PlainAuth.

type AddressHeader added in v1.3.0

type AddressHeader string

AddressHeader is a dedicated type for mail AddressHeader fields.

const (
	AddrSender     AddressHeader = "Sender"
	AddrFrom       AddressHeader = "From"
	AddrTo         AddressHeader = "To"
	AddrCc         AddressHeader = "Cc"
	AddrBcc        AddressHeader = "Bcc"
	AddrReplyTo    AddressHeader = "ReplyTo"
	AddrFollowupTo AddressHeader = "FollowupTo"
)

Valid values for mail address headers

type Addresses added in v1.3.0

type Addresses map[AddressHeader][]mail.Address

Addresses handles setting and encoding the mail address headers

func NewAddresses added in v1.3.0

func NewAddresses() Addresses

NewAddresses creates a new mail address header

func (*Addresses) AddAddress added in v1.3.0

func (a *Addresses) AddAddress(field AddressHeader, address mail.Address) error

AddAddress adds a recipient to your mail Header. Field should be a valid address field. Use the predefined Addr... constants or the corresponding methods. Adding the address will fail if field is not one of the predefined constants.

func (*Addresses) AddPerson added in v1.3.0

func (a *Addresses) AddPerson(field AddressHeader, name, address string) error

AddPerson adds the given details to the given mail header field. Field should be a valid address field. Use the predefined Addr... constants or the corresponding methods. Adding the address will fail if the field is not one of the predefined constants.

func (*Addresses) Bcc added in v1.3.0

func (a *Addresses) Bcc(name, address string) error

Bcc adds the given name, address pair to Bcc.

func (*Addresses) BccAddr added in v1.3.0

func (a *Addresses) BccAddr(address mail.Address) error

BccAddr adds the given address to Bcc.

func (*Addresses) Cc added in v1.3.0

func (a *Addresses) Cc(name, address string) error

Cc adds the given name, address pair to Cc.

func (*Addresses) CcAddr added in v1.3.0

func (a *Addresses) CcAddr(address mail.Address) error

CcAddr adds the given address to Cc.

func (Addresses) EffectiveSender added in v1.3.0

func (a Addresses) EffectiveSender() (string, error)

EffectiveSender returns the first "sender" entry, if there is none it returns the "first" from entry, if that is empty it returns a NoSender error.

func (*Addresses) FollowupTo added in v1.3.0

func (a *Addresses) FollowupTo(name, address string) error

FollowupTo adds the given name, address pair to FollowupTo.

func (*Addresses) FollowupToAddr added in v1.3.0

func (a *Addresses) FollowupToAddr(address mail.Address) error

FollowupToAddr adds the given address to FollowupTo.

func (*Addresses) From added in v1.3.0

func (a *Addresses) From(name, address string) error

From adds the given name, address pair to From.

func (*Addresses) FromAddr added in v1.3.0

func (a *Addresses) FromAddr(address mail.Address) error

FromAddr adds the given address to From.

func (Addresses) Recipients added in v1.3.0

func (a Addresses) Recipients() []string

Recipients returns just the mailaddresses of all the recipients (To, Cc, Bcc), ready to be passed to smtp.SendMail et al.

func (*Addresses) ReplyTo added in v1.3.0

func (a *Addresses) ReplyTo(name, address string) error

ReplyTo adds the given name, address pair to ReplyTo.

func (*Addresses) ReplyToAddr added in v1.3.0

func (a *Addresses) ReplyToAddr(address mail.Address) error

ReplyToAddr adds the given address to ReplyTo.

func (*Addresses) Sender added in v1.3.0

func (a *Addresses) Sender(name, address string) error

Sender adds the given name, address pair to Sender.

func (*Addresses) SenderAddr added in v1.3.0

func (a *Addresses) SenderAddr(address mail.Address) error

SenderAddr adds the given address to Sender.

func (*Addresses) To added in v1.3.0

func (a *Addresses) To(name, address string) error

To adds the given name, address pair to To.

func (*Addresses) ToAddr added in v1.3.0

func (a *Addresses) ToAddr(address mail.Address) error

ToAddr adds the given address to To.

func (Addresses) ToMimeHeader added in v1.3.0

func (a Addresses) ToMimeHeader(part textproto.MIMEHeader) textproto.MIMEHeader

ToMimeHeader packs the contents up in the given MIMEHeader or creates a new one if nil is passed.

type Client added in v1.3.0

type Client struct {
	*smtp.Client
	// contains filtered or unexported fields
}

Client establishes a connection and handles sending the MIME Message(s).

func PlainClient added in v1.4.0

func PlainClient(cnf *Account) (*Client, error)

PlainClient uses the standard smtp.Dail, so an unencrypted connection will be used. It will check wether STARTTLS is supported by the server and use it, if available.

func TLSClient added in v1.3.0

func TLSClient(cnf *Account) (*Client, error)

TLSClient establishes a TLSConnection to the Server described by config.

func (Client) Send added in v1.3.0

func (c Client) Send(m *Mail) error

Send sends the given Mail. If you have the "Sender" field set, it's first entry is used and should match the Address in auth, else the first "From" entry is used (with the same restrictions). If both are nil, a NoSender error is returned. To Send encrypted mails, use the (Client.Write / Mail.Encrypt) or (Client.W / Mail.WriteEncrypted) pairs.

func (Client) SendEncrypted added in v1.4.0

func (c Client) SendEncrypted(m *Mail, recipient, sender *Account) error

SendEncrypted sends the given mail to recipient, encrypting it with recipient's Key (which therefore cannot be nil) and signing it with sender's Key (which may also not be nil).

func (Client) W added in v1.3.0

func (c Client) W(from string, to []string) (io.WriteCloser, error)

W is the equivalent of Writer, but returns a WriteCloser that you can write your message to. Remember to close the writer when you are done writing to it.

func (Client) Write added in v1.3.0

func (c Client) Write(from string, to []string, msg []byte) error

Write sends the message with the given from / to email addresses.

type InvalidField added in v1.3.0

type InvalidField AddressHeader

InvalidField is returned by the various Addresses' From(Addr), To(Addr), ... methods if an invalid field value is provided.

func (InvalidField) Error added in v1.3.0

func (e InvalidField) Error() string

type MIMEPart added in v1.3.0

type MIMEPart struct {
	textproto.MIMEHeader
	*bytes.Buffer
}

MIMEPart wraps the MIMEPart functionality, in all likelyhood you'll never use it directly.

func NewAttachment added in v1.3.0

func NewAttachment(name string, r io.Reader) (*MIMEPart, error)

NewAttachment creates a new MIMEPart with all the necessary headers set.

func NewFile added in v1.3.0

func NewFile(file string, attachment ...string) (*MIMEPart, error)

NewFile creates a new File attachment MIMEPart with all the necessary headers set. If you pass a string as the optional attachment argument, it will be used as the filename for sending the attachment, if no such argument is passed, filepath.Base(file) will be used.

func NewHTML added in v1.3.0

func NewHTML() *MIMEPart

NewHTML creates a new MIMEPart with "Content-Type: text/html; encoding: utf-8"

func NewMIMEPart added in v1.3.0

func NewMIMEPart() *MIMEPart

NewMIMEPart creates a new blank MIMEPart.

func NewPGPBody added in v1.3.0

func NewPGPBody() *MIMEPart

NewPGPBody creates a PGP/MIME message body part.

func NewPGPVersion added in v1.3.0

func NewPGPVersion() *MIMEPart

NewPGPVersion creates a new PGP/MIME Version header.

func NewPart added in v1.3.0

func NewPart(contenttype, encoding string) *MIMEPart

NewPart creates a new MIMEPart with the given Content-Type and encoding.

func NewPlainText added in v1.3.0

func NewPlainText() *MIMEPart

NewPlainText creates a new MIMEPart with "Content-Type: text/plain; encoding: utf-8"

type Mail

type Mail struct {
	// Address Lists for the Mailheader,
	// Fields that are nil, will be ignored.
	// Use the Add_Recipient or AddAddress for convienice.
	Addresses

	// The subject Line
	Subject string
	// contains filtered or unexported fields
}

Mail represents a MIME email message and handles encoding, MIME headers and so on.

func NewMail

func NewMail() *Mail

NewMail returns a new mail object ready to use.

func NewTemplated added in v1.4.0

func NewTemplated(cnf *templated.Config, name string, data interface{}) (*Mail, error)

NewTemplated renders the template specified by config and name using data as the rendering context. The results will be put into the Subject and HTMLBody of the

returned Mail struct.

func (*Mail) AddFile added in v1.3.0

func (m *Mail) AddFile(filename string, attachmentname ...string) error

AddFile adds the file given by filename as an attachment to the mail. If you provide the optional attachmentname argument, the file will be attached with this name.

func (*Mail) AddReader added in v1.3.0

func (m *Mail) AddReader(name string, r io.Reader) error

AddReader adds the given reader as an attachment, using name as the filename.

func (*Mail) Bytes

func (m *Mail) Bytes() ([]byte, error)

Bytes returns the fully formatted complete message as a slice of bytes. This is for plain MIME mails, if you want a PGP/MIME encrypted mail, use the Encrypt method instead.

func (*Mail) Encrypt added in v1.3.0

func (m *Mail) Encrypt(to *Account, signer *Account) ([]byte, error)

Encrypt encrypts the mail with PGP/MIME using CreateEntity to obtain recpient and CreateSigningEntity to obtain the signing entity. If signer is nil, the mail will simply not be signed. The Key Fields of both to and signer must be non-nil.

func (*Mail) HTMLBody

func (m *Mail) HTMLBody() io.Writer

HTMLBody adds a HTML body part and returns a buffer that you can render your Template to.

func (*Mail) PlainTextBody

func (m *Mail) PlainTextBody() io.Writer

PlainTextBody adds a Plaintext body part and returns a buffer that you can render your Template to.

func (*Mail) SendMail

func (m *Mail) SendMail(adr string, auth smtp.Auth) error

SendMail sends the mail via smtp.SendMail (which uses StartTLS if available). If you have the Sender field set, it's first entry is used and should match the Address in auth, else the first "From" entry is used (with the same restrictions). If both are nil, a NoSender error is returned. These values are then passed on to smtp.SendMail, returning any errors it throws.

func (*Mail) WriteEncrypted added in v1.3.0

func (m *Mail) WriteEncrypted(w io.Writer, to *Account, signer *Account) error

WriteEncrypted encrypts the mail with PGP/MIME using CreateEntity to obtain the recpient and CreateSigningEntity to obtain the signing entity. If signer is nil, the mail will simply not be signed. The Key Fields of both to and signer must be non-nil.

Example
sender := &Account{
	Name:    "Mr. Sender",
	Address: "sender@example.com",
	Pass:    "sender's mail account password",

	Key: &PGP{
		File: "sender.asc",
		Pass: "sender's key password",
	},

	Server: &Server{
		Host: "mail.example.com",
		Port: "465",
	},
}

recipient := &Account{
	Name:    "Mr. Receiver",
	Address: "receiver@example.com",

	Key: &PGP{
		File: "receiver.asc",
	},
}

m := NewMail()

// setup the mail, use which ever syntax fits you better
m.ToAddr(recipient.Addr())
m.From(sender.Name, sender.Address)
m.Subject = "PGP test mail"

bodyContent := `
	<html>
		<body>
			<h1>Hello Mr. Receiver!</h1>
		</body>
	</html>`
if _, err := m.HTMLBody().Write([]byte(bodyContent)); err != nil {
	fmt.Println(err)
}

from, err := m.EffectiveSender()
if err != nil {
	fmt.Println(err)
}

c, err := TLSClient(sender)
if err != nil {
	fmt.Println(err)
}

out, err := c.W(from, m.Recipients())
if err != nil {
	fmt.Println(err)
}

if err := m.WriteEncrypted(out, recipient, sender); err != nil {
	fmt.Println(err)
}
Output:

func (*Mail) WriteTo

func (m *Mail) WriteTo(w io.Writer) error

WriteTo writes the fully formatted complete message to the given writer. This is for plain MIME mails, if you want a PGP/MIME encrypted mail, use the WriteEncrypted method instead.

type NoSender

type NoSender int

NoSender is returned when trying to send a mail with no From or Sender address set.

func (NoSender) Error

func (e NoSender) Error() string

type PGP added in v1.4.0

type PGP struct {
	// File holds the filesystem path from which the key should be read.
	// if Key field below is not empty it will take precedence.
	File string

	// Key is mostly for usage in tests, if it is not empty,
	// Open() will return a strings.Reader reading from Key.
	Key string

	// Pass holds the password to decrypt the key (if it is encrypted).
	Pass string

	// Config holds pgp config values. If it is nil sane defaults will be used.
	*packet.Config
}

PGP holds the filesystem location of an ASCII Armored PGP private key.

func (PGP) Open added in v1.4.0

func (p PGP) Open() (io.Reader, error)

type Server added in v1.4.0

type Server struct {
	Host string
	Port string

	// Config holds TLS connection configuration values.
	// if it is nil, sane defaults will be used.
	*tls.Config
}

Server holds connection details for a mail server

func (Server) Addr added in v1.4.0

func (s Server) Addr() string

Addr return the joint host:port string.

Directories

Path Synopsis
Package templated implements a lightweight mail templating mechanism.
Package templated implements a lightweight mail templating mechanism.

Jump to

Keyboard shortcuts

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