Documentation
¶
Overview ¶
Package email provides email sending functionality for the application.
Index ¶
- Constants
- func Check(ctx context.Context, c Config) error
- func SanitizeHeader(v string) (string, bool)
- type AdminAddressChangedData
- type AdminAddressSetupData
- type CheckError
- type Config
- type FormConfirmationData
- type FormFieldData
- type FormSubmissionData
- type InviteMailData
- type ResetMailData
- type Security
- type SendOptions
- type Service
- func (s *Service) Config() Config
- func (s *Service) FromAddress() string
- func (s *Service) FromName() string
- func (s *Service) IsConfigured() bool
- func (s *Service) Reload(c Config)
- func (s *Service) Send(ctx context.Context, to []string, subject, htmlBody, textBody string) error
- func (s *Service) SendAdminAddressChanged(ctx context.Context, to string, data AdminAddressChangedData) error
- func (s *Service) SendAdminAddressSetup(ctx context.Context, to string, data AdminAddressSetupData) error
- func (s *Service) SendFormConfirmation(ctx context.Context, to string, data FormConfirmationData) error
- func (s *Service) SendFormSubmission(ctx context.Context, to []string, data FormSubmissionData) error
- func (s *Service) SendFormSubmissionForward(ctx context.Context, to []string, data FormSubmissionData, forwardedBy string) error
- func (s *Service) SendInvite(ctx context.Context, to string, data InviteMailData) error
- func (s *Service) SendPasswordReset(ctx context.Context, to string, data ResetMailData) error
- func (s *Service) SendTest(ctx context.Context, to, siteName string) error
- func (s *Service) SendTracked(ctx context.Context, to []string, subject, htmlBody, textBody string) (string, error)
- func (s *Service) SendTrackedWith(ctx context.Context, opts SendOptions, to []string, ...) (string, error)
- func (s *Service) SetSiteNameSource(fn func(context.Context) string)
Constants ¶
const ( StageConnect = "connect" StageTLS = "tls" StageAuth = "auth" StageSender = "sender" )
Stages a CheckError can report.
Variables ¶
This section is empty.
Functions ¶
func Check ¶
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 ¶
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 ¶
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 ¶
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 ¶
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" )
type SendOptions ¶
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 ¶
NewService creates a new email service with the given configuration.
func (*Service) FromAddress ¶
FromAddress exposes the configured From-header address. Same rationale as FromName — plugin templates render it into footers / CAN-SPAM lines.
func (*Service) FromName ¶
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 ¶
IsConfigured returns true if the email service has SMTP credentials configured.
func (*Service) Reload ¶
Reload replaces the SMTP configuration. Sends already in flight keep the snapshot they started with.
func (*Service) Send ¶
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 ¶
SendInvite mails an invitation link.
func (*Service) SendPasswordReset ¶
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) 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 ¶
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.