feat(mail): 支持草稿与定时发送

- 新增草稿保存、草稿编辑/删除、定时发送列表与取消接口,并在后台加入待发送任务表与定时发送工作协程。
- 邮件撰写页支持草稿自动保存、定时发送弹窗、草稿入口识别,以及待发送视图与状态标记。
- 同步补充前端 API 类型与调用,并增加定时发送流程的后端测试。
This commit is contained in:
LanQin_
2026-06-17 13:43:19 +08:00
parent f0044e477c
commit a8c2fc852c
8 changed files with 1577 additions and 139 deletions
+17 -2
View File
@@ -68,9 +68,10 @@ func New(cfg Config, logger *slog.Logger) (*App, error) {
db.Close()
return nil, err
}
workerCtx, cancel := context.WithCancel(context.Background())
a.workerCancel = cancel
go a.scheduledSendWorker(workerCtx)
if strings.TrimSpace(cfg.MaildirRoot) != "" {
workerCtx, cancel := context.WithCancel(context.Background())
a.workerCancel = cancel
go a.maildirWorker(workerCtx)
}
return a, nil
@@ -223,6 +224,20 @@ func (a *App) migrate(ctx context.Context) error {
storage_path TEXT NOT NULL,
created_at TEXT NOT NULL
)`,
`CREATE TABLE IF NOT EXISTS scheduled_sends (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,
mailbox_id TEXT NOT NULL REFERENCES mailboxes(id) ON DELETE CASCADE,
draft_id TEXT REFERENCES messages(id) ON DELETE SET NULL,
payload_json TEXT NOT NULL,
send_at TEXT NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
error TEXT NOT NULL DEFAULT '',
created_at TEXT NOT NULL,
updated_at TEXT NOT NULL,
sent_at TEXT
)`,
`CREATE INDEX IF NOT EXISTS idx_scheduled_sends_due ON scheduled_sends(status, send_at)`,
`CREATE TABLE IF NOT EXISTS contacts (
id TEXT PRIMARY KEY,
user_id TEXT NOT NULL REFERENCES users(id) ON DELETE CASCADE,