postoffice

package module
v0.0.1 Latest Latest
Warning

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

Go to latest
Published: Feb 29, 2020 License: MIT Imports: 17 Imported by: 0

README

postoffice - Simple mailing for GO

GoDoc Version

This library provides a uniform access and configuration for multiple email delivery providers. It automatically configures the providers (Carriers) from a single YAML configuration file.

Terminology

  • Letter: The mail to be sent
  • Carrier: A configured email delivery provider (currently SMTP or Gmail)
  • PostOffice: Container for the configured Carriers (optional)

Install

go get github.com/bounoable/postoffice

Usage

Read the GoDocs for more examples

  1. Create configuration
default: carrier2 # Default Carrier to use

carriers:
  carrier1: # Specify a unique Carrier name
    provider: smtp # The email delivery provider
    config: # SMTP configuration
      host: smtp.mailtrap.io
      port: 587
      username: abcdef123456
      password: 123456abcdef
  
  carrier2:
    provider: gmail
    config:
      serviceAccount: ${SERVICE_ACCOUNT_PATH} # Use environment variable
  1. Create PostOffice
package main

import (
  "net/mail"

  "github.com/bounoable/postoffice"
  "github.com/bounoable/postoffice/smtp"
  "github.com/bounoable/postoffice/gmail"
)

func main() {
    // Register providers & create config
    cfg := postoffice.NewConfig(
      smtp.Register,
      gmail.Register,
    )

    // Load YAML configuration
    err := cfg.Load("/path/to/config.yml")
    if err != nil {
      panic(err)
    }

    // Create PostOffice
    po, err := cfg.NewOffice(context.Background())
    if err != nil {
      panic(err)
    }

    // Get Carrier by name send mail
    carrier, _ := po.Carrier("carrier1")
    err = carrier.Send(
      context.Background(),
      postoffice.From(mail.Address{Name: "Bob", Address: "bob@belcher.test"}),
      postoffice.To(
        mail.Address{Name: "Calvin", Address: "calvin@fishoeder.test"},
        mail.Address{Name: "Felix", Address: "felix@fishoeder.test"},
      ),
      postoffice.BCC(mail.Address{Name: "Jimmy", Address: "jimmy@pesto.test"}),
      postoffice.Subject("Hi, buddy."),
      postoffice.Text("Have a drink later?"),
      postoffice.HTML("Have a <strong>drink</strong> later?"),
      postoffice.Attach(bytes.NewReader([]byte{1, 2, 3}), "My burger recipe"),
    )

    // or use the default Carrier
    err = po.Send(
      context.Background(),
      postoffice.From(mail.Address{Name: "Bob", Address: "bob@belcher.test"}),
      // ...
    )

    // or select the Carrier through the PostOffice
    err = po.SendWith(
      context.Background(),
      "carrier1",
      postoffice.From(mail.Address{Name: "Bob", Address: "bob@belcher.test"}),
      // ...
    )

    // or create the Letter first, then send it
    let, err := postoffice.Write(
      postoffice.From(mail.Address{Name: "Bob", Address: "bob@belcher.test"}),
      // ...
    )

    err = po.SendLetter(context.Background(), let)
}

Documentation

Overview

Package postoffice provides a uniform access and configuration for multiple email delivery providers. It automatically configures the providers (Carriers) from a single YAML configuration file.

Example

Configure PostOffice from YAML file.

package main

import (
	"bytes"
	"context"
	"net/mail"

	"github.com/bounoable/postoffice"
	"github.com/bounoable/postoffice/gmail"
	"github.com/bounoable/postoffice/smtp"
)

func main() {
	// Register providers & create config
	cfg := postoffice.NewConfig(
		smtp.Register,
		gmail.Register,
	)

	// Load YAML configuration
	err := cfg.Load("/path/to/config.yml")
	if err != nil {
		panic(err)
	}

	// Create PostOffice
	po, err := cfg.NewOffice(context.Background())
	if err != nil {
		panic(err)
	}

	// Send mail through the default carrier
	err = po.Send(
		context.Background(),
		postoffice.From(mail.Address{Name: "Bob", Address: "bob@belcher.test"}),
		postoffice.To(
			mail.Address{Name: "Calvin", Address: "calvin@fishoeder.test"},
			mail.Address{Name: "Felix", Address: "felix@fishoeder.test"},
		),
		postoffice.BCC(mail.Address{Name: "Jimmy", Address: "jimmy@pesto.test"}),
		postoffice.Subject("Hi, buddy."),
		postoffice.Text("Have a drink later?"),
		postoffice.HTML("Have a <strong>drink</strong> later?"),
		postoffice.Attach(bytes.NewReader([]byte{1, 2, 3}), "My burger recipe"),
	)

	// or use a specific Carrier
	err = po.SendWith(
		context.Background(),
		"carrier2",
		postoffice.From(mail.Address{Name: "Bob", Address: "bob@belcher.test"}),
		// ...
	)

	// or create the Letter first, then send it
	let, err := postoffice.Write(
		postoffice.From(mail.Address{Name: "Bob", Address: "bob@belcher.test"}),
		// ...
	)

	err = po.SendLetter(context.Background(), let)
}
Output:

Example (ManualConfiguration)
package main

import (
	"context"
	"net/mail"

	"github.com/bounoable/postoffice"
	"github.com/bounoable/postoffice/gmail"
	"github.com/bounoable/postoffice/smtp"
)

func main() {
	po := postoffice.New()

	gmailCarrier, _ := gmail.NewCarrier(context.Background(), gmail.CredentialsFile("/path/to/service_account.json"))

	po.Configure("carrier1", smtp.NewCarrier("smtp.mailtrap.io", 587, "abcdef123456", "123456abcdef"))
	po.Configure("carrier2", gmailCarrier, postoffice.Default()) // Make "carrier2" the default

	err := po.Send(
		context.Background(),
		postoffice.From(mail.Address{Name: "Bob", Address: "bob@belcher.test"}),
		// ...
	)

	if err != nil {
		panic(err)
	}
}
Output:

Example (UseCarrierDirectly)
package main

import (
	"context"
	"net/mail"

	"github.com/bounoable/postoffice"
	"github.com/bounoable/postoffice/gmail"
)

func main() {
	carrier, err := gmail.NewCarrier(context.Background(), gmail.CredentialsFile("/path/to/service_account.json"))

	if err != nil {
		panic(err)
	}

	let, err := postoffice.Write(
		postoffice.From(mail.Address{Name: "Bob", Address: "bob@belcher.test"}),
		// ...
	)

	if err != nil {
		panic(err)
	}

	if err := carrier.Send(context.Background(), let); err != nil {
		panic(err)
	}
}
Output:

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrUnconfiguredCarrier means a Carrier has not been registered in the PostOffice.
	ErrUnconfiguredCarrier = errors.New("unconfigured carrier")
)

Functions

func RecipientsHeader

func RecipientsHeader(recipients []mail.Address) string

RecipientsHeader builds the mail header value for the given recipients.

Types

type AttachOption

type AttachOption func(*attachConfig)

AttachOption is an attachment option.

func ContentType

func ContentType(contentType string) AttachOption

ContentType sets the Content-Type of an attachment.

type Attachment

type Attachment struct {
	Filename string
	Header   textproto.MIMEHeader
	Content  []byte
}

Attachment is a file attachment.

type Carrier

type Carrier interface {
	Send(context.Context, *Letter) error
}

Carrier is a mail carrier.

type CarrierFactory

type CarrierFactory interface {
	CreateCarrier(ctx context.Context, cfg map[string]interface{}) (Carrier, error)
}

CarrierFactory creates Carriers.

type CarrierFactoryConfig

type CarrierFactoryConfig struct {
	Provider string
	Config   map[string]interface{}
}

CarrierFactoryConfig creates Carriers.

type CarrierFactoryFunc

type CarrierFactoryFunc func(context.Context, map[string]interface{}) (Carrier, error)

CarrierFactoryFunc creates Carriers.

func (CarrierFactoryFunc) CreateCarrier

func (fn CarrierFactoryFunc) CreateCarrier(ctx context.Context, cfg map[string]interface{}) (Carrier, error)

CreateCarrier creates a Carrier.

type Config

type Config struct {
	Carriers       map[string]CarrierFactoryConfig
	Creators       map[string]CarrierFactory
	DefaultCarrier string
}

Config contains the configuration for the PostOffce creation.

func NewConfig

func NewConfig(options ...ConfigOption) *Config

NewConfig returns a new PostOffice configuration.

func (*Config) Configure

func (cfg *Config) Configure(name, provider string, config map[string]interface{})

Configure configures a Carrier.

func (*Config) Load

func (cfg *Config) Load(path string) error

Load loads the Carrier configuration from a file. It checks against provided file extensions and returns an error if the filetype is unsupported.

func (*Config) LoadYAML

func (cfg *Config) LoadYAML(path string) error

LoadYAML loads the Carrier configuration from a YAML file.

func (*Config) LoadYAMLReader

func (cfg *Config) LoadYAMLReader(r io.Reader) error

LoadYAMLReader loads the Carrier configuration from the YAML in r.

func (*Config) NewOffice

func (cfg *Config) NewOffice(ctx context.Context) (*PostOffice, error)

NewOffice creates a new PostOffice with the initialized Carriers.

func (*Config) RegisterFactory

func (cfg *Config) RegisterFactory(name string, creator CarrierFactory)

RegisterFactory registers a CarrierFactory.

type ConfigOption

type ConfigOption func(*Config)

ConfigOption is a PostOffice option.

type ConfigureOption

type ConfigureOption func(*configureConfig)

ConfigureOption is a Carrier configuration option.

func Default

func Default() ConfigureOption

Default makes the Carrier the default Carrier.

type DuplicateCarrierConfigError

type DuplicateCarrierConfigError struct {
	Name string
}

DuplicateCarrierConfigError means the YAML configuration contains multiple configurations for a Carrier name.

func (DuplicateCarrierConfigError) Error

func (err DuplicateCarrierConfigError) Error() string

type InvalidConfigValueError

type InvalidConfigValueError struct {
	CarrierName string
	ConfigKey   string
	Expected    interface{}
	Provided    interface{}
}

InvalidConfigValueError means a configuration value for a Carrier has a wrong type.

func (InvalidConfigValueError) Error

func (err InvalidConfigValueError) Error() string

type Letter

type Letter struct {
	Subject     string
	From        mail.Address
	To          []mail.Address
	CC          []mail.Address
	BCC         []mail.Address
	Text        string
	HTML        string
	Attachments []Attachment
	// contains filtered or unexported fields
}

Letter represents a mail.

func Write

func Write(options ...WriteOption) (*Letter, error)

Write writes a letter.

func (*Letter) Attach

func (let *Letter) Attach(r io.Reader, filename string, options ...AttachOption) (Attachment, error)

Attach attaches the file in r to the mail. If no contentType is provided, it is be determined by the filename's extension (if it has one). If it doesn't have a file extension, the Content-Type is detected by http.DetectContentType.

func (*Letter) AttachFile

func (let *Letter) AttachFile(path, filename string, options ...AttachOption) (Attachment, error)

AttachFile attaches the file at path to the mail. If no filename is provided, the basename of the path is used as the filename. If no contentType is provided, it is be determined by the filename's extension (if it has one). If it doesn't have a file extension, the Content-Type is detected by http.DetectContentType.

func (*Letter) RFC

func (let *Letter) RFC() string

RFC builds the mail according to the RFC 2822 spec.

func (*Letter) String

func (let *Letter) String() string

type PostOffice

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

PostOffice is a container for multiple Carriers and is itself also a Carrier. PostOffice is thread-safe (but the Carrier implementations may not).

func New

func New() *PostOffice

New returns a new PostOffice. It acts as a container for multiple Carriers and also implements the Carrier interface, so it can be used directly to send mails through the configured default Carrier.

func (*PostOffice) Carrier

func (o *PostOffice) Carrier(name string) (Carrier, error)

Carrier returns the Carrier with the given name.

func (*PostOffice) Configure

func (o *PostOffice) Configure(name string, c Carrier, options ...ConfigureOption)

Configure configures a Carrier. The first Carrier will automatically be made the default Carrier, even if the Default option is not used.

func (*PostOffice) Default

func (o *PostOffice) Default() (Carrier, error)

Default returns the default Carrier.

func (*PostOffice) Send

func (o *PostOffice) Send(ctx context.Context, options ...WriteOption) error

Send writes and sends a Letter through the default Carrier.

func (*PostOffice) SendLetter

func (o *PostOffice) SendLetter(ctx context.Context, let *Letter) error

SendLetter sends the Letter through the default Carrier.

func (*PostOffice) SendLetterWith

func (o *PostOffice) SendLetterWith(ctx context.Context, name string, let *Letter) error

SendLetterWith sends the Letter through the Carrier with the given name.

func (*PostOffice) SendWith

func (o *PostOffice) SendWith(ctx context.Context, name string, options ...WriteOption) error

SendWith writes and sends a Letter through the Carrier with the given name.

func (*PostOffice) SetDefault

func (o *PostOffice) SetDefault(name string) error

SetDefault sets the default Carrier.

type UnregisteredProviderError

type UnregisteredProviderError struct {
	Provider string
}

UnregisteredProviderError means the configuration contains a Carrier that is not registered.

func (UnregisteredProviderError) Error

func (err UnregisteredProviderError) Error() string

type WriteOption

type WriteOption func(*Letter) error

WriteOption is a write option.

func Attach

func Attach(r io.Reader, filename string, options ...AttachOption) WriteOption

Attach attaches the file in r to the mail. If no contentType is provided, it is be determined by the filename's extension (if it has one). If it doesn't have a file extension, the Content-Type is detected by http.DetectContentType.

func AttachFile

func AttachFile(path, filename string, options ...AttachOption) WriteOption

AttachFile attaches the file at path to the mail. If no filename is provided, the basename of the path is used as the filename. If no contentType is provided, it is be determined by the filename's extension (if it has one). If it doesn't have a file extension, the Content-Type is detected by http.DetectContentType.

func BCC

func BCC(recipients ...mail.Address) WriteOption

BCC adds blind carbon copy recipients to the mail.

func CC

func CC(recipients ...mail.Address) WriteOption

CC adds carbon copy recipients to the mail.

func From

func From(sender mail.Address) WriteOption

From sets the sender of the mail.

func HTML

func HTML(html string) WriteOption

HTML sets the HTML content of the mail.

func Subject

func Subject(subject string) WriteOption

Subject sets the mail's subject.

func Text

func Text(text string) WriteOption

Text sets the text content of the mail.

func To

func To(recipients ...mail.Address) WriteOption

To adds recipients to the mail.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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