commo

package module
v0.3.0 Latest Latest
Warning

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

Go to latest
Published: May 28, 2026 License: BSD-3-Clause Imports: 13 Imported by: 3

README

commo

An email rendering and sending package that can be configured to use either SendGrid or SMTP.

Usage

First, add it to your module with go get go.rtnl.ai/commo.

import "go.rtnl.ai/commo"

// Load configuration from a .env file
conf := commo.Config{}
err := confire.Process("commo_email", &conf)
checkErr(err)

// Load templates
var templates map[string]*template.Template
templates = ... // not shown here; see `commo/commo_test.go` for full example

// Initialize commo
err = commo.Initialize(conf, templates)
checkErr(err)

// Data is a struct that has all of the required fields for the template being used
data := struct{ ContactName string }{ContactName: "User Name"}

// Create the email
email, err := commo.New("Test User <test@example.com>", "Email Subject", "template_name_no_ext", data)
checkErr(err)

// Send the email
err = email.Send()
checkErr(err)

See the test TestLiveEmails in commo_test.go for a full working example.

License

See LICENSE

Naming

See https://en.wikipedia.org/wiki/Communications_officer for information on why this library is named "COMMO".

Documentation

Overview

An email rendering and sending package that can be configured to use either SendGrid or SMTP.

Usage Example:

// Load configuration from a .env file
conf := commo.Config{}
err := confire.Process("commo_email", &conf)
checkErr(err)

// Load templates
var templates map[string]*template.Template
templates = ... // not shown here; see `commo/commo_test.go` for full example

// Initialize commo
err = commo.Initialize(conf, templates)
checkErr(err)

// Data is a struct that has all of the required fields for the template being used
data := struct{ ContactName string }{ContactName: "User Name"}

// Create the email
email, err := commo.New("Test User <test@example.com>", "Email Subject", "template_name_no_ext", data)
checkErr(err)

// Send the email
err = email.Send()
checkErr(err)

See the test TestLiveEmails() in commo_test.go for a full working example.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrIncorrectEmail     = errors.New("could not parse email address")
	ErrMissingRecipient   = errors.New("missing email recipient(s)")
	ErrMissingSender      = errors.New("missing email sender")
	ErrMissingSubject     = errors.New("missing email subject")
	ErrMissingTemplate    = errors.New("missing email template name")
	ErrNotInitialized     = errors.New("email sending method has not been configured")
	ErrTemplatesNotLoaded = errors.New("templates have not been loaded yet")
	ErrEmptyContent       = errors.New("email must have non-empty text and html content")
)
View Source
var (
	ErrConfigConflict        = errors.New("invalid configuration: cannot specify configuration for both smtp and sendgrid")
	ErrConfigCRAMMD5Auth     = errors.New("invalid configuration: smtp cram-md5 requires username and password")
	ErrConfigInitialInterval = errors.New("invalid configuration: initial interval must be greater than zero")
	ErrConfigInvalidSender   = errors.New("invalid configuration: could not parse sender email address")
	ErrConfigMaxElapsedTime  = errors.New("invalid configuration: max elapsed time must be greater than zero")
	ErrConfigMaxInterval     = errors.New("invalid configuration: max interval must be greater than zero")
	ErrConfigMissingPort     = errors.New("invalid configuration: smtp port is required")
	ErrConfigMissingSender   = errors.New("invalid configuration: sender email is required")
	ErrConfigPoolSize        = errors.New("invalid configuration: smtp connections pool size must be greater than zero")
	ErrConfigTimeout         = errors.New("invalid configuration: timeout must be greater than zero")
)

Functions

func Initialize

func Initialize(conf Config, templates map[string]*template.Template) (err error)

Initialize the package to start sending emails. If there is no valid email configuration available then configuration is gracefully ignored without error.

func MustNewSGEmail

func MustNewSGEmail(email string) *sgmail.Email

func MustNewSGEmails

func MustNewSGEmails(emails []string) []*sgmail.Email

func NewSGEmail

func NewSGEmail(email string) (_ *sgmail.Email, err error)

func NewSGEmails

func NewSGEmails(emails []string) (out []*sgmail.Email, err error)

func Render

func Render(name string, data any) (text, html []byte, err error)

Render returns the text and html executed templates for the specified name and data. Ensure that the extension is not supplied to the render method.

func RenderString

func RenderString(name string, data any) (text, html string, err error)

Render returns the text and html executed templates as strings for the specified name and data. Ensure that the extension is not supplied to the render method.

func Send

func Send(email *Email) (err error)

Send an email using the configured send methodology. Uses exponential backoff to retry multiple times on error with an increasing delay between attempts.

func WithTemplates

func WithTemplates(templates map[string]*template.Template)

Loads templates into commo's internal template storage. Useful for testing.

Types

type BackoffConfig

type BackoffConfig struct {
	Timeout         time.Duration `default:"30s" desc:"the time to wait for emails to send (default: 30 seconds)"`
	InitialInterval time.Duration `split_words:"true" default:"3s" desc:"the initial time between tries (default: 3 seconds)"`
	MaxInterval     time.Duration `split_words:"true" default:"45s" desc:"the maximum time between tries (default: 45 seconds)"`
	MaxElapsedTime  time.Duration `split_words:"true" default:"180s" desc:"the the overall maximum time to try to send emails (default: 180 seconds)"`
}

Configuration for timeouts and retries when sending emails.

func (BackoffConfig) Validate

func (c BackoffConfig) Validate() (err error)

type Config

type Config struct {
	Sender     string         `split_words:"true" desc:"the email address that messages are sent from"`
	SenderName string         `split_words:"true" desc:"the name of the sender, usually the name of the organization"`
	Testing    bool           `split_words:"true" default:"false" desc:"set the emailer to testing mode to ensure no live emails are sent"`
	SMTP       SMTPConfig     `split_words:"true"`
	SendGrid   SendGridConfig `split_words:"false"`
	Backoff    BackoffConfig  `split_words:"true"`
}

The emails config allows users to either send messages via SendGrid or via SMTP.

func (Config) Available

func (c Config) Available() bool

Returns true if either SMTP is configured or SendGrid is.

func (Config) GetSenderName

func (c Config) GetSenderName() string

func (Config) Validate

func (c Config) Validate() (err error)

type Email

type Email struct {
	Sender   string
	To       []string
	Subject  string
	Template string
	Data     any
}

func New

func New(recipient, subject, template string, data any) (*Email, error)

New creates a new email template with the currently configured sender attached. If the sender is not configured, then it is left empty; otherwise if the module has been configured and there is no sender, an error is returned.

func (*Email) Send

func (e *Email) Send() error

Helper method to send an email using the commo.Send package function.

func (*Email) ToSMTP

func (e *Email) ToSMTP() (msg *email.Email, err error)

Return an email struct that can be sent via SMTP

func (*Email) ToSendGrid

func (e *Email) ToSendGrid() (msg *sgmail.SGMailV3, err error)

Return an email struct that can be sent via SendGrid

func (*Email) Validate

func (e *Email) Validate() error

Validate that all required data is present to assemble a sendable email.

type SMTPConfig

type SMTPConfig struct {
	Host       string `` /* 139-byte string literal not displayed */
	Port       uint16 `default:"587" desc:"the port to access the smtp server on"`
	Username   string `required:"false" desc:"the username for authentication with the smtp server"`
	Password   string `required:"false" desc:"the password for authentication with the smtp server"`
	UseCRAMMD5 bool   `env:"USE_CRAM_MD5" default:"false" desc:"use CRAM-MD5 auth as defined in RFC 2195 instead of simple authentication"`
	PoolSize   int    `split_words:"true" default:"2" desc:"the smtp connection pool size to use for concurrent email sending"`
}

Configuration for sending emails via SMTP.

func (SMTPConfig) Addr

func (c SMTPConfig) Addr() string

func (SMTPConfig) Auth

func (c SMTPConfig) Auth() smtp.Auth

func (SMTPConfig) Enabled

func (c SMTPConfig) Enabled() bool

func (SMTPConfig) Pool

func (c SMTPConfig) Pool() (*email.Pool, error)

func (SMTPConfig) Validate

func (c SMTPConfig) Validate() (err error)

type SendGridConfig

type SendGridConfig struct {
	APIKey string `split_words:"true" required:"false" desc:"set the sendgrid api key to use sendgrid as the email backend"`
}

Configuration for sending emails using SendGrid.

func (SendGridConfig) Client

func (c SendGridConfig) Client() *sendgrid.Client

func (SendGridConfig) Enabled

func (c SendGridConfig) Enabled() bool

func (SendGridConfig) Validate

func (c SendGridConfig) Validate() (err error)

Jump to

Keyboard shortcuts

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