mail

package
v0.0.23 Latest Latest
Warning

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

Go to latest
Published: Dec 21, 2024 License: Apache-2.0 Imports: 13 Imported by: 0

README

Mail Package

The mail package provides a simple yet flexible email sending solution for Go applications using SMTP. It supports HTML and plain text emails, attachments, templates, and retries.

Features

  • HTML and plain text email support
  • Go template-based email composition
  • File attachments with content type detection
  • Configurable retry mechanism
  • HTML processing (optional)
  • CC, BCC, and Reply-To support
  • Multiple recipients
  • SMTP authentication

Installation

go get github.com/patrickward/hop/mail

Quick Start

// Create configuration
config := &mail.Config{
    Host:     "smtp.example.com",
    Port:     587,
    Username: "user@example.com",
    Password: "password",
    From:     "sender@example.com",
}

// Create mailer
mailer, err := mail.NewMailer(config)
if err != nil {
    log.Fatal(err)
}

// Send an email
msg, err := mail.NewMessage().
    To("recipient@example.com").
    Template("emails/welcome.tmpl").
    WithData(map[string]any{
        "name": "John",
    }).
    Build()

if err != nil {
    log.Fatal(err)
}

err = mailer.Send(msg)

Configuration

type Config struct {
    // SMTP Configuration
    Host      string        // SMTP server host
    Port      int          // SMTP server port
    Username  string       // SMTP authentication username
    Password  string       // SMTP authentication password
    From      string       // Default sender address
    AuthType  string       // Auth type (e.g., "LOGIN", "PLAIN", "NOAUTH")
    
    // Template Configuration
    TemplateFS    fs.FS    // Filesystem for templates
    TemplatePath  string   // Optional base path for templates
    
    // Retry Configuration
    RetryCount    int          // Number of retry attempts
    RetryDelay    time.Duration // Delay between retries
    
    // Optional HTML Processing
    HTMLProcessor HTMLProcessor // Optional HTML processor
}

Email Templates

Templates must define three sections:

  • subject: The email subject
  • text/plain: Plain text version of the email
  • text/html: HTML version of the email (optional)

Example template:

{{define "subject"}}Welcome to {{.Company}}{{end}}

{{define "text/plain"}}
Hello {{.Name}},

Welcome to {{.Company}}! We're glad to have you on board.

Best regards,
The Team
{{end}}

{{define "text/html"}}
<html>
<body>
    <h1>Welcome to {{.Company}}</h1>
    <p>Hello {{.Name}},</p>
    <p>We're glad to have you on board.</p>
    <p>Best regards,<br>The Team</p>
</body>
</html>
{{end}}

Working with Attachments

Basic Attachment
content := strings.NewReader("Hello World")
msg, err := mail.NewMessage().
    To("recipient@example.com").
    Template("template.tmpl").
    Attach("hello.txt", content).
    Build()
File Attachment
filename, reader, cleanup, err := mail.OpenFileAttachment("document.pdf")
if err != nil {
    log.Fatal(err)
}
defer cleanup()

msg, err := mail.NewMessage().
    To("recipient@example.com").
    Template("template.tmpl").
    Attach(filename, reader).
    Build()
Custom Content Type
msg, err := mail.NewMessage().
    To("recipient@example.com").
    Template("template.tmpl").
    AttachWithContentType("page.html", reader, gomail.TypeTextHTML).
    Build()

Advanced Usage

Multiple Recipients
msg, err := mail.NewMessage().
    To("recipient1@example.com", "recipient2@example.com").
    Cc("cc@example.com").
    Bcc("bcc@example.com").
    ReplyTo("reply@example.com").
    Template("template.tmpl").
    Build()
Multiple Templates
msg, err := mail.NewMessage().
    To("recipient@example.com").
    Template(
        "emails/header.tmpl",
        "emails/content.tmpl",
    ).
    Build()

HTML Processing

The package supports custom HTML processing through the HTMLProcessor interface:

type HTMLProcessor interface {
    Process(html string) (string, error)
}

This can be used for tasks like CSS inlining or HTML modification before sending.

Known Limitations

  1. Template Requirements

    • Templates must provide at least subject and text/plain sections
    • HTML body (text/html) is optional but recommended
  2. SMTP Support

    • Limited to SMTP protocol
    • No direct support for API-based email services
  3. Attachments

    • Files must be readable at send time
    • No automatic MIME type detection
    • File handles must be managed properly
  4. HTML Processing

    • Basic HTML support only
    • No built-in CSS inlining
    • Custom processing requires implementing HTMLProcessor interface
  5. Templates

    • All templates must be available in the provided TemplateFS
    • No dynamic template loading
    • No support for external template sources

Best Practices

  1. Template Management

    • Keep templates organized in a dedicated directory
    • Use consistent naming conventions
    • Include both HTML and plain text versions
  2. Error Handling

    • Always check Build() errors before sending
    • Implement proper retry handling for temporary failures
    • Log send failures appropriately
  3. Resource Management

    • Always use cleanup functions when working with file attachments
    • Close file handles after sending
    • Monitor SMTP connection status
  4. Security

    • Use TLS when possible
    • Protect credentials
    • Validate email addresses
    • Sanitize template data

Dependencies

Testing

The package includes both unit tests and integration tests. Integration tests require a running SMTP server (like MailPit) and can be enabled by setting the TEST_MAILPIT=1 environment variable.

Documentation

Overview

Package mail provides a simple mailer that sends emails using the SMTP protocol.

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrNoContent = errors.New("email must have either plain text or HTML body")
	ErrNoSubject = errors.New("email must have a subject")
)

Functions

func OpenFileAttachment added in v0.0.18

func OpenFileAttachment(filepath string) (string, io.Reader, func() error, error)

OpenFileAttachment is a helper that returns a file reader and a cleanup function for an attachment file. The filename is extracted from the filepath. It returns the filename, a reader for the file, a cleanup function, and an error if the file cannot be opened. It is the caller's responsibility to close the file reader after sending the email using the cleanup function.

Example:

filename, reader, cleanup, err := OpenFileAttachment("path/to/file.txt")

if err != nil {
    return err
}

defer cleanup()

msg, err := NewMessage().To("foo@example.com").Template("template.tmpl").Attach(filename, reader).Build()

Types

type Attachment

type Attachment struct {
	Filename    string
	Data        io.Reader
	ContentType gomail.ContentType
}

Attachment represents an email attachment

type Builder added in v0.0.18

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

Builder provides a fluent interface for constructing emails

func NewMessage added in v0.0.18

func NewMessage() *Builder

NewMessage creates an email builder

func (*Builder) Attach added in v0.0.18

func (b *Builder) Attach(filename string, data io.Reader) *Builder

Attach adds an attachment to the email. The data is read from the provided reader and the content type is inferred from the filename.

func (*Builder) AttachWithContentType added in v0.0.18

func (b *Builder) AttachWithContentType(filename string, data io.Reader, contentType gomail.ContentType) *Builder

AttachWithContentType adds an attachment to the email with a specific content type. The data is read from the provided reader.

func (*Builder) Bcc added in v0.0.18

func (b *Builder) Bcc(addresses ...string) *Builder

func (*Builder) Build added in v0.0.18

func (b *Builder) Build() (*Message, error)

func (*Builder) Cc added in v0.0.18

func (b *Builder) Cc(addresses ...string) *Builder

func (*Builder) ReplyTo added in v0.0.18

func (b *Builder) ReplyTo(address string) *Builder

func (*Builder) Template added in v0.0.18

func (b *Builder) Template(names ...string) *Builder

func (*Builder) To added in v0.0.18

func (b *Builder) To(addresses ...string) *Builder

func (*Builder) WithData added in v0.0.18

func (b *Builder) WithData(data any) *Builder

func (*Builder) WithTemplateData added in v0.0.18

func (b *Builder) WithTemplateData(data any) *Builder

WithTemplateData is an alias for WithData for clarity

type Config

type Config struct {
	// SMTP server configuration
	Host      string // SMTP server host
	Port      int    // SMTP server port
	Username  string // SMTP server username
	Password  string // SMTP server password
	From      string // From address
	AuthType  string // Type of SMTP authentication (see the go-mail package for options). Default is LOGIN.
	TLSPolicy int    // TLS policy for the SMTP connection (see the go-mail package for options). Default is opportunistic.

	// Template configuration
	TemplateFS      fs.FS            // File system for templates
	TemplatePath    string           // Path to the templates directory in the file system
	TemplateFuncMap template.FuncMap // Template function map that gets merged with the default function map from render

	// Retry configuration
	RetryCount int           // Number of retry attempts for sending email
	RetryDelay time.Duration // Delay between retry attempts

	// HTML processor for processing HTML content
	HTMLProcessor HTMLProcessor // HTML processor for processing HTML content

	// Company/Branding
	BaseURL         string // Base URL of the website
	CompanyAddress1 string // The first line of the company address (usually the street address)
	CompanyAddress2 string // The second line of the company address (usually the city, state, and ZIP code)
	CompanyName     string // Company name
	LogoURL         string // URL to the company logo
	SupportEmail    string // Support email address
	SupportPhone    string // Support phone number
	WebsiteName     string // Name of the website
	WebsiteURL      string // URL to the company website.

	// Links
	SiteLinks        map[string]string // Site links
	SocialMediaLinks map[string]string // Social media links
}

Config holds the mailer configuration

type DefaultHTMLProcessor

type DefaultHTMLProcessor struct{}

DefaultHTMLProcessor provides a pass-through implementation

func (*DefaultHTMLProcessor) Process

func (p *DefaultHTMLProcessor) Process(html string) (string, error)

type HTMLProcessor

type HTMLProcessor interface {
	Process(html string) (string, error)
}

HTMLProcessor defines the interface for processing HTML content

type Mailer

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

Mailer handles email sending operations

func NewMailer

func NewMailer(cfg *Config) (*Mailer, error)

NewMailer creates a new Mailer instance using the provided configuration and the default SMTP client

func NewMailerWithClient added in v0.0.18

func NewMailerWithClient(cfg *Config, client SMTPClient) *Mailer

NewMailerWithClient creates a new Mailer with a provided SMTP client

func (*Mailer) Config

func (m *Mailer) Config() *Config

Config returns the mailer configuration

func (*Mailer) NewTemplateData

func (m *Mailer) NewTemplateData() TemplateData

NewTemplateData creates a new template data map with default values

func (*Mailer) Send

func (m *Mailer) Send(msg *Message) error

Send sends an email using the provided template and data

type Message added in v0.0.18

type Message struct {
	To           StringList   // List of recipient email addresses
	Cc           StringList   // List of CC email addresses
	Bcc          StringList   // List of BCC email addresses
	Templates    StringList   // List of template names to proccess
	TemplateData any          // Data to be passed to the templates
	Attachments  []Attachment // List of attachments
	ReplyTo      string       // Reply-to email address
}

Message represents the content and recipients of an email message

type Module added in v0.0.18

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

func NewMailerModule added in v0.0.18

func NewMailerModule(config *Config) *Module

func (*Module) ID added in v0.0.18

func (m *Module) ID() string

func (*Module) Init added in v0.0.18

func (m *Module) Init() error

func (*Module) Mailer added in v0.0.18

func (m *Module) Mailer() *Mailer

func (*Module) Start added in v0.0.18

func (m *Module) Start(_ context.Context) error

func (*Module) Stop added in v0.0.18

func (m *Module) Stop(_ context.Context) error

type SMTPClient added in v0.0.18

type SMTPClient interface {
	DialAndSend(messages ...*gomail.Msg) error
}

SMTPClient defines the interface for an SMTP client, mainly used for testing

type StringList

type StringList = []string

StringList is an alias for a slice of strings

type TemplateData

type TemplateData map[string]any

func NewTemplateData

func NewTemplateData(cfg *Config) TemplateData

func (TemplateData) Merge

func (td TemplateData) Merge(data map[string]any) TemplateData

Merge combines the current TemplateData with the provided data map.

func (TemplateData) MergeKeys

func (td TemplateData) MergeKeys(data map[string]any) TemplateData

MergeKeys merges data into the template data, combining maps for existing keys instead of overwriting the entire map. This allows for more granular updates. It can merge maps for existing keys as well as add new keys.

type TemplateError added in v0.0.18

type TemplateError struct {
	TemplateName string
	OriginalErr  error
	Phase        string // "parse", "execute", "process"
}

TemplateError provides context about template errors

func (*TemplateError) Error added in v0.0.18

func (e *TemplateError) Error() string

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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