mail

package
v1.4.6 Latest Latest
Warning

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

Go to latest
Published: Aug 8, 2025 License: BSD-3-Clause Imports: 31 Imported by: 0

Documentation

Overview

Package mail provides comprehensive email sending and SMTP server functionality with support for templates, queuing, and notification handling.

Features:

  • SMTP client for sending emails with various authentication methods
  • SMTP server for receiving emails with notification handlers
  • HTML template support with embedded and custom templates
  • Queue integration for asynchronous email processing
  • TLS/STARTTLS encryption support
  • Attachment support
  • Statistics tracking
  • Retry mechanisms with exponential backoff

Example Usage:

package main

import (
	"context"
	"time"

	"github.com/Valentin-Kaiser/go-core/mail"
	"github.com/Valentin-Kaiser/go-core/queue"
)

func main() {
	// Create mail configuration
	config := mail.DefaultConfig()
	config.SMTP.Host = "smtp.gmail.com"
	config.SMTP.Port = 587
	config.SMTP.Username = "your-email@gmail.com"
	config.SMTP.Password = "your-password"
	config.SMTP.From = "noreply@example.com"
	config.SMTP.Auth = true
	config.SMTP.Encryption = "STARTTLS"

	// Create queue manager
	queueManager := queue.NewManager()

	// Create mail manager
	mailManager := mail.NewManager(config, queueManager)

	// Start the manager
	ctx := context.Background()
	if err := mailManager.Start(ctx); err != nil {
		panic(err)
	}
	defer mailManager.Stop(ctx)

	// Send a simple email
	message := mail.NewMessage().
		To("recipient@example.com").
		Subject("Test Email").
		TextBody("Hello, this is a test email!").
		Build()

	if err := mailManager.Send(ctx, message); err != nil {
		panic(err)
	}

	// Send an email with template
	templateMessage := mail.NewMessage().
		To("user@example.com").
		Subject("Welcome!").
		Template("welcome.html", map[string]interface{}{
			"FirstName":     "John",
			"ActivationURL": "https://example.com/activate?token=abc123",
		}).
		Build()

	if err := mailManager.SendAsync(ctx, templateMessage); err != nil {
		panic(err)
	}
}

SMTP Server Example:

config := mail.DefaultConfig()
config.Server.Enabled = true
config.Server.Host = "localhost"
config.Server.Port = 2525
config.Server.Domain = "example.com"
config.Server.Auth = true
config.Server.Username = "admin"
config.Server.Password = "password"

mailManager := mail.NewManager(config, nil)

// Add notification handler
mailManager.AddNotificationHandler(func(ctx context.Context, from string, to []string, data []byte) error {
	log.Printf("Received email from %s to %v", from, to)
	return nil
})

if err := mailManager.Start(ctx); err != nil {
	panic(err)
}

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func NewLoginAuth

func NewLoginAuth(username, password string) smtp.Auth

NewLoginAuth creates a new LOGIN authenticator

Types

type Attachment

type Attachment struct {
	// Filename is the name of the file
	Filename string `json:"filename"`
	// ContentType is the MIME content type
	ContentType string `json:"content_type"`
	// Content is the file content
	Content []byte `json:"content,omitempty"`
	// Reader is an alternative to Content for streaming large files
	Reader io.Reader `json:"-"`
	// Size is the size of the attachment in bytes
	Size int64 `json:"size"`
	// Inline indicates if the attachment should be displayed inline
	Inline bool `json:"inline"`
	// ContentID is used for inline attachments
	ContentID string `json:"content_id,omitempty"`
}

Attachment represents a file attachment

type AuthMethod

type AuthMethod string

AuthMethod represents SMTP authentication methods

const (
	// AuthMethodPlain represents PLAIN authentication
	AuthMethodPlain AuthMethod = "PLAIN"
	// AuthMethodCRAMMD5 represents CRAM-MD5 authentication
	AuthMethodCRAMMD5 AuthMethod = "CRAMMD5"
	// AuthMethodLogin represents LOGIN authentication
	AuthMethodLogin AuthMethod = "LOGIN"
)

type ClientConfig added in v1.4.1

type ClientConfig struct {
	// Host is the SMTP server hostname
	Host string `yaml:"host" json:"host"`
	// Port is the SMTP server port
	Port int `yaml:"port" json:"port"`
	// Username for SMTP authentication
	Username string `yaml:"username" json:"username"`
	// Password for SMTP authentication
	Password string `yaml:"password" json:"password"`
	// From address for outgoing emails
	From string `yaml:"from" json:"from"`
	// FQDN for HELO command
	FQDN string `yaml:"fqdn" json:"fqdn"`
	// Authentication enabled
	Auth bool `yaml:"auth" json:"auth"`
	// AuthMethod defines the authentication method (PLAIN, CRAMMD5, LOGIN)
	AuthMethod string `yaml:"auth_method" json:"auth_method"`
	// Encryption method (NONE, STARTTLS, TLS)
	Encryption string `yaml:"encryption" json:"encryption"`
	// SkipCertificateVerification skips TLS certificate verification
	SkipCertificateVerification bool `yaml:"skip_cert_verification" json:"skip_cert_verification"`
	// Timeout for SMTP operations
	Timeout time.Duration `yaml:"timeout" json:"timeout"`
	// MaxRetries for failed email sending
	MaxRetries int `yaml:"max_retries" json:"max_retries"`
	// RetryDelay between retries
	RetryDelay time.Duration `yaml:"retry_delay" json:"retry_delay"`
}

ClientConfig holds the SMTP client configuration for sending emails

func (*ClientConfig) TLSConfig added in v1.4.1

func (c *ClientConfig) TLSConfig() *tls.Config

TLSConfig returns a TLS configuration for the SMTP client

func (*ClientConfig) Validate added in v1.4.1

func (c *ClientConfig) Validate() error

type Config

type Config struct {
	// SMTP Client Configuration
	Client ClientConfig `yaml:"smtp" json:"smtp"`
	// SMTP Server Configuration
	Server ServerConfig `yaml:"server" json:"server"`
	// Queue Configuration
	Queue QueueConfig `yaml:"queue" json:"queue"`
	// Templates Configuration
	Templates TemplateConfig `yaml:"templates" json:"templates"`
}

Config holds the configuration for the mail package

func DefaultConfig

func DefaultConfig() *Config

DefaultConfig returns a default configuration

func (*Config) Validate added in v1.4.1

func (c *Config) Validate() error

type EncryptionMethod

type EncryptionMethod string

EncryptionMethod represents SMTP encryption methods

const (
	// EncryptionNone represents no encryption
	EncryptionNone EncryptionMethod = "NONE"
	// EncryptionSTARTTLS represents STARTTLS encryption
	EncryptionSTARTTLS EncryptionMethod = "STARTTLS"
	// EncryptionTLS represents TLS encryption
	EncryptionTLS EncryptionMethod = "TLS"
)

type LoginAuth

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

LoginAuth implements LOGIN authentication for SMTP

func (*LoginAuth) Next

func (a *LoginAuth) Next(fromServer []byte, more bool) ([]byte, error)

Next handles the LOGIN authentication process

func (*LoginAuth) Start

func (a *LoginAuth) Start(_ *smtp.ServerInfo) (string, []byte, error)

Start begins the LOGIN authentication

type Manager

type Manager struct {
	TemplateManager *TemplateManager
	// contains filtered or unexported fields
}

Manager manages email sending and SMTP server functionality

func NewManager

func NewManager(config *Config, queueManager *queue.Manager) *Manager

NewManager creates a new mail manager

func (*Manager) AddNotificationHandler

func (m *Manager) AddNotificationHandler(handler NotificationHandler) error

AddNotificationHandler adds a notification handler to the SMTP server

func (*Manager) GetStats

func (m *Manager) GetStats() *Stats

GetStats returns the current mail statistics

func (*Manager) IsRunning

func (m *Manager) IsRunning() bool

IsRunning returns true if the mail manager is running

func (*Manager) NotifyMessageReceived

func (m *Manager) NotifyMessageReceived()

NotifyMessageReceived notifies that a message was received by the SMTP server

func (*Manager) ReloadTemplates

func (m *Manager) ReloadTemplates() error

ReloadTemplates reloads all templates

func (*Manager) Send

func (m *Manager) Send(ctx context.Context, message *Message) error

Send sends an email message synchronously

func (*Manager) SendAsync

func (m *Manager) SendAsync(ctx context.Context, message *Message) error

SendAsync sends an email message asynchronously using the queue

func (*Manager) SendTestEmail

func (m *Manager) SendTestEmail(ctx context.Context, to string) error

SendTestEmail sends a test email

func (*Manager) Start

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

Start starts the mail manager

func (*Manager) Stop

func (m *Manager) Stop(ctx context.Context) error

Stop stops the mail manager

func (*Manager) WithFS

func (m *Manager) WithFS(filesystem fs.FS) *Manager

WithFS configures the template manager to load templates from a filesystem

func (*Manager) WithFileServer

func (m *Manager) WithFileServer(templatesPath string) *Manager

WithFileServer configures the template manager to load templates from a file path

type Message

type Message struct {
	// ID is a unique identifier for the message
	ID string `json:"id"`
	// From is the sender's email address
	From string `json:"from"`
	// To is a list of recipient email addresses
	To []string `json:"to"`
	// CC is a list of carbon copy recipient email addresses
	CC []string `json:"cc,omitempty"`
	// BCC is a list of blind carbon copy recipient email addresses
	BCC []string `json:"bcc,omitempty"`
	// ReplyTo is the reply-to email address
	ReplyTo string `json:"reply_to,omitempty"`
	// Subject is the email subject
	Subject string `json:"subject"`
	// TextBody is the plain text body of the email
	TextBody string `json:"text_body,omitempty"`
	// HTMLBody is the HTML body of the email
	HTMLBody string `json:"html_body,omitempty"`
	// Template is the name of the template to use
	Template string `json:"template,omitempty"`
	// TemplateData is the data to pass to the template
	TemplateData interface{} `json:"template_data,omitempty"`
	// Attachments is a list of file attachments
	Attachments []Attachment `json:"attachments,omitempty"`
	// Headers contains additional email headers
	Headers map[string]string `json:"headers,omitempty"`
	// Priority is the message priority
	Priority Priority `json:"priority"`
	// CreatedAt is when the message was created
	CreatedAt time.Time `json:"created_at"`
	// ScheduleAt is when the message should be sent (optional)
	ScheduleAt *time.Time `json:"schedule_at,omitempty"`
	// Metadata contains additional metadata
	Metadata map[string]string `json:"metadata,omitempty"`
}

Message represents an email message

type MessageBuilder

type MessageBuilder struct {
	Error error // Error is used to capture any errors during building
	// contains filtered or unexported fields
}

MessageBuilder provides a fluent interface for building messages

func NewMessage

func NewMessage() *MessageBuilder

NewMessage creates a new message builder

func (*MessageBuilder) Attach

func (b *MessageBuilder) Attach(attachment Attachment) *MessageBuilder

Attach adds a file attachment

func (*MessageBuilder) AttachFile

func (b *MessageBuilder) AttachFile(fileHeader *multipart.FileHeader) *MessageBuilder

AttachFile adds a file attachment from a multipart file header Returns the builder for chaining. If an error occurs, it logs the error and continues without adding the attachment.

func (*MessageBuilder) AttachInline

func (b *MessageBuilder) AttachInline(filename, contentType, contentID string, content []byte) *MessageBuilder

AttachInline adds an inline file attachment with Content-ID for embedding in HTML

func (*MessageBuilder) AttachInlineFromReader

func (b *MessageBuilder) AttachInlineFromReader(filename, contentType, contentID string, reader io.Reader, size int64) *MessageBuilder

AttachInlineFromReader adds an inline file attachment from a reader with Content-ID for embedding in HTML

func (*MessageBuilder) BCC

func (b *MessageBuilder) BCC(bcc ...string) *MessageBuilder

BCC sets the blind carbon copy recipient email addresses

func (*MessageBuilder) Build

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

Build returns the built message

func (*MessageBuilder) CC

func (b *MessageBuilder) CC(cc ...string) *MessageBuilder

CC sets the carbon copy recipient email addresses

func (*MessageBuilder) From

func (b *MessageBuilder) From(from string) *MessageBuilder

From sets the sender's email address

func (*MessageBuilder) HTMLBody

func (b *MessageBuilder) HTMLBody(html string) *MessageBuilder

HTMLBody sets the HTML body

func (*MessageBuilder) Header

func (b *MessageBuilder) Header(key, value string) *MessageBuilder

Header sets a custom header

func (*MessageBuilder) Metadata

func (b *MessageBuilder) Metadata(key, value string) *MessageBuilder

Metadata sets metadata for the message

func (*MessageBuilder) Priority

func (b *MessageBuilder) Priority(priority Priority) *MessageBuilder

Priority sets the message priority

func (*MessageBuilder) ReplyTo

func (b *MessageBuilder) ReplyTo(replyTo string) *MessageBuilder

ReplyTo sets the reply-to email address

func (*MessageBuilder) ScheduleAt

func (b *MessageBuilder) ScheduleAt(scheduleAt time.Time) *MessageBuilder

ScheduleAt sets when the message should be sent

func (*MessageBuilder) Subject

func (b *MessageBuilder) Subject(subject string) *MessageBuilder

Subject sets the email subject

func (*MessageBuilder) Template

func (b *MessageBuilder) Template(name string, data interface{}) *MessageBuilder

Template sets the template name and data

func (*MessageBuilder) TextBody

func (b *MessageBuilder) TextBody(text string) *MessageBuilder

TextBody sets the plain text body

func (*MessageBuilder) To

func (b *MessageBuilder) To(to ...string) *MessageBuilder

To sets the recipient email addresses

type NotificationHandler

type NotificationHandler func(ctx context.Context, from string, to []string, data io.Reader) error

NotificationHandler is a function that handles incoming SMTP messages

type Priority

type Priority int

Priority represents the message priority

const (
	// PriorityLow represents low priority
	PriorityLow Priority = iota
	// PriorityNormal represents normal priority
	PriorityNormal
	// PriorityHigh represents high priority
	PriorityHigh
	// PriorityCritical represents critical priority
	PriorityCritical
)

func (Priority) String

func (p Priority) String() string

String returns the string representation of the priority

type QueueConfig

type QueueConfig struct {
	// Enabled indicates if queue processing should be used
	Enabled bool `yaml:"enabled" json:"enabled"`
	// WorkerCount is the number of workers processing mail jobs
	WorkerCount int `yaml:"worker_count" json:"worker_count"`
	// QueueName is the name of the queue for mail jobs
	QueueName string `yaml:"queue_name" json:"queue_name"`
	// Priority for mail jobs
	Priority int `yaml:"priority" json:"priority"`
	// MaxAttempts for failed mail jobs
	MaxAttempts int `yaml:"max_attempts" json:"max_attempts"`
	// JobTimeout for mail job processing
	JobTimeout time.Duration `yaml:"job_timeout" json:"job_timeout"`
}

QueueConfig holds the queue configuration for mail processing

func (*QueueConfig) Validate added in v1.4.1

func (c *QueueConfig) Validate() error

type Recipient

type Recipient struct {
	// Email is the recipient's email address
	Email string `json:"email"`

	// Name is the recipient's display name
	Name string `json:"name,omitempty"`

	// Type is the recipient type (to, cc, bcc)
	Type string `json:"type"`
}

Recipient represents an email recipient

type Sender

type Sender interface {
	// Send sends an email message
	Send(ctx context.Context, message *Message) error
	// SendAsync sends an email message asynchronously using the queue
	SendAsync(ctx context.Context, message *Message) error
}

Sender is the interface for sending emails

func NewSMTPSender

func NewSMTPSender(config ClientConfig, templateManager *TemplateManager) Sender

NewSMTPSender creates a new SMTP sender

type Server

type Server interface {
	// Start starts the SMTP server
	Start(ctx context.Context) error
	// Stop stops the SMTP server
	Stop(ctx context.Context) error
	// AddHandler adds a notification handler
	AddHandler(handler NotificationHandler)
	// IsRunning returns true if the server is running
	IsRunning() bool
}

Server is the interface for SMTP servers

func NewSMTPServer

func NewSMTPServer(config ServerConfig, manager *Manager) Server

NewSMTPServer creates a new SMTP server

type ServerConfig

type ServerConfig struct {
	// Enabled indicates if the SMTP server should be started
	Enabled bool `yaml:"enabled" json:"enabled"`
	// Host to bind the server to
	Host string `yaml:"host" json:"host"`
	// Port to bind the server to
	Port int `yaml:"port" json:"port"`
	// Domain name for the server
	Domain string `yaml:"domain" json:"domain"`
	// Authentication required for incoming messages
	Auth bool `yaml:"auth" json:"auth"`
	// Username for server authentication
	Username string `yaml:"username" json:"username"`
	// Password for server authentication
	Password string `yaml:"password" json:"password"`
	// TLS encryption enabled
	TLS bool `yaml:"tls" json:"tls"`
	// Certificate file path for TLS
	CertFile string `yaml:"cert_file" json:"cert_file"`
	// Key file path for TLS
	KeyFile string `yaml:"key_file" json:"key_file"`
	// ReadTimeout for server connections
	ReadTimeout time.Duration `yaml:"read_timeout" json:"read_timeout"`
	// WriteTimeout for server connections
	WriteTimeout time.Duration `yaml:"write_timeout" json:"write_timeout"`
	// MaxMessageBytes is the maximum size of a message
	MaxMessageBytes int64 `yaml:"max_message_bytes" json:"max_message_bytes"`
	// MaxRecipients is the maximum number of recipients per message
	MaxRecipients int `yaml:"max_recipients" json:"max_recipients"`
	// AllowInsecureAuth allows authentication over non-TLS connections
	AllowInsecureAuth bool `yaml:"allow_insecure_auth" json:"allow_insecure_auth"`
	// MaxConcurrentHandlers limits the number of concurrent notification handlers
	MaxConcurrentHandlers int `yaml:"max_concurrent_handlers" json:"max_concurrent_handlers"`
}

ServerConfig holds the SMTP server configuration

func (*ServerConfig) TLSConfig

func (c *ServerConfig) TLSConfig() *tls.Config

TLSConfig returns a TLS configuration for the SMTP server

func (*ServerConfig) Validate added in v1.4.1

func (c *ServerConfig) Validate() error

type Stats

type Stats struct {
	// SentCount is the number of emails sent
	SentCount int64 `json:"sent_count"`

	// FailedCount is the number of emails that failed to send
	FailedCount int64 `json:"failed_count"`

	// QueuedCount is the number of emails currently queued
	QueuedCount int64 `json:"queued_count"`

	// ReceivedCount is the number of emails received by the server
	ReceivedCount int64 `json:"received_count"`

	// LastSent is the timestamp of the last sent email
	LastSent *time.Time `json:"last_sent,omitempty"`

	// LastReceived is the timestamp of the last received email
	LastReceived *time.Time `json:"last_received,omitempty"`
}

Stats represents mail statistics

type TemplateConfig

type TemplateConfig struct {
	// DefaultTemplate is the name of the default template
	DefaultTemplate string `yaml:"default_template" json:"default_template"`
	// AutoReload indicates if templates should be reloaded on change
	AutoReload bool `yaml:"auto_reload" json:"auto_reload"`
	// FileSystem for loading templates (internal use - not serializable)
	FileSystem fs.FS `yaml:"-" json:"-"`
	// TemplatesPath is the path to custom email templates (used with WithFileServer)
	TemplatesPath string `yaml:"templates_path" json:"templates_path"`
}

TemplateConfig holds the template configuration

func (*TemplateConfig) Validate added in v1.4.1

func (c *TemplateConfig) Validate() error

type TemplateData

type TemplateData struct {
	// Subject is the email subject
	Subject string `json:"subject"`

	// Data is the custom data for the template
	Data interface{} `json:"data"`

	// Metadata contains additional metadata
	Metadata map[string]interface{} `json:"metadata,omitempty"`
}

TemplateData represents data passed to email templates

type TemplateManager

type TemplateManager struct {
	Error error
	// contains filtered or unexported fields
}

TemplateManager implements the TemplateManager interface

func NewTemplateManager

func NewTemplateManager(config TemplateConfig) *TemplateManager

NewTemplateManager creates a new template manager

func (*TemplateManager) LoadTemplate

func (tm *TemplateManager) LoadTemplate(name string) (*template.Template, error)

LoadTemplate loads a template by name

func (*TemplateManager) ReloadTemplates

func (tm *TemplateManager) ReloadTemplates() error

ReloadTemplates reloads all templates

func (*TemplateManager) RenderTemplate

func (tm *TemplateManager) RenderTemplate(name string, data interface{}) (string, error)

RenderTemplate renders a template with the given data

func (*TemplateManager) WithDefaultFuncs added in v1.4.1

func (tm *TemplateManager) WithDefaultFuncs() *TemplateManager

func (*TemplateManager) WithFS

func (tm *TemplateManager) WithFS(filesystem fs.FS) *TemplateManager

WithFS configures the template manager to load templates from a filesystem

func (*TemplateManager) WithFileServer

func (tm *TemplateManager) WithFileServer(templatesPath string) *TemplateManager

WithFileServer configures the template manager to load templates from a file path

func (*TemplateManager) WithTemplateFunc added in v1.4.1

func (tm *TemplateManager) WithTemplateFunc(key string, fn interface{}) *TemplateManager

Jump to

Keyboard shortcuts

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