Documentation
¶
Overview ¶
Package notification provides unified HTML email sending (SMTP or SendCloud), optional persistence on mail_logs, retries, and SendCloud webhook-driven status updates.
Index ¶
- Constants
- func ApplySendCloudWebhookToMailLog(db *gorm.DB, raw []byte) error
- func GetMailLogStats(db *gorm.DB, userID uint) (map[string]int64, error)
- func InitialMailStatus(kind ProviderKind) string
- func NextMailLogSnowflakeID() int64
- func SendCloudEventToStatus(event string) string
- func UpdateMailLogStatusByMessageID(db *gorm.DB, messageID, provider, status, errorMsg string) error
- type MailConfig
- type MailLog
- func CreateFailedMailLog(db *gorm.DB, userID uint, ...) (*MailLog, error)
- func CreateMailLog(db *gorm.DB, userID uint, ...) (*MailLog, error)
- func GetMailLogByMessageID(db *gorm.DB, messageID string) (*MailLog, error)
- func GetMailLogs(db *gorm.DB, userID uint, page, pageSize int) ([]MailLog, int64, error)
- type MailProvider
- type Mailer
- func NewMailer(cfg MailConfig, opts ...MailerOption) (*Mailer, error)
- func NewMailerMulti(channels []MailConfig, opts ...MailerOption) (*Mailer, error)
- func NewMailerMultiWithDB(channels []MailConfig, db *gorm.DB, userID uint, opts ...MailerOption) (*Mailer, error)
- func NewMailerMultiWithIP(channels []MailConfig, db *gorm.DB, ip string, opts ...MailerOption) (*Mailer, error)
- func NewMailerWithDB(cfg MailConfig, db *gorm.DB, userID uint, opts ...MailerOption) (*Mailer, error)
- func NewMailerWithIP(cfg MailConfig, db *gorm.DB, ip string, opts ...MailerOption) (*Mailer, error)
- type MailerOption
- type MultiChannelMailConfig
- type ParsedSender
- type ProviderKind
- type RetryPolicy
- type SMTPClient
- type SMTPConfig
- type SendCloudClient
- type SendCloudConfig
- type SendCloudWebhookEvent
Constants ¶
const ( StatusQueued = "queued" StatusSent = "sent" StatusDelivered = "delivered" StatusFailed = "failed" StatusSoftBounce = "soft_bounce" StatusBounced = "bounced" StatusInvalid = "invalid" StatusSpam = "spam" StatusClicked = "clicked" StatusOpened = "opened" StatusUnsubscribed = "unsubscribed" StatusUnknown = "unknown" )
Mail delivery / engagement status stored on MailLog. SMTP: after a successful handoff to the server we only record StatusSent (no callbacks). SendCloud: starts as StatusSent after API success; webhooks may refine to delivered, opened, etc.
Variables ¶
This section is empty.
Functions ¶
func ApplySendCloudWebhookToMailLog ¶
ApplySendCloudWebhookToMailLog maps a webhook to MailLog status and updates the row (SendCloud only).
func GetMailLogStats ¶
GetMailLogStats aggregates counts by status for a user.
func InitialMailStatus ¶
func InitialMailStatus(kind ProviderKind) string
InitialMailStatus returns the DB status right after a successful provider send.
func NextMailLogSnowflakeID ¶
func NextMailLogSnowflakeID() int64
NextMailLogSnowflakeID allocates a primary key for mail_logs (system sends or admin API).
func SendCloudEventToStatus ¶
SendCloudEventToStatus maps SendCloud webhook event codes (numeric or common names) to MailLog status.
func UpdateMailLogStatusByMessageID ¶
func UpdateMailLogStatusByMessageID(db *gorm.DB, messageID, provider, status, errorMsg string) error
UpdateMailLogStatusByMessageID updates status for SendCloud (and any provider keyed by message id). Only rows with matching provider are updated when provider is non-empty.
Types ¶
type MailConfig ¶
type MailConfig struct {
Provider string `json:"provider"` // "smtp" | "sendcloud"
Name string `json:"name"` // channel label, e.g. "primary-smtp", "backup-sendcloud"
Host string `json:"host"`
Port int64 `json:"port"`
Username string `json:"username"`
Password string `json:"password"`
APIUser string `json:"api_user"`
APIKey string `json:"api_key"`
From string `json:"from"` // 发件邮箱;也可写 RFC 格式「显示名 <email>」
FromName string `json:"from_name,omitempty"` // 可选显示名;与 From 中 Name 二选一,此项在纯邮箱 From 时生效
}
MailConfig selects provider and credentials (JSON tags for config files). Name is optional and used in mail_logs and ops logs to identify the channel when multiple are configured.
type MailLog ¶
type MailLog struct {
ID int64 `gorm:"primaryKey;autoIncrement:false" json:"id,string"`
UserID uint `gorm:"index" json:"user_id"`
Provider string `gorm:"size:32;index" json:"provider"` // smtp | sendcloud | multi
ChannelName string `gorm:"size:128;index" json:"channel_name"` // MailConfig.Name when set
ToEmail string `gorm:"index" json:"to_email"`
Subject string `json:"subject"`
Status string `gorm:"index" json:"status"`
HtmlBody string `gorm:"type:longtext" json:"html_body"` // 邮件 HTML,管理端可预览
ErrorMsg string `gorm:"type:text" json:"error_msg"`
MessageID string `gorm:"type:varchar(255);index" json:"message_id"`
IPAddress string `gorm:"size:64" json:"ip_address"`
RetryCount int `json:"retry_count"`
SentAt time.Time `json:"sent_at"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
MailLog is a persisted record of an outbound email (optional when DB is wired).
func CreateFailedMailLog ¶
func CreateFailedMailLog(db *gorm.DB, userID uint, provider, channelName, toEmail, subject, htmlBody, errMsg string, retries int, ip string) (*MailLog, error)
CreateFailedMailLog records a send that failed after all retries.
func CreateMailLog ¶
func CreateMailLog(db *gorm.DB, userID uint, provider, channelName, toEmail, subject, htmlBody, messageID, status string, ip string) (*MailLog, error)
CreateMailLog records a successful send (or send accepted by provider).
func GetMailLogByMessageID ¶
GetMailLogByMessageID returns a log by provider message id.
func GetMailLogs ¶
GetMailLogs returns paginated logs for a user.
type MailProvider ¶
type MailProvider interface {
Kind() ProviderKind
SendHTML(to, subject, htmlBody string) (messageID string, err error)
}
MailProvider sends HTML mail and reports a provider-specific message id (may be empty).
func NewProviderFromConfig ¶
func NewProviderFromConfig(cfg MailConfig) (MailProvider, error)
NewProviderFromConfig returns the provider implementation for a single MailConfig.
type Mailer ¶
type Mailer struct {
// contains filtered or unexported fields
}
Mailer sends HTML mail over one or more channels: each send round-robins the starting channel, then fails over to the rest until one succeeds or all are exhausted. Per-channel retries use RetryPolicy.
func NewMailer ¶
func NewMailer(cfg MailConfig, opts ...MailerOption) (*Mailer, error)
NewMailer builds a Mailer from a single channel config.
func NewMailerMulti ¶
func NewMailerMulti(channels []MailConfig, opts ...MailerOption) (*Mailer, error)
NewMailerMulti builds a Mailer from multiple channel configs; sends rotate and fail over on errors.
func NewMailerMultiWithDB ¶
func NewMailerMultiWithDB(channels []MailConfig, db *gorm.DB, userID uint, opts ...MailerOption) (*Mailer, error)
NewMailerMultiWithDB is like NewMailerMulti with DB and user id for logging.
func NewMailerMultiWithIP ¶
func NewMailerMultiWithIP(channels []MailConfig, db *gorm.DB, ip string, opts ...MailerOption) (*Mailer, error)
NewMailerMultiWithIP is like NewMailerMulti with DB and IP for logging.
func NewMailerWithDB ¶
func NewMailerWithDB(cfg MailConfig, db *gorm.DB, userID uint, opts ...MailerOption) (*Mailer, error)
NewMailerWithDB attaches GORM for mail_logs and sets user id for created rows.
func NewMailerWithIP ¶
func NewMailerWithIP(cfg MailConfig, db *gorm.DB, ip string, opts ...MailerOption) (*Mailer, error)
NewMailerWithIP attaches GORM and client IP for mail_logs.ip_address. 默认 mail_logs.user_id 为 0;需要关联用户时请传 WithMailLogUserID。
func (*Mailer) ChannelCount ¶
ChannelCount returns the number of configured send channels.
func (*Mailer) PrimaryProvider ¶
func (m *Mailer) PrimaryProvider() MailProvider
PrimaryProvider returns the first configured provider, or nil if none.
type MailerOption ¶
type MailerOption func(*mailerOptions)
MailerOption configures optional behaviour for Mailer.
func WithMailLogUserID ¶
func WithMailLogUserID(uid uint) MailerOption
WithMailLogUserID sets mail_logs.user_id for sends that use NewMailerMultiWithIP (no session user on mailer).
func WithRetry ¶
func WithRetry(p RetryPolicy) MailerOption
WithRetry sets retry policy (merged with defaults for zero fields if you only set MaxAttempts).
type MultiChannelMailConfig ¶
type MultiChannelMailConfig struct {
Channels []MailConfig `json:"channels"`
}
MultiChannelMailConfig is a convenience wrapper for JSON/YAML config: ordered list of channels passed to NewMailerMulti / NewMailerMultiWithDB (first channel is default primary; order is preserved for failover).
type ParsedSender ¶
type ParsedSender struct {
Envelope string // bare email only
Display string // UTF-8 display name for SendCloud fromName; may be empty
HeaderFrom string // value for MIME "From:" header (includes encoded-word if needed)
}
ParsedSender is the envelope address (SMTP MAIL FROM / SendCloud `from`) plus display name and full RFC From header line.
func ParseMailSender ¶
func ParseMailSender(fromField, nameFallback string) (ParsedSender, error)
ParseMailSender parses MailConfig.from (optional "Name <email>") and optional from_name fallback.
type ProviderKind ¶
type ProviderKind string
ProviderKind identifies how mail is sent and how status is tracked.
const ( ProviderSMTP ProviderKind = "smtp" ProviderSendCloud ProviderKind = "sendcloud" )
type RetryPolicy ¶
type RetryPolicy struct {
MaxAttempts int // total tries including the first; default 1 = no retry
InitialBackoff time.Duration // delay before 2nd attempt; default 200ms
MaxBackoff time.Duration // cap; default 5s
}
RetryPolicy controls send retries (exponential backoff between attempts).
type SMTPClient ¶
type SMTPClient struct {
Config SMTPConfig
// contains filtered or unexported fields
}
SMTPClient implements MailProvider over SMTP.
func NewSMTPClient ¶
func NewSMTPClient(config SMTPConfig) (*SMTPClient, error)
NewSMTPClient builds an SMTP mail provider.
type SMTPConfig ¶
type SMTPConfig struct {
Host string
Port int64
Username string
Password string
From string
FromName string
}
SMTPConfig holds SMTP connection settings.
type SendCloudClient ¶
type SendCloudClient struct {
Config SendCloudConfig
Client *http.Client
// contains filtered or unexported fields
}
SendCloudClient implements MailProvider via SendCloud HTTP API.
func NewSendCloudClient ¶
func NewSendCloudClient(config SendCloudConfig) (*SendCloudClient, error)
NewSendCloudClient creates a SendCloud provider with default HTTP timeout.
func (*SendCloudClient) Kind ¶
func (s *SendCloudClient) Kind() ProviderKind
Kind implements MailProvider.
type SendCloudConfig ¶
SendCloudConfig holds SendCloud API credentials.
type SendCloudWebhookEvent ¶
type SendCloudWebhookEvent struct {
Event string `json:"event"`
MessageID string `json:"messageId"`
Email string `json:"email"`
Timestamp int64 `json:"timestamp"`
SmtpStatus string `json:"smtpStatus"`
SmtpError string `json:"smtpError"`
}
SendCloudWebhookEvent is a normalized webhook payload (JSON or form).
func ParseSendCloudWebhookEvent ¶
func ParseSendCloudWebhookEvent(data []byte) (*SendCloudWebhookEvent, error)
ParseSendCloudWebhookEvent parses JSON or x-www-form-urlencoded webhook bodies.