email

package module
v0.2.1 Latest Latest
Warning

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

Go to latest
Published: Mar 12, 2020 License: Apache-2.0 Imports: 16 Imported by: 0

README

A Go package for composing and sending email messages

Release GoDoc  Build Status Coverage Status Go Report Card

This package implements a simple yet powerful API for email message composition and sending via an authenticating SMTP server, in Go.

Project Status

v0.2.1 Edge: Breaking changes to the API unlikely but possible until the v1.0 release. May be robust enough to use in production, though provided on "AS IS" basis. Vendoring recommended.

This package is under active development. If you encounter any problems or have any suggestions for improvement, please open an issue. Pull requests are welcome.

Overview

This package provides a fluid API for composing and sending email messages.

Any application needs one (and usually only one) Sender, representing an SMTP account connection information plus a sender Address.

A Message contains all the information required to create an email message. Usually, at least some parts of each message are templates to be filled with data from the rest of the application. Also, it is often convenient to define base messages on program initialization, and clone them for fine-tuning and send-out when needed.

Below is an overly-simplified example, to showcase the basic functionality. Note that by not defining From: and To: addresses for a message, they default to the sender address, which is convenient for system messaging.

package main

import (
	"log"

	"github.com/agext/email"
)

var (
	host               = "smtp.example.com"
	user               = "username"
	pass               = "password"
	name               = "Application mail"
	addr               = "app@example.com"
	sender             *email.Sender
	contactFormMessage *email.Message
)

func main() {
	var err error
	// create a sender with a given configuration
	sender, err = email.NewSender(host, user, pass, name, addr)
	if err != nil {
		log.Fatalln("invalid sender configuration: " + err.Error())
	}

	// create a message from scratch, to be used as a base for the actual messages
	contactFormMessage = email.NewMessage(nil).
		SubjectTemplate("Contact form message from {{.first}} {{.last}}").
		TextTemplate(`
First Name:   {{.first}}
Last Name:    {{.last}}
Phone:        {{.phone}}
Email:        {{.email}}
`)

	// ...
}

func sendContact(data map[string]interface{}) error {
	// create a message from the base we created in main() - basically, clone all its data
	msg := email.NewMessage(contactFormMessage)

	// customize / adapt the message as needed...
	// if the base messages are well thought out, the need should be minimal, if at all
	// as an example, we could set the To: address based on the form data, to dispatch the messages
	// to the person in the company who is most capable to handle it.

	// send the message after composing it with the provided data
	err := sender.Send(msg, data)

	if err != nil {
		log.Println(err, msg.Errors())
	}

	return err
}

Installation

go get github.com/agext/email

License

Package email is released under the Apache 2.0 license. See the LICENSE file for details.

Documentation

Overview

Package email provides a fluid API for composing and sending email messages.

Any application needs one (and usually only one) Sender, representing an SMTP account connection information plus a sender Address.

A Message contains all the information required to create an email message. Usually, at least some parts of each message are templates to be filled with data from the rest of the application. Also, it is often convenient to define base messages on program initialization, and clone them for fine-tuning and send-out when needed.

Below is an overly-simplified example, to showcase the basic functionality. Note that by not defining From: and To: addresses for a message, they default to the sender address, which is convenient for system messaging.

package main

import (
	"log"

	"github.com/agext/email"
)

var (
	host               = "smtp.example.com"
	user               = "username"
	pass               = "password"
	name               = "Application mail"
	addr               = "app@example.com"
	sender             *email.Sender
	contactFormMessage *email.Message
)

func main() {
	var err error
	// create a sender with a given configuration
	sender, err = email.NewSender(host, user, pass, name, addr)
	if err != nil {
		log.Fatalln("invalid sender configuration: " + err.Error())
	}

	// create a message from scratch, to be used as a base for the actual messages
	contactFormMessage = email.NewMessage(nil).
		SubjectTemplate("Contact form message from {{.first}} {{.last}}").
		TextTemplate(`
First Name:   {{.first}}
Last Name:    {{.last}}
Phone:        {{.phone}}
Email:        {{.email}}
`)

	// ...
}

func sendContact(data map[string]interface{}) error {
	// create a message from the base we created in main() - basically, clone all its data
	msg := email.NewMessage(contactFormMessage)

	// customize / adapt the message as needed...
	// if the base messages are well thought out, the need should be minimal, if at all
	// as an example, we could set the To: address based on the form data, to dispatch the messages
	// to the person in the company who is most capable to handle it.

	// send the message after composing it with the provided date
	err := sender.Send(msg, data)

	if err != nil {
		log.Println(err, msg.Errors())
	}

	return err
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Base64Encode

func Base64Encode(src []byte) []byte

Base64Encode encodes the src data using the base64 content transfer encoding specified by RFC 2045. The result is the equivalent of base64-encoding src using StdEncoding from the standard package encoding/base64, then breaking it into lines of maximum 76 characters, separated by CRLF. Besides convenience, this function also has the advantage of combining the encoding and line-breaking steps into a single pass, with a single buffer allocation.

func QEncode

func QEncode(src []byte, offset int) (dst []byte, pos int)

QEncode encodes the src data using the q-encoding encoded-word syntax specified by RFC 2047. Since RFC 2047 requires that each line of a header that includes encoded-word text be no longer than 76, this function takes an offset argument for the length of the current header line already used up, e.g. by the header name, colon and space.

func QEncodeIfNeeded

func QEncodeIfNeeded(src []byte, offset int) (dst []byte)

QEncodeIfNeeded q-encodes the src data only if it contains 'unsafe' characters.

func QuotedPrintableEncode

func QuotedPrintableEncode(src []byte) []byte

QuotedPrintableEncode encodes the src data using the quoted-printable content transfer encoding specified by RFC 2045. Although RFC 2045 does not require that UTF multi-byte characters be kept on the same line of encoded text, this function does so.

func SeemsValidAddr

func SeemsValidAddr(addr string) bool

SeemsValidAddr does a very loose check on addr, to weed out obviously invalid addresses. This function only checks that addr contains one and only one '@', followed by a domain name that has a TLD part.

func Send

func Send(msg *Message, data interface{}) error

Send composes the provided message using the `data`, and sends it using the default Sender.

Types

type Address

type Address struct {
	Name string
	Addr string
}

Address represents a human-friendly email address: a name plus the actual address.

func NewAddress

func NewAddress(name, addr string) (*Address, error)

NewAddress creates a new Address enforcing a very basic validity check - see `SeemsValidAddr`.

func (*Address) Clone

func (a *Address) Clone() *Address

Clone creates a new Address with the same contents as the receiver.

func (*Address) Domain

func (a *Address) Domain() string

Domain extracts the domain portion of the email address in the receiver.

type CTE

type CTE byte

CTE represents a "Content-Transfer-Encoding" method identifier.

const (
	// AutoCTE leaves it up to the package to determine CTE
	AutoCTE CTE = iota
	// QuotedPrintable indicates "quoted-printable" CTE
	QuotedPrintable
	// Base64 indicates "base64" CTE
	Base64
)

type Message

type Message struct {
	sync.RWMutex
	// contains filtered or unexported fields
}

Message represents all the information necessary for composing an email message with optional external data, and sending it via a Sender.

func NewMessage

func NewMessage(msg *Message) *Message

NewMessage creates a new Message, deep-copying from `msg`, if provided.

func QuickMessage

func QuickMessage(subject string, body ...string) *Message

QuickMessage creates a Message with the subject and the body provided. Alternative text and HTML body versions can be provided, in this order.

func (*Message) Attach

func (m *Message) Attach(file ...string) *Message

Attach attaches the files provided as filesystem paths.

func (*Message) AttachFile

func (m *Message) AttachFile(name, ctype, file string) *Message

AttachFile attaches a file specified by its filesystem path, setting its name and type to the provided values.

func (*Message) AttachObject

func (m *Message) AttachObject(name, ctype string, data []byte) *Message

AttachObject creates an attachment with the name, type and data provided.

func (*Message) Bcc

func (m *Message) Bcc(addr ...*Address) *Message

Bcc sets the (optional) Bcc: email addresses. Last call overrides any previous calls, replacing rather than adding to the list.

func (*Message) Cc

func (m *Message) Cc(addr ...*Address) *Message

Cc sets the (optional) Cc: email addresses. Last call overrides any previous calls, replacing rather than adding to the list.

func (*Message) Compose

func (m *Message) Compose(data interface{}) []byte

Compose merges the `data` into the receiver's templates and creates the body of the SMTP message to be sent.

func (*Message) Domain

func (m *Message) Domain(domain string) *Message

Domain sets the domain portion of the generated message Id.

If not specified, the domain is extracted from the sender email address - which is the right choice for most applications.

func (*Message) Errors

func (m *Message) Errors() (errs []error)

Errors returns the list of errors associated with the receiver, then resets the internal list.

func (*Message) From

func (m *Message) From(addr *Address) *Message

From sets the From: email address.

func (*Message) FromAddr

func (m *Message) FromAddr() string

FromAddr returns the email address that the message would be sent from.

func (*Message) HasErrors

func (m *Message) HasErrors() bool

HasErrors checks if there are any errors associated with the receiver

func (*Message) Html

func (m *Message) Html(html interface{}, related ...Related) *Message

Html sets the HTML version of the message body to the provided content. Optionally, related objects can be specified for inclusion.

func (*Message) HtmlTemplate

func (m *Message) HtmlTemplate(tpl string, related ...Related) *Message

HtmlTemplate sets the HTML version of the message body to the provided template. Optionally, related objects can be specified for inclusion.

func (*Message) Part

func (m *Message) Part(ctype string, cte CTE, bytes []byte, related ...Related) *Message

Part adds an alternative part to the message. For a plain-text and/or an HTML body use the convenience methods: Text, TextTemplate, Html or HtmlTemplate.

func (*Message) Prepare

func (m *Message) Prepare() *Message

Prepare reads all the files referenced by the message at attachments or related items.

If the message was already prepared and no new files have been added, it is no-op.

func (*Message) PrepareFresh

func (m *Message) PrepareFresh() *Message

PrepareFresh forces a new preparation of the message, even if there were no changes to the referred files since the previous one.

func (*Message) RecipientAddrs

func (m *Message) RecipientAddrs() []string

RecipientAddrs returns a list of email addresses with all the recipients for the message.

It includes addresses from the To, CC and BCC fields.

func (*Message) ReplyTo

func (m *Message) ReplyTo(addr *Address) *Message

ReplyTo sets the (optional) Reply-To: email address. A `*Address` argument is expected for consistency, although only the email address part is used.

func (*Message) Sender

func (m *Message) Sender(s *Sender) *Message

func (*Message) Subject

func (m *Message) Subject(subject interface{}) *Message

Subject sets the text for the subject of the message.

func (*Message) SubjectTemplate

func (m *Message) SubjectTemplate(tpl string) *Message

SubjectTemplate sets a template for the subject of the message.

func (*Message) Text

func (m *Message) Text(text interface{}) *Message

Text sets the plain-text version of the message body to the provided content.

func (*Message) TextTemplate

func (m *Message) TextTemplate(tpl string) *Message

TextTemplate sets the plain-text version of the message body to the provided template.

func (*Message) To

func (m *Message) To(addr ...*Address) *Message

To sets the To: email address(es). Last call overrides any previous calls, replacing rather than adding to the list.

type Related struct {
	// contains filtered or unexported fields
}

Related represents a multipart/related item.

func RelatedFile

func RelatedFile(id, ctype, file string) Related

RelatedFile creates a Related structure from the provided file information.

func RelatedObject

func RelatedObject(id, ctype string, data []byte) Related

RelatedObject creates a Related structure from the provided data.

type Sender

type Sender struct {
	// contains filtered or unexported fields
}

Sender represents the SMTP credentials along with the (optional) Address of a sender.

func NewSender

func NewSender(host, user, pass string, addr ...string) (*Sender, error)

NewSender creates a new Sender from the provided information.

The `host` may include a port number, which defaults to 25. That is, "example.com" and "example.com:25" are equivalent. The `addr` parameters are optional and may be either an email address or a name followed by an email address.

func (*Sender) Send

func (s *Sender) Send(msg *Message, data interface{}) error

Send composes the provided message using the `data`, and sends it.

func (*Sender) SetDefault

func (s *Sender) SetDefault() *Sender

SetDefault sets the receiver as the default sender.

Jump to

Keyboard shortcuts

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