email

package
v0.0.0-...-6f8fa1e Latest Latest
Warning

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

Go to latest
Published: Dec 2, 2016 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package mail provides functions and services for sending html or text emails via encrypted or unencrypted connections.

Features: Attachments, Embedded images, HTML and text templates, Automatic encoding of special characters, SSL and TLS, Sending multiple emails with the same SMTP connection.

Daemon Manager

The daemon manager handles for each store view a mail daemon... @todo

Running one daemon

To run one daemon for a specific store view:

todo

Running multiple daemons

When you have configured different stores with different SMTP server, the daemon will check to only create one new Dialer to a SMTP server, called DialerPool.

Running 3rd party APIs

Currently supported is only the Mandrill API. Other providers will be added on request: AmazonSES, Mailgun, MailJet, SendGrid, PostMark, etc.

d := mail.NewDaemon(
	mail.SetSMTPTimeout(20),
	mail.SetScope(sm.Store())
	mail.SetMandrill(),
)

The API key must be stored in path: mail.PathSmtpMandrillAPIKey

Offline sending

If SMTP has been disabled via config key mail.PathSmtpDisable all emails will be send to a custom logger.

@todo Instead of sending the emails to a logger, we can use a web interface like mailcatcher.me to read the emails.

TODO: Think about using a queue for sending emails either an external one or the following package github.com/albrow/jobs. Think about an abstracted interface for sending email Job queque for e.g. sending emails … but we cannot require it as an dependency only for testing https://github.com/albrow/jobs

Index

Constants

View Source
const (
	PathSmtp                = "system/smtp"                   // Used for pubsub
	PathSmtpDisable         = PathSmtp + "/disable"           // Scope: Default, Website, Store
	PathSmtpHost            = PathSmtp + "/host"              // Scope: Default, Website, Store
	PathSmtpPort            = PathSmtp + "/port"              // Scope: Default, Website, Store
	PathSmtpUsername        = PathSmtp + "/username"          // Scope: Default, Website, Store
	PathSmtpPassword        = PathSmtp + "/password"          // Scope: Default, Website, Store
	PathSmtpSetReturnPath   = PathSmtp + "/set_return_path"   // Scope: Default; 0 = no, 1 = yes, 2 = specified in PathSmtpReturnPathEmail
	PathSmtpReturnPathEmail = PathSmtp + "/return_path_email" // Scope: Default; email address
	PathSmtpMandrillAPIKey  = PathSmtp + "/mandrill_api_key"  // Scope: Default, Website, Store @todo
)

PathSmtp* defines the configuration settings for a SMTP daemon.

Variables

View Source
var ErrMailChannelClosed = errors.New("The mail channel has been closed.")

ErrMailChannelClosed will be returned when the channel is closed.

View Source
var OfflineLogger log.Logger = new(log.BlackHole)

OfflineLogger represents a special email logger if mail sending has been deactivated for a scope ID. The underlying default logger is a NullLogger.

View Source
var OfflineSend gomail.SendFunc = offlineSend

OfflineSend defines a function which uses the OfflineLogger.Info function to log emails when SMTP has been disabled.

View Source
var PackageConfiguration = config.MustNewConfiguration(
	&config.Section{
		ID: "design",
		Groups: config.GroupSlice{
			&config.Group{
				ID:        "email",
				Label:     `Transactional Emails`,
				Comment:   ``,
				SortOrder: 510,
				Scope:     scope.PermStore,
				Fields: config.FieldSlice{
					&config.Field{

						ID:           "logo",
						Label:        `Logo Image`,
						Comment:      `Allowed file types: jpg, jpeg, gif, png. To optimize logo for high-resolution displays, upload an image that is 3x normal size and then specify 1x dimensions in width/height fields below.`,
						Type:         config.TypeImage,
						SortOrder:    10,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},
					&config.Field{

						ID:           "logo_alt",
						Label:        `Logo Image Alt`,
						Comment:      ``,
						Type:         config.TypeText,
						SortOrder:    20,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},
					&config.Field{

						ID:           "logo_width",
						Label:        `Logo Width`,
						Comment:      `Only necessary if image has been uploaded above. Enter number of pixels, without appending "px".`,
						Type:         config.TypeText,
						SortOrder:    30,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},
					&config.Field{

						ID:           "logo_height",
						Label:        `Logo Height`,
						Comment:      `Only necessary if image has been uploaded above. Enter number of pixels, without appending "px".`,
						Type:         config.TypeText,
						SortOrder:    40,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},
					&config.Field{

						ID:           "header_template",
						Label:        `Header Template`,
						Comment:      `Email template chosen based on theme fallback when "Default" option is selected.`,
						Type:         config.TypeSelect,
						SortOrder:    50,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      `design_email_header_template`,
						BackendModel: nil,
					},
					&config.Field{

						ID:           "footer_template",
						Label:        `Footer Template`,
						Comment:      `Email template chosen based on theme fallback when "Default" option is selected.`,
						Type:         config.TypeSelect,
						SortOrder:    60,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      `design_email_footer_template`,
						BackendModel: nil,
					},
				},
			},
		},
	},
	&config.Section{
		ID:        "trans_email",
		Label:     "Store Email Addresses",
		SortOrder: 90,
		Scope:     scope.PermStore,
		Groups: config.GroupSlice{
			&config.Group{
				ID:        "ident_custom1",
				Label:     `Custom Email 1`,
				Comment:   ``,
				SortOrder: 4,
				Scope:     scope.PermStore,
				Fields: config.FieldSlice{
					&config.Field{

						ID:           "email",
						Label:        `Sender Email`,
						Comment:      ``,
						Type:         config.TypeText,
						SortOrder:    2,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},

					&config.Field{

						ID:           "name",
						Label:        `Sender Name`,
						Comment:      ``,
						Type:         config.TypeText,
						SortOrder:    1,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},
				},
			},

			&config.Group{
				ID:        "ident_custom2",
				Label:     `Custom Email 2`,
				Comment:   ``,
				SortOrder: 5,
				Scope:     scope.PermStore,
				Fields: config.FieldSlice{
					&config.Field{

						ID:           "email",
						Label:        `Sender Email`,
						Comment:      ``,
						Type:         config.TypeText,
						SortOrder:    2,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},

					&config.Field{

						ID:           "name",
						Label:        `Sender Name`,
						Comment:      ``,
						Type:         config.TypeText,
						SortOrder:    1,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},
				},
			},

			&config.Group{
				ID:        "ident_general",
				Label:     `General Contact`,
				Comment:   ``,
				SortOrder: 1,
				Scope:     scope.PermStore,
				Fields: config.FieldSlice{
					&config.Field{

						ID:           "email",
						Label:        `Sender Email`,
						Comment:      ``,
						Type:         config.TypeText,
						SortOrder:    2,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},

					&config.Field{

						ID:           "name",
						Label:        `Sender Name`,
						Comment:      ``,
						Type:         config.TypeText,
						SortOrder:    1,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},
				},
			},

			&config.Group{
				ID:        "ident_sales",
				Label:     `Sales Representative`,
				Comment:   ``,
				SortOrder: 2,
				Scope:     scope.PermStore,
				Fields: config.FieldSlice{
					&config.Field{

						ID:           "email",
						Label:        `Sender Email`,
						Comment:      ``,
						Type:         config.TypeText,
						SortOrder:    2,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},

					&config.Field{

						ID:           "name",
						Label:        `Sender Name`,
						Comment:      ``,
						Type:         config.TypeText,
						SortOrder:    1,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},
				},
			},

			&config.Group{
				ID:        "ident_support",
				Label:     `Customer Support`,
				Comment:   ``,
				SortOrder: 3,
				Scope:     scope.PermStore,
				Fields: config.FieldSlice{
					&config.Field{

						ID:           "email",
						Label:        `Sender Email`,
						Comment:      ``,
						Type:         config.TypeText,
						SortOrder:    2,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},

					&config.Field{

						ID:           "name",
						Label:        `Sender Name`,
						Comment:      ``,
						Type:         config.TypeText,
						SortOrder:    1,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},
				},
			},
		},
	},

	&config.Section{
		ID: "system",
		Groups: config.GroupSlice{
			&config.Group{
				ID:        "smtp",
				Label:     `Mail Sending Settings`,
				Comment:   ``,
				SortOrder: 20,
				Scope:     scope.PermStore,
				Fields: config.FieldSlice{
					&config.Field{

						ID:           "disable",
						Label:        `Disable Email Communications. Output will be logged if disabled.`,
						Comment:      ``,
						Type:         config.TypeSelect,
						SortOrder:    10,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},

					&config.Field{

						ID:           "host",
						Label:        `Host`,
						Comment:      `SMTP Host`,
						Type:         config.TypeText,
						SortOrder:    20,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},

					&config.Field{

						ID:           "port",
						Label:        `Port (25)`,
						Comment:      `SMTP Port`,
						Type:         config.TypeText,
						SortOrder:    30,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},

					&config.Field{

						ID:           "username",
						Label:        `Username`,
						Comment:      `SMTP Username`,
						Type:         config.TypeText,
						SortOrder:    40,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},

					&config.Field{

						ID:           "password",
						Label:        `Password`,
						Comment:      `SMTP Passowrd`,
						Type:         config.TypeText,
						SortOrder:    40,
						Visible:      config.VisibleYes,
						Scope:        scope.PermStore,
						Default:      nil,
						BackendModel: nil,
					},

					&config.Field{

						ID:           "set_return_path",
						Label:        `Set Return-Path`,
						Comment:      ``,
						Type:         config.TypeSelect,
						SortOrder:    70,
						Visible:      config.VisibleYes,
						Scope:        scope.PermDefault,
						Default:      nil,
						BackendModel: nil,
					},

					&config.Field{

						ID:           "return_path_email",
						Label:        `Return-Path Email`,
						Comment:      ``,
						Type:         config.TypeText,
						SortOrder:    80,
						Visible:      config.VisibleYes,
						Scope:        scope.PermDefault,
						Default:      nil,
						BackendModel: nil,
					},
				},
			},
		},
	},
)

PkgLog global package based logger

Functions

This section is empty.

Types

type Daemon

type Daemon struct {

	// Config contains the config.Service
	Config config.Scoped
	// SmtpTimeout sets the time when the daemon should closes the connection
	// to the SMTP server if no email was sent in the last default 30 seconds.
	SmtpTimeout time.Duration
	// contains filtered or unexported fields
}

Daemon represents a daemon which must be created via NewDaemon() function

func NewDaemon

func NewDaemon(c config.Scoped, opts ...DaemonOption) (*Daemon, error)

NewDaemon creates a new mail sending daemon to send to a SMTP server. Per default it uses localhost:25, creates an unbuffered channel, uses the config.DefaultManager, applies the admin scope (0) and sets the SMTP timeout to 30s.

func (*Daemon) Error

func (dm *Daemon) Error() string

Error implements the error interface. Returns a string where each error has been separated by a line break.

func (*Daemon) IsOffline

func (dm *Daemon) IsOffline() bool

IsOffline checks if SMTP sending for the current scope ID has been deactivated. If disabled the output will be logged.

func (*Daemon) Send

func (dm *Daemon) Send(m *gomail.Message) error

Send sends a mail

func (*Daemon) SetOptions

func (dm *Daemon) SetOptions(opts ...DaemonOption) (previous DaemonOption)

SetOptions applies optional arguments to the daemon struct. It returns the last set option. More info about the returned function: http://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html

func (*Daemon) Stop

func (dm *Daemon) Stop() error

Stop closes the channel stops the daemon

func (*Daemon) Worker

func (dm *Daemon) Worker() error

Start listens to a channel and sends all incoming messages to a SMTP server. Errors will be logged. Use code snippet:

d := NewDaemon(...)
go func(){
	if err := d.Worker(); err != nil {
		panic(err) // for example
	}
}()
d.Send(*gomail.Message)
d.Stop()

type DaemonOption

type DaemonOption func(*Daemon) DaemonOption

DaemonOption can be used as an argument in NewDaemon to configure a daemon.

func SetDialer

func SetDialer(di Dialer) DaemonOption

SetDialer sets a custom dialer, e.g. for a different smtp.Auth use. Usually a *gomail.Dialer. If not provided falls back the plain auth dialer of gomail. Applying the SetDialer with set the sendFunc to nil.

func SetMandrill

func SetMandrill(opts ...MandrillOptions) DaemonOption

SetMandrill sets the Mandrill API for sending emails. This function is not recursive and returns nil. @todo

func SetMessageChannel

func SetMessageChannel(mailChan chan *gomail.Message) DaemonOption

SetMessageChannel sets your custom channel to listen to.

func SetSendFunc

func SetSendFunc(sf gomail.SendFunc) DaemonOption

SetSendFunc lets you implements your email-sending function for e.g. to use any other third party API provider. Setting this option will remove the dialer. Your implementation must handle timeouts, etc.

func SetTLSConfig

func SetTLSConfig(c *tls.Config) DaemonOption

SetTLSConfig sets the TLS configuration for a default plain dialer used for TLS (when the STARTTLS extension is used) or SSL connections.

type Dialer

type Dialer interface {
	// SetConfig allows instant access to the system wide configuration by the
	// current scope ID.
	SetConfig(config.Scoped)
	// Dial initiates the connection to the mail server.
	Dial() (gomail.SendCloser, error)
}

Dialer mocked out *gomail.Dialer for testing. Also includes a feature to pass the configuration manager. Sorry for the confusion but *gomail.Dialer is the wrong name because ending on "er" means interface and not a struct.

type MandrillOptions

type MandrillOptions func(*gochimp.MandrillAPI)

MandrillOptions can be used as an argument to SetMandrill() function.

func SetMandrillRoundTripper

func SetMandrillRoundTripper(transport http.RoundTripper) MandrillOptions

SetMandrillRoundTripper sets a round tripper to the MandrillAPI mainly for testing.

type Service

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

Manager represents a daemon which must be created via NewManager() function. A manager starts and stops a daemon. Restarts happens on config changes.

func NewService

func NewService(opts ...ServiceOption) (*Service, error)

func (*Service) Error

func (s *Service) Error() string

Error implements the error interface. Returns a string where each error has been separated by a line break.

func (*Service) MessageConfig

func (s *Service) MessageConfig(path string, sc scope.Type, id int64) error

MessageConfig allows subscription to the publish/subscribe message system of config.Service. MessageConfig will be added via SubscribeToConfigChanges to the config.Subscriber. IF a configuration change

func (*Service) Option

func (s *Service) Option(opts ...ServiceOption) *Service

Options applies optional arguments to the daemon struct. It returns the last set option. More info about the returned function: http://commandcenter.blogspot.com/2014/01/self-referential-functions-and-design.html

func (*Service) Send

func (s *Service) Send(sc scope.Type, id int64, m *gomail.Message) error

func (*Service) SubscribeToConfigChanges

func (s *Service) SubscribeToConfigChanges(sub config.Subscriber) (subscriptionID int, err error)

SubscribeToConfigChanges subscribes the function MessageConfig to the config.Subscriber

type ServiceOption

type ServiceOption func(*Service)

ManagerOption can be used as an argument in NewManager to configure a manager.

Jump to

Keyboard shortcuts

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