Help us shape the future of Go! Take the 2026 Go Developer Survey

email

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Oct 28, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

Documentation

Overview

Package email provides email sending functionality for the application.

Index

Constants

View Source
const (
	StageConnect = "connect"
	StageTLS     = "tls"
	StageAuth    = "auth"
	StageSender  = "sender"
)

Stages a CheckError can report.

Variables

This section is empty.

Functions

func Check

func Check(ctx context.Context, c Config) error

Check verifies c without sending a message: connect, TLS, AUTH, MAIL FROM and RSET (never DATA). It gives up after 10 seconds. A failure is a *CheckError.

func SanitizeHeader

func SanitizeHeader(v string) (string, bool)

SanitizeHeader validates a single string as safe to substitute into an email header or subject line. CR/LF characters are the SMTP injection vector — if the input contains either, the second return value is false and callers MUST reject the entire request rather than try to scrub the string (truncating after the CR/LF would just hide the attack from a log review).

Clean inputs are returned verbatim — no trimming, no case change. The caller decides on further normalisation.

Types

type AdminAddressChangedData

type AdminAddressChangedData struct {
	SiteName  string
	Address   string
	ChangedBy string
	When      string // already formatted, UTC
	IP        string
}

AdminAddressChangedData drives admin_address_changed.html. Address is the full URL, or the path alone when the site has no base URL.

type AdminAddressSetupData

type AdminAddressSetupData struct {
	SiteName string
	Address  string
}

AdminAddressSetupData drives admin_address_setup.html.

type CheckError

type CheckError struct {
	Stage string
	Code  int
	Msg   string
	Host  string
	Port  int
	// contains filtered or unexported fields
}

CheckError describes why an SMTP connection check (or the connect phase of a send) failed. Code and Msg carry the server's reply when there was one.

func (*CheckError) Error

func (e *CheckError) Error() string

func (*CheckError) Unwrap

func (e *CheckError) Unwrap() error

func (*CheckError) UserMessage

func (e *CheckError) UserMessage() string

UserMessage is the sentence shown to the owner, for example "Could not sign in to smtp.x:587 (535 Authentication failed)."

type Config

type Config struct {
	SMTPHost     string
	SMTPPort     int
	SMTPUsername string
	SMTPPassword string
	FromAddress  string
	FromName     string
	// FromNameFromSite makes the admin's own mails (reset, invite, test) use the
	// site name they carry as the From name instead of FromName.
	FromNameFromSite bool
	// Security selects how the connection is protected. The zero value means
	// SecurityStarttls.
	Security Security
	// AllowLocalhost makes the host "localhost" count as configured (a local
	// mail sink). Set only for settings saved in the admin; env keeps the
	// historical rule that "localhost" means "not set up".
	AllowLocalhost bool
	// RootCAs overrides the system roots when verifying the server
	// certificate. Nil means system roots; tests use it for self-signed certs.
	RootCAs *x509.CertPool
}

Config holds SMTP configuration for the email service.

type FormConfirmationData

type FormConfirmationData struct {
	FormName string
	// Name is the submitter's name from a "name" field; empty when absent.
	Name     string
	Message  string
	SiteName string
}

FormConfirmationData drives form_confirmation.html. It deliberately carries no submitted values beyond the submitter's name: the message is the form's configured confirmation/success text.

type FormFieldData

type FormFieldData struct {
	Label string
	Value string
}

FormFieldData represents a single field in the form submission.

type FormSubmissionData

type FormSubmissionData struct {
	FormName      string
	FormSlug      string
	SubmissionID  string
	SubmittedAt   time.Time
	Fields        []FormFieldData
	SubmitterIP   string
	SubmitterPage string
	AdminURL      string
	SiteName      string
}

FormSubmissionData contains data for the form submission email template. SiteName is rendered into the shared base.html (<title>, header, footer attribution) and the form-submission footer line. Callers MUST populate it from cfg.Hatamoto.SiteName — empty string would surface as a blank brand in the email.

type InviteMailData

type InviteMailData struct {
	SiteName    string
	InviterName string
	Role        string
	URL         string
	ExpiresIn   string // "7 days"
}

InviteMailData drives invite.html.

type ResetMailData

type ResetMailData struct {
	SiteName  string
	URL       string
	ExpiresIn string // "1 hour"
}

ResetMailData drives password_reset.html. URL carries the one-time token.

type Security

type Security string

Security is the transport protection used for an SMTP connection.

const (
	// SecurityStarttls connects in plain text and upgrades with STARTTLS
	// (typically port 587). It is the default.
	SecurityStarttls Security = "starttls"
	// SecurityTLS wraps the connection in TLS from the first byte
	// (implicit TLS, typically port 465).
	SecurityTLS Security = "tls"
	// SecurityNone sends in plain text, for local sinks.
	SecurityNone Security = "none"
)

func (Security) Valid

func (s Security) Valid() bool

Valid reports whether s is a known security mode. The zero value is valid and means SecurityStarttls.

type SendOptions

type SendOptions struct {
	FromAddress string
	FromName    string
	ReplyTo     string
}

SendOptions overrides per-call envelope/header fields. Any empty field falls back to the service's configured default. Used by callers that need a different From identity or a Reply-To header for a specific send.

type Service

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

Service provides email sending functionality.

The configuration can be swapped in place with Reload, so every holder of the same *Service sees the change. Each public method reads one snapshot.

func NewService

func NewService(cfg Config, logger *slog.Logger) (*Service, error)

NewService creates a new email service with the given configuration.

func (*Service) Config

func (s *Service) Config() Config

Config returns a copy of the current configuration snapshot.

func (*Service) FromAddress

func (s *Service) FromAddress() string

FromAddress exposes the configured From-header address. Same rationale as FromName — plugin templates render it into footers / CAN-SPAM lines.

func (*Service) FromName

func (s *Service) FromName() string

FromName exposes the From-header display name. Plugins that render their own templates use this to keep the From identity uniform with core sends. It follows the stored site name when the config asks for that; otherwise it is whatever was configured — empty if unset.

func (*Service) IsConfigured

func (s *Service) IsConfigured() bool

IsConfigured returns true if the email service has SMTP credentials configured.

func (*Service) Reload

func (s *Service) Reload(c Config)

Reload replaces the SMTP configuration. Sends already in flight keep the snapshot they started with.

func (*Service) Send

func (s *Service) Send(ctx context.Context, to []string, subject, htmlBody, textBody string) error

Send sends an email with both HTML and plain text bodies. Returns nil on success or when the service is unconfigured / disabled.

Send is the entrypoint for callers that don't need the Message-ID.

func (*Service) SendAdminAddressChanged

func (s *Service) SendAdminAddressChanged(ctx context.Context, to string, data AdminAddressChangedData) error

SendAdminAddressChanged tells an owner the admin address changed.

func (*Service) SendAdminAddressSetup

func (s *Service) SendAdminAddressSetup(ctx context.Context, to string, data AdminAddressSetupData) error

SendAdminAddressSetup mails the owner their admin address after setup.

func (*Service) SendFormConfirmation

func (s *Service) SendFormConfirmation(ctx context.Context, to string, data FormConfirmationData) error

SendFormConfirmation emails a receipt to the person who submitted a form.

func (*Service) SendFormSubmission

func (s *Service) SendFormSubmission(ctx context.Context, to []string, data FormSubmissionData) error

SendFormSubmission sends a notification email for a new form submission.

func (*Service) SendFormSubmissionForward

func (s *Service) SendFormSubmissionForward(ctx context.Context, to []string, data FormSubmissionData, forwardedBy string) error

SendFormSubmissionForward sends a forwarded form submission to an arbitrary recipient.

func (*Service) SendInvite

func (s *Service) SendInvite(ctx context.Context, to string, data InviteMailData) error

SendInvite mails an invitation link.

func (*Service) SendPasswordReset

func (s *Service) SendPasswordReset(ctx context.Context, to string, data ResetMailData) error

SendPasswordReset mails the reset link (HTML plus a plain-text part). Like every send it is a no-op when the service is unconfigured; callers check IsConfigured first when they must tell the user.

func (*Service) SendTest

func (s *Service) SendTest(ctx context.Context, to, siteName string) error

SendTest sends the "is my SMTP configuration working" message.

func (*Service) SendTracked

func (s *Service) SendTracked(ctx context.Context, to []string, subject, htmlBody, textBody string) (string, error)

SendTracked is the Send variant that returns the generated Message-ID header value.

An empty return + nil error means the message was suppressed (service unconfigured or EMAIL_DISABLED=true).

func (*Service) SendTrackedWith

func (s *Service) SendTrackedWith(ctx context.Context, opts SendOptions, to []string, subject, htmlBody, textBody string) (string, error)

SendTrackedWith is the override-aware variant of SendTracked. Pass SendOptions{} for default behaviour identical to SendTracked.

func (*Service) SetSiteNameSource

func (s *Service) SetSiteNameSource(fn func(context.Context) string)

SetSiteNameSource installs the lookup for the owner's stored site name. With Config.FromNameFromSite it is asked at send time, so a rename applies to all mail without re-applying the configuration. Config.FromName is the fallback when the lookup returns nothing.

Directories

Path Synopsis
Package smtptest is a minimal in-process SMTP server for tests.
Package smtptest is a minimal in-process SMTP server for tests.

Jump to

Keyboard shortcuts

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