package db import ( "database/sql" "errors" ) func (d *DB) ListAliasesForMailbox(mailboxID int64) ([]MailboxAlias, error) { rows, err := d.Query(`SELECT id, mailbox_id, email, domain_id, can_send_as, is_active, created_at FROM esrv_mailbox_aliases WHERE mailbox_id = ? ORDER BY email`, mailboxID) if err != nil { return nil, err } defer rows.Close() var out []MailboxAlias for rows.Next() { var a MailboxAlias var createdAt string if err := rows.Scan(&a.ID, &a.MailboxID, &a.Email, &a.DomainID, &a.CanSendAs, &a.IsActive, &createdAt); err != nil { return nil, err } a.CreatedAt, _ = parseTime(createdAt) out = append(out, a) } return out, rows.Err() } // GetAliasByEmail mirrors GetMailboxByEmail: case-insensitive, active-only. Used by // mailstore.ResolveRecipient when a recipient address doesn't match any mailbox's // primary address directly. func (d *DB) GetAliasByEmail(email string) (*MailboxAlias, error) { row := d.QueryRow(`SELECT id, mailbox_id, email, domain_id, can_send_as, is_active, created_at FROM esrv_mailbox_aliases WHERE lower(email) = lower(?) AND is_active = 1`, email) var a MailboxAlias var createdAt string if err := row.Scan(&a.ID, &a.MailboxID, &a.Email, &a.DomainID, &a.CanSendAs, &a.IsActive, &createdAt); err != nil { if errors.Is(err, sql.ErrNoRows) { return nil, nil } return nil, err } a.CreatedAt, _ = parseTime(createdAt) return &a, nil } func (d *DB) AliasEmailExists(email string, excludeID int64) (bool, error) { var n int err := d.QueryRow(`SELECT COUNT(*) FROM esrv_mailbox_aliases WHERE lower(email) = lower(?) AND id != ?`, email, excludeID).Scan(&n) return n > 0, err } func (d *DB) CreateAlias(mailboxID int64, email string, domainID int64, canSendAs bool) (int64, error) { res, err := d.Exec(`INSERT INTO esrv_mailbox_aliases (mailbox_id, email, domain_id, can_send_as) VALUES (?, ?, ?, ?)`, mailboxID, email, domainID, canSendAs) if err != nil { return 0, err } return res.LastInsertId() } // RemoveAlias deletes an alias, scoped to mailboxID so a caller can't remove one // belonging to a different mailbox by guessing its id (mirrors RemoveAppPassword). func (d *DB) RemoveAlias(id, mailboxID int64) error { _, err := d.Exec(`DELETE FROM esrv_mailbox_aliases WHERE id = ? AND mailbox_id = ?`, id, mailboxID) return err } // MailboxCanSendAs reports whether address is an active, send-as-enabled alias owned // by mailboxID — the authorization check for an authenticated mailbox's MAIL FROM // (see smtpserver's validateSenderAuthorization). func (d *DB) MailboxCanSendAs(mailboxID int64, address string) (bool, error) { var n int err := d.QueryRow(`SELECT COUNT(*) FROM esrv_mailbox_aliases WHERE mailbox_id = ? AND lower(email) = lower(?) AND can_send_as = 1 AND is_active = 1`, mailboxID, address).Scan(&n) return n > 0, err }