Files
mail/history.go
Z.To 7ab9f00c4f Fearure:
- 增加收件箱功能(有BUG)
- 增加已发送|草稿箱|发送历史 本地记录
2026-04-09 21:48:21 +08:00

222 lines
5.0 KiB
Go

package main
import (
"database/sql"
"encoding/json"
"fmt"
"os"
"path/filepath"
"time"
_ "github.com/mattn/go-sqlite3"
)
const historyDBName = "history.db"
type EmailStatus string
const (
StatusSent EmailStatus = "sent"
StatusDraft EmailStatus = "draft"
)
type EmailHistory struct {
ID int64
From string
To string
Cc string
Bcc string
Subject string
BodyText string
BodyHTML string
Attachments string
Status EmailStatus
DeliveryMethod string
CreatedAt time.Time
SentAt *time.Time
}
func getHistoryDBPath() (string, error) {
configDir, err := getConfigDir()
if err != nil {
return "", err
}
return filepath.Join(configDir, historyDBName), nil
}
func initHistoryDB() (*sql.DB, error) {
dbPath, err := getHistoryDBPath()
if err != nil {
return nil, err
}
db, err := sql.Open("sqlite3", dbPath)
if err != nil {
return nil, err
}
_, err = db.Exec(`
CREATE TABLE IF NOT EXISTS emails (
id INTEGER PRIMARY KEY AUTOINCREMENT,
from_addr TEXT NOT NULL,
to_addrs TEXT NOT NULL,
cc_addrs TEXT,
bcc_addrs TEXT,
subject TEXT NOT NULL,
body_text TEXT,
body_html TEXT,
attachments TEXT,
status TEXT NOT NULL,
delivery_method TEXT,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
sent_at DATETIME
)
`)
if err != nil {
return nil, err
}
return db, nil
}
func SaveEmail(from, to, cc, bcc, subject, bodyText, bodyHTML, attachments, deliveryMethod string, status EmailStatus) (int64, error) {
db, err := initHistoryDB()
if err != nil {
return 0, err
}
defer db.Close()
stmt, err := db.Prepare(`
INSERT INTO emails (from_addr, to_addrs, cc_addrs, bcc_addrs, subject, body_text, body_html, attachments, status, delivery_method, created_at, sent_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`)
if err != nil {
return 0, err
}
defer stmt.Close()
now := time.Now()
var sentAt *time.Time
if status == StatusSent {
sentAt = &now
}
result, err := stmt.Exec(from, to, cc, bcc, subject, bodyText, bodyHTML, attachments, status, deliveryMethod, now, sentAt)
if err != nil {
return 0, err
}
return result.LastInsertId()
}
func UpdateEmailStatus(id int64, status EmailStatus) error {
db, err := initHistoryDB()
if err != nil {
return err
}
defer db.Close()
_, err = db.Exec("UPDATE emails SET status = ?, sent_at = ? WHERE id = ?", status, time.Now(), id)
return err
}
func GetEmailHistory(status EmailStatus) ([]EmailHistory, error) {
db, err := initHistoryDB()
if err != nil {
return nil, err
}
defer db.Close()
var query string
var args []interface{}
if status == "" {
query = "SELECT id, from_addr, to_addrs, cc_addrs, bcc_addrs, subject, body_text, body_html, attachments, status, delivery_method, created_at, sent_at FROM emails ORDER BY created_at DESC"
} else {
query = "SELECT id, from_addr, to_addrs, cc_addrs, bcc_addrs, subject, body_text, body_html, attachments, status, delivery_method, created_at, sent_at FROM emails WHERE status = ? ORDER BY created_at DESC"
args = []interface{}{status}
}
rows, err := db.Query(query, args...)
if err != nil {
return nil, err
}
defer rows.Close()
var histories []EmailHistory
for rows.Next() {
var h EmailHistory
var sentAt sql.NullTime
err := rows.Scan(&h.ID, &h.From, &h.To, &h.Cc, &h.Bcc, &h.Subject, &h.BodyText, &h.BodyHTML, &h.Attachments, &h.Status, &h.DeliveryMethod, &h.CreatedAt, &sentAt)
if err != nil {
return nil, err
}
if sentAt.Valid {
h.SentAt = &sentAt.Time
}
histories = append(histories, h)
}
return histories, nil
}
func GetEmailByID(id int64) (*EmailHistory, error) {
db, err := initHistoryDB()
if err != nil {
return nil, err
}
defer db.Close()
var h EmailHistory
var sentAt sql.NullTime
err = db.QueryRow("SELECT id, from_addr, to_addrs, cc_addrs, bcc_addrs, subject, body_text, body_html, attachments, status, delivery_method, created_at, sent_at FROM emails WHERE id = ?", id).Scan(
&h.ID, &h.From, &h.To, &h.Cc, &h.Bcc, &h.Subject, &h.BodyText, &h.BodyHTML, &h.Attachments, &h.Status, &h.DeliveryMethod, &h.CreatedAt, &sentAt,
)
if err != nil {
return nil, err
}
if sentAt.Valid {
h.SentAt = &sentAt.Time
}
return &h, nil
}
func DeleteEmailHistory(id int64) error {
db, err := initHistoryDB()
if err != nil {
return err
}
defer db.Close()
_, err = db.Exec("DELETE FROM emails WHERE id = ?", id)
return err
}
func getAttachmentsJSON(paths []string) string {
if len(paths) == 0 {
return "[]"
}
data, _ := json.Marshal(paths)
return string(data)
}
func parseAttachmentsJSON(jsonStr string) []string {
if jsonStr == "" || jsonStr == "[]" {
return nil
}
var paths []string
json.Unmarshal([]byte(jsonStr), &paths)
return paths
}
func init() {
dbPath, err := getHistoryDBPath()
if err != nil {
return
}
if _, err := os.Stat(dbPath); os.IsNotExist(err) {
if _, err := initHistoryDB(); err != nil {
fmt.Fprintf(os.Stderr, "Failed to initialize history DB: %v\n", err)
}
}
}