feat(store): add account from_address field + v2 migration
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
+25
-14
@@ -23,6 +23,7 @@ type Account struct {
|
||||
SMTPSecurity string // tls | starttls
|
||||
AuthType string // password | oauth2
|
||||
Username string
|
||||
FromAddress string // send-as identity; blank ⇒ fall back to Username
|
||||
Password string // decrypted; empty in ListAccounts
|
||||
WhitelistInEnabled bool
|
||||
WhitelistOutEnabled bool
|
||||
@@ -30,6 +31,15 @@ type Account struct {
|
||||
ProcessBacklog bool
|
||||
}
|
||||
|
||||
// SendFrom returns the From identity for outgoing mail, falling back to the
|
||||
// login username when no explicit from-address is configured.
|
||||
func (a Account) SendFrom() string {
|
||||
if a.FromAddress != "" {
|
||||
return a.FromAddress
|
||||
}
|
||||
return a.Username
|
||||
}
|
||||
|
||||
func (s *Store) AddAccount(a Account) (int64, error) {
|
||||
var encPw []byte
|
||||
if a.Password != "" {
|
||||
@@ -42,12 +52,12 @@ func (s *Store) AddAccount(a Account) (int64, error) {
|
||||
res, err := s.db.Exec(`
|
||||
INSERT INTO accounts
|
||||
(name,mode,imap_host,imap_port,imap_security,smtp_host,smtp_port,smtp_security,
|
||||
auth_type,username,
|
||||
auth_type,username,from_address,
|
||||
enc_password,whitelist_in_enabled,whitelist_out_enabled,subject_regex,process_backlog)
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,
|
||||
VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)`,
|
||||
a.Name, a.Mode, a.IMAPHost, a.IMAPPort, a.IMAPSecurity,
|
||||
nullStr(a.SMTPHost), nullInt(a.SMTPPort), nullStr(a.SMTPSecurity),
|
||||
a.AuthType, a.Username,
|
||||
a.AuthType, a.Username, nullStr(a.FromAddress),
|
||||
encPw, b2i(a.WhitelistInEnabled), b2i(a.WhitelistOutEnabled),
|
||||
nullStr(a.SubjectRegex), b2i(a.ProcessBacklog))
|
||||
if err != nil {
|
||||
@@ -59,7 +69,7 @@ func (s *Store) AddAccount(a Account) (int64, error) {
|
||||
func (s *Store) GetAccount(name string) (Account, error) {
|
||||
row := s.db.QueryRow(`
|
||||
SELECT id,name,mode,imap_host,imap_port,imap_security,smtp_host,smtp_port,smtp_security,
|
||||
auth_type,username,
|
||||
auth_type,username,from_address,
|
||||
enc_password,whitelist_in_enabled,whitelist_out_enabled,subject_regex,process_backlog
|
||||
FROM accounts WHERE name = ?`, name)
|
||||
a, encPw, err := scanAccount(row)
|
||||
@@ -82,7 +92,7 @@ func (s *Store) GetAccount(name string) (Account, error) {
|
||||
func (s *Store) ListAccounts() ([]Account, error) {
|
||||
rows, err := s.db.Query(`
|
||||
SELECT id,name,mode,imap_host,imap_port,imap_security,smtp_host,smtp_port,smtp_security,
|
||||
auth_type,username,
|
||||
auth_type,username,from_address,
|
||||
enc_password,whitelist_in_enabled,whitelist_out_enabled,subject_regex,process_backlog
|
||||
FROM accounts ORDER BY name`)
|
||||
if err != nil {
|
||||
@@ -108,12 +118,12 @@ func (s *Store) UpdateAccount(a Account) error {
|
||||
// Build the SET clause, conditionally including secret columns.
|
||||
set := `mode=?, imap_host=?, imap_port=?, imap_security=?,
|
||||
smtp_host=?, smtp_port=?, smtp_security=?,
|
||||
auth_type=?, username=?,
|
||||
auth_type=?, username=?, from_address=?,
|
||||
whitelist_in_enabled=?, whitelist_out_enabled=?, subject_regex=?, process_backlog=?`
|
||||
args := []any{
|
||||
a.Mode, a.IMAPHost, a.IMAPPort, a.IMAPSecurity,
|
||||
nullStr(a.SMTPHost), nullInt(a.SMTPPort), nullStr(a.SMTPSecurity),
|
||||
a.AuthType, a.Username,
|
||||
a.AuthType, a.Username, nullStr(a.FromAddress),
|
||||
b2i(a.WhitelistInEnabled), b2i(a.WhitelistOutEnabled),
|
||||
nullStr(a.SubjectRegex), b2i(a.ProcessBacklog),
|
||||
}
|
||||
@@ -152,16 +162,16 @@ type scanner interface{ Scan(dest ...any) error }
|
||||
|
||||
func scanAccount(sc scanner) (Account, []byte, error) {
|
||||
var (
|
||||
a Account
|
||||
encPw []byte
|
||||
subj, smtpHost, smtpSec sql.NullString
|
||||
smtpPort sql.NullInt64
|
||||
wlIn, wlOut int
|
||||
backlog int
|
||||
a Account
|
||||
encPw []byte
|
||||
subj, smtpHost, smtpSec, fromAddr sql.NullString
|
||||
smtpPort sql.NullInt64
|
||||
wlIn, wlOut int
|
||||
backlog int
|
||||
)
|
||||
err := sc.Scan(&a.ID, &a.Name, &a.Mode, &a.IMAPHost, &a.IMAPPort, &a.IMAPSecurity,
|
||||
&smtpHost, &smtpPort, &smtpSec,
|
||||
&a.AuthType, &a.Username, &encPw, &wlIn, &wlOut, &subj, &backlog)
|
||||
&a.AuthType, &a.Username, &fromAddr, &encPw, &wlIn, &wlOut, &subj, &backlog)
|
||||
if err != nil {
|
||||
return Account{}, nil, err
|
||||
}
|
||||
@@ -172,6 +182,7 @@ func scanAccount(sc scanner) (Account, []byte, error) {
|
||||
a.WhitelistOutEnabled = wlOut != 0
|
||||
a.ProcessBacklog = backlog != 0
|
||||
a.SubjectRegex = subj.String
|
||||
a.FromAddress = fromAddr.String
|
||||
return a, encPw, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user