notification

package
v0.0.0-...-f17429d Latest Latest
Warning

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

Go to latest
Published: Apr 26, 2026 License: GPL-3.0 Imports: 19 Imported by: 0

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

View Source
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

func ApplySendCloudWebhookToMailLog(db *gorm.DB, raw []byte) error

ApplySendCloudWebhookToMailLog maps a webhook to MailLog status and updates the row (SendCloud only).

func GetMailLogStats

func GetMailLogStats(db *gorm.DB, userID uint) (map[string]int64, error)

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

func SendCloudEventToStatus(event string) string

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

func GetMailLogByMessageID(db *gorm.DB, messageID string) (*MailLog, error)

GetMailLogByMessageID returns a log by provider message id.

func GetMailLogs

func GetMailLogs(db *gorm.DB, userID uint, page, pageSize int) ([]MailLog, int64, error)

GetMailLogs returns paginated logs for a user.

func (MailLog) TableName

func (MailLog) TableName() string

TableName returns the GORM table name.

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

func (m *Mailer) ChannelCount() int

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.

func (*Mailer) SendHTML

func (m *Mailer) SendHTML(ctx context.Context, to, subject, htmlBody string) error

SendHTML sends HTML mail with per-channel retries and cross-channel failover.

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.

func (*SMTPClient) Kind

func (s *SMTPClient) Kind() ProviderKind

Kind implements MailProvider.

func (*SMTPClient) SendHTML

func (s *SMTPClient) SendHTML(to, subject, htmlBody string) (string, error)

SendHTML sends a MIME HTML message. Returns a synthetic message id for logging (SMTP has no provider id).

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.

func (*SendCloudClient) SendHTML

func (s *SendCloudClient) SendHTML(to, subject, htmlBody string) (string, error)

SendHTML sends HTML mail via SendCloud apiv2.

type SendCloudConfig

type SendCloudConfig struct {
	APIUser  string
	APIKey   string
	From     string
	FromName string
}

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.

Jump to

Keyboard shortcuts

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