package db import ( "encoding/json" "time" ) // Mailbox is a real, IMAP-retrievable local mailbox — distinct from Sender (which is // relay/auth-only). PasswordHash authenticates the self-service web portal only; // IMAP/SMTP client login always goes through a MailboxAppPassword instead. type Mailbox struct { ID int64 Email string DomainID int64 PasswordHash string IsActive bool QuotaBytes int64 UsedBytes int64 DEKWrapped []byte DEKNonce []byte CreatedAt time.Time CreatedBy *int64 TOTPSecret string TOTPEnabled bool // MFAExempt overrides [Auth] enforce_mailbox_mfa off for this mailbox specifically, // even if its domain isn't exempt. MFAExempt bool } // MailboxSession is a self-service webmail portal login — a parallel schema to // AdminSession, not shared (see esrv_mailbox_sessions in schema.go). type MailboxSession struct { Token string MailboxID int64 MFAVerified bool CreatedAt time.Time ExpiresAt time.Time } // MailboxWebAuthnCredential is a mailbox owner's passkey — a parallel schema to // WebAuthnCredential, not shared. type MailboxWebAuthnCredential struct { ID int64 MailboxID int64 Name string CredentialID string CredentialData string CreatedAt time.Time } // MailboxAlias is an alternate address for a mailbox — receive-only by default, or // also usable as MAIL FROM once authenticated (CanSendAs). Login is always the // mailbox's own primary address, never an alias. type MailboxAlias struct { ID int64 MailboxID int64 Email string DomainID int64 CanSendAs bool IsActive bool CreatedAt time.Time } // MailboxAllowBlockEntry is one allow- or block-list pattern for a mailbox. type MailboxAllowBlockEntry struct { ID int64 MailboxID int64 ListType string // "allow" | "block" Pattern string CreatedAt time.Time } // MailboxFilterRule is one priority-ordered, first-match-wins delivery rule. // ConditionField/Op/Value are the legacy single-condition columns; ConditionsJSON // (when non-empty) is the current multi-condition representation — see Conditions(). type MailboxFilterRule struct { ID int64 MailboxID int64 Priority int ConditionField string // "from" | "to" | "subject" ConditionOp string // "contains" | "equals" | "starts_with" ConditionValue string Action string // "move_to_folder" | "delete" | "mark_read" | "mark_as_spam" ActionValue string IsActive bool ConditionsJSON string MatchType string // "all" (AND, default) | "any" (OR) CreatedAt time.Time } // RuleCondition is one condition within a filter rule's "if" clause. type RuleCondition struct { Field string `json:"field"` Op string `json:"op"` Value string `json:"value"` } // Conditions returns this rule's conditions and how they combine ("all"=AND, // "any"=OR) — parses ConditionsJSON when present, falling back to the single legacy // condition_field/op/value columns for rules created before multi-condition support // existed. Shared by mailstore.ApplyRules (evaluation) and the webui (display), so // both stay in sync with the same fallback rule. func (r MailboxFilterRule) Conditions() ([]RuleCondition, string) { if r.ConditionsJSON != "" { var parsed []RuleCondition if err := json.Unmarshal([]byte(r.ConditionsJSON), &parsed); err == nil && len(parsed) > 0 { matchType := r.MatchType if matchType != "any" { matchType = "all" } return parsed, matchType } } return []RuleCondition{{Field: r.ConditionField, Op: r.ConditionOp, Value: r.ConditionValue}}, "all" } // MailboxAppPassword is the only credential an IMAP/SMTP client ever uses. Plaintext // is shown once at creation and never stored. ExpiresAt is nil for a password that // never expires (the default). type MailboxAppPassword struct { ID int64 MailboxID int64 Label string PasswordHash string IsActive bool CreatedAt time.Time LastUsedAt *time.Time ExpiresAt *time.Time } // MailboxMessage is one stored message. CachedFrom/CachedTo/CachedSubject are // plaintext by design (see schema.go); the rest of the message lives encrypted at // StoragePath. CachedTo exists purely so folder listings (e.g. Sent) can show the // recipient without decrypting every message just to render a list. type MailboxMessage struct { ID int64 MailboxID int64 Folder string MessageIDHeader string Flags string InternalDate time.Time SizeBytes int64 CachedFrom string CachedTo string CachedSubject string StoragePath string Nonce []byte CreatedAt time.Time } // MailboxSMIMEIdentity is one of a mailbox's own S/MIME certificate + private key // pairs — a mailbox may hold several. Both halves are stored plain: S/MIME is // sign-only in this codebase, so the key never protects anything beyond what the // server already has access to. type MailboxSMIMEIdentity struct { ID int64 MailboxID int64 CertPEM string KeyPEM string NotAfter time.Time CreatedAt time.Time } // MailboxSMIMEContact is another address's public certificate a mailbox owner has // collected, either added by hand or auto-captured off a verified signature. type MailboxSMIMEContact struct { ID int64 MailboxID int64 Email string CertPEM string CreatedAt time.Time } // MailboxPGPIdentity is one of a mailbox's own PGP keypairs — a mailbox may hold // several. PrivateKeyArmor is stored exactly as the pgp package serializes it, // already passphrase-protected via OpenPGP's own native key-encryption format (no // separate ciphertext/nonce/salt columns needed, unlike MailboxSMIMEIdentity). // Label is a free-text user note distinguishing keys (PGP keys have no expiry). type MailboxPGPIdentity struct { ID int64 MailboxID int64 Label string Email string Fingerprint string PublicKeyArmor string PrivateKeyArmor string CreatedAt time.Time } // MailboxPGPContact is another address's PGP public key a mailbox owner has // collected — mirrors MailboxSMIMEContact. type MailboxPGPContact struct { ID int64 MailboxID int64 Email string Label string PublicKeyArmor string Fingerprint string CreatedAt time.Time }