Documentation
¶
Overview ¶
Package store owns perch's SQLite schema, blobs, messages, and search index.
Index ¶
- Variables
- func FTSQuery(text string) string
- func NormalizeAddress(address string) (string, error)
- func SpecialUse(name string) string
- func StripPlus(address string) (string, bool)
- type Account
- type Address
- type Blob
- type CopyResult
- type Flags
- type FlagsOp
- type Header
- type Mailbox
- type MailboxStatus
- type Message
- type MessageInput
- type MessageState
- type Outbound
- type SearchContent
- type Store
- func (s *Store) AccountByAddress(ctx context.Context, address string) (Account, error)
- func (s *Store) AccountByID(ctx context.Context, id int64) (Account, error)
- func (s *Store) AddAlias(ctx context.Context, accountID int64, address string) error
- func (s *Store) AddCatchAll(ctx context.Context, accountID int64, domain string) error
- func (s *Store) AllMessages(ctx context.Context, mailboxID int64) ([]Message, error)
- func (s *Store) Backup(ctx context.Context, path string) error
- func (s *Store) BindS3ByMessageID(ctx context.Context, messageID int64, objectKey string) error
- func (s *Store) BlobByRef(ctx context.Context, ref string) (Blob, error)
- func (s *Store) Close() error
- func (s *Store) CopyMessages(ctx context.Context, sourceMailboxID, destMailboxID int64, uids []uint32) (CopyResult, error)
- func (s *Store) CountDeadLetters(ctx context.Context) (int64, error)
- func (s *Store) CountIndexed(ctx context.Context) (int, error)
- func (s *Store) CountOutbound(ctx context.Context) (map[string]int, error)
- func (s *Store) CreateAccount(ctx context.Context, address, displayName, passwordHash string) (Account, error)
- func (s *Store) CreateMailbox(ctx context.Context, accountID int64, name, specialUse string) (Mailbox, error)
- func (s *Store) DeadLetter(ctx context.Context, address, taskID, reason string, raw []byte) error
- func (s *Store) DeleteBlob(ctx context.Context, id int64) error
- func (s *Store) DeleteMailbox(ctx context.Context, accountID int64, name string) error
- func (s *Store) EnforceSpoolLimit(ctx context.Context, maxBytes int64) (int, int64, error)
- func (s *Store) EvictLocalData(ctx context.Context, messageID int64) error
- func (s *Store) Expunge(ctx context.Context, mailboxID int64, uids []uint32) ([]uint32, error)
- func (s *Store) FTSCandidates(ctx context.Context, mailboxID int64, term string, limit int) ([]int64, error)
- func (s *Store) GCLocalOrphans(ctx context.Context, dryRun bool) (int, int64, error)
- func (s *Store) IncrementalVacuum(ctx context.Context) error
- func (s *Store) InsertMessage(ctx context.Context, in MessageInput) (Message, bool, error)
- func (s *Store) IntegrityCheck(ctx context.Context) error
- func (s *Store) ListAccounts(ctx context.Context) ([]Account, error)
- func (s *Store) ListAddresses(ctx context.Context, accountID int64) ([]string, error)
- func (s *Store) ListMailboxes(ctx context.Context, accountID int64) ([]Mailbox, error)
- func (s *Store) ListOutbound(ctx context.Context, accountID int64, limit int) ([]Outbound, error)
- func (s *Store) MailboxByID(ctx context.Context, id int64) (Mailbox, error)
- func (s *Store) MailboxByName(ctx context.Context, accountID int64, name string) (Mailbox, error)
- func (s *Store) MailboxState(ctx context.Context, mailboxID int64) ([]MessageState, error)
- func (s *Store) MessageByRawSHA(ctx context.Context, accountID int64, sha string) (Message, error)
- func (s *Store) MessageByS3Key(ctx context.Context, key string) (Message, error)
- func (s *Store) MessageByTaskID(ctx context.Context, taskID string) (Message, error)
- func (s *Store) MessageByUID(ctx context.Context, mailboxID int64, uid uint32) (Message, error)
- func (s *Store) MessageCount(ctx context.Context, mailboxID int64) (uint32, error)
- func (s *Store) MessagesByIDs(ctx context.Context, mailboxID int64, ids []int64) ([]Message, error)
- func (s *Store) MessagesByUIDs(ctx context.Context, mailboxID int64, uids []uint32) ([]Message, error)
- func (s *Store) MoveMessages(ctx context.Context, sourceMailboxID, destMailboxID int64, uids []uint32) (CopyResult, error)
- func (s *Store) PurgeDeadLetters(ctx context.Context, before time.Time) (int, error)
- func (s *Store) RawBlob(ctx context.Context, messageID int64) ([]byte, Blob, error)
- func (s *Store) RecordOutboundAttempt(ctx context.Context, out Outbound) error
- func (s *Store) RemoveAddress(ctx context.Context, address string) error
- func (s *Store) RenameMailbox(ctx context.Context, accountID int64, oldName, newName string) error
- func (s *Store) ResolveRecipient(ctx context.Context, address string) (Account, string, error)
- func (s *Store) S3Tombstones(ctx context.Context) ([]Blob, error)
- func (s *Store) SearchContentByIDs(ctx context.Context, ids []int64) (map[int64]SearchContent, error)
- func (s *Store) SetAccountDisabled(ctx context.Context, accountID int64, disabled bool) error
- func (s *Store) SetPasswordHash(ctx context.Context, accountID int64, hash string) error
- func (s *Store) SetS3Key(ctx context.Context, taskID, objectKey string) (Message, error)
- func (s *Store) SetSubscribed(ctx context.Context, accountID int64, name string, subscribed bool) error
- func (s *Store) SpoolStats(ctx context.Context) (int64, int, error)
- func (s *Store) Status(ctx context.Context, mailboxID int64) (MailboxStatus, error)
- func (s *Store) StoreFlags(ctx context.Context, mailboxID int64, uids []uint32, op FlagsOp, flags Flags, ...) ([]Message, error)
- func (s *Store) UpsertOutboundAccepted(ctx context.Context, out Outbound) error
Constants ¶
This section is empty.
Variables ¶
var ( ErrNotFound = errors.New("store: not found") ErrDuplicate = errors.New("store: already exists") ErrNoRecipient = errors.New("store: recipient does not map to an account") ErrMailboxNotFound = errors.New("store: mailbox not found") ErrMailboxHasChildren = errors.New("store: mailbox has children") ErrAccountDisabled = errors.New("store: account is disabled") )
Common store errors.
ErrBlobUnavailable reports that the message body exists only in remote storage and the caller must provide a blob store.
Functions ¶
func FTSQuery ¶
FTSQuery converts free text into a conservative FTS5 prefix query. Each token is quoted, and tokens are ANDed. It returns "" when no token is at least three characters, because short terms are poor FTS candidates.
func NormalizeAddress ¶
NormalizeAddress lowercases and canonicalizes an RFC 5322 mailbox.
func SpecialUse ¶
SpecialUse returns the IMAP special-use attribute for a standard mailbox name, or an empty string.
Types ¶
type Account ¶
type Account struct {
ID int64
PrimaryAddress string
DisplayName string
PasswordHash string
Disabled bool
CreatedAt time.Time
}
Account is one local mailbox account.
type CopyResult ¶
CopyResult reports a COPY or MOVE.
type Mailbox ¶
type Mailbox struct {
ID int64
AccountID int64
Name string
UIDValidity uint32
UIDNext uint32
HighestModSeq uint64
Subscribed bool
SpecialUse string
CreatedAt time.Time
}
Mailbox is one IMAP mailbox belonging to an account.
type MailboxStatus ¶
type MailboxStatus struct {
Mailbox Mailbox
Messages uint32
Unseen uint32
Deleted uint32
Size int64
FirstUnseen uint32
}
MailboxStatus summarises a mailbox for SELECT and STATUS.
type Message ¶
type Message struct {
ID int64
AccountID int64
MailboxID int64
UID uint32
ModSeq uint64
BlobID int64
Size int64
InternalDate time.Time
MessageID string
Subject string
From []Address
To []Address
Cc []Address
Bcc []Address
ReplyTo []Address
InReplyTo []string
References []string
SentAt *time.Time
Headers []Header
MIMETree string
RawSHA256 string
S3Key string
TaskID string
CorrelationID string
IsSpam bool
Flags Flags
Keywords []string
}
Message is a stored message with its metadata, flags, and keywords.
type MessageInput ¶
type MessageInput struct {
AccountID int64
MailboxID int64
Raw []byte
RawSHA256 string
Kind string // local or s3; inferred from Raw/S3Key when empty
S3Key string
StoreData bool // keep a local copy of Raw even for an S3 blob
Size int64
InternalDate time.Time
MessageID string
Subject string
From []Address
To []Address
Cc []Address
Bcc []Address
ReplyTo []Address
InReplyTo []string
References []string
SentAt *time.Time
Headers []Header
MIMETree string
TaskID string
CorrelationID string
IsSpam bool
Flags Flags
Keywords []string
Search SearchContent
// DedupeRaw rejects an insert when the same account already has a message
// with this raw SHA-256. Ingest and S3 reconciliation set it; APPEND does
// not, so a client can intentionally append the same message twice.
DedupeRaw bool
}
MessageInput describes a new message. Raw may be nil when the message is already in S3 and only metadata is being indexed.
type MessageState ¶
MessageState is the lightweight per-message state used for SELECT and IDLE polling.
type Outbound ¶
type Outbound struct {
ID int64
AccountID int64
MessageRef string
TaskID string
FromAddress string
Recipients []string
Subject string
Size int64
Status string
Attempt uint64
SMTPCode int
EnhancedStatus string
RemoteResponse string
Reason string
AcceptedAt time.Time
OccurredAt time.Time
NextRetryAt time.Time
CreatedAt time.Time
UpdatedAt time.Time
}
Outbound is one submitted message and its latest delivery status.
type SearchContent ¶
type SearchContent struct {
Subject string
Sender string
Recipients string
Headers string
Body string
Attachments string
}
SearchContent is the text indexed for FTS.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store is the persistent SQLite state. Reads use a small connection pool; writes use a single connection so transactions are serialized without SQLITE_BUSY upgrade races.
func Open ¶
Open opens or creates the database at path, applies migrations, and returns a ready store. The caller must call Close.
func (*Store) AccountByAddress ¶
AccountByAddress returns the account owning address, including aliases and catch-all domains.
func (*Store) AccountByID ¶
AccountByID returns one account.
func (*Store) AddCatchAll ¶
AddCatchAll routes every otherwise-unmatched address at domain to accountID.
func (*Store) AllMessages ¶
AllMessages returns every message in a mailbox ordered by UID.
func (*Store) Backup ¶
Backup writes a consistent copy of the database to path using SQLite's VACUUM INTO.
func (*Store) BindS3ByMessageID ¶
BindS3ByMessageID binds an existing message to an S3 object key.
func (*Store) BlobByRef ¶
BlobByRef returns a blob by its S3 object reference, including refcount-zero tombstones. It returns ErrNotFound when no such object has ever been seen.
func (*Store) CopyMessages ¶
func (s *Store) CopyMessages(ctx context.Context, sourceMailboxID, destMailboxID int64, uids []uint32) (CopyResult, error)
CopyMessages copies messages to destMailbox in one transaction.
func (*Store) CountDeadLetters ¶
CountDeadLetters returns the number of stored dead letters.
func (*Store) CountIndexed ¶
CountIndexed returns the number of rows in the FTS index. It is used by doctor to verify that the FTS5 module is available.
func (*Store) CountOutbound ¶
CountOutbound returns outbound status counts for doctor.
func (*Store) CreateAccount ¶
func (s *Store) CreateAccount(ctx context.Context, address, displayName, passwordHash string) (Account, error)
CreateAccount creates an account, its primary address, and the default mailbox set in one transaction. passwordHash must already be hashed.
func (*Store) CreateMailbox ¶
func (s *Store) CreateMailbox(ctx context.Context, accountID int64, name, specialUse string) (Mailbox, error)
CreateMailbox creates a mailbox and any missing parent mailboxes.
func (*Store) DeadLetter ¶
DeadLetter stores a message that could not be routed to an account.
func (*Store) DeleteBlob ¶
DeleteBlob removes a blob row by ID.
func (*Store) DeleteMailbox ¶
DeleteMailbox deletes an empty-of-children mailbox and all its messages. It refuses to delete INBOX.
func (*Store) EnforceSpoolLimit ¶
EnforceSpoolLimit evicts confirmed S3 spool copies until their compressed size is at most maxBytes. Unconfirmed copies are never evicted.
func (*Store) EvictLocalData ¶
EvictLocalData removes a message's local raw copy after an S3 object has been confirmed. The blob row and S3 reference remain.
func (*Store) Expunge ¶
Expunge deletes messages with \Deleted set, optionally restricted to uids. It returns the expunged UIDs in ascending order.
func (*Store) FTSCandidates ¶
func (s *Store) FTSCandidates(ctx context.Context, mailboxID int64, term string, limit int) ([]int64, error)
FTSCandidates returns message IDs matching term. It is a candidate prefilter, not a substitute for IMAP's substring semantics; callers must verify the full criteria against SearchContent.
func (*Store) GCLocalOrphans ¶
GCLocalOrphans removes local blobs that are no longer referenced by any message. When dryRun is true it only reports what would be removed.
func (*Store) IncrementalVacuum ¶
IncrementalVacuum releases free pages without a full VACUUM.
func (*Store) InsertMessage ¶
InsertMessage stores a message and its blob, assigning the next UID. It is idempotent for non-empty TaskID: a duplicate returns the existing message with inserted=false.
func (*Store) IntegrityCheck ¶
IntegrityCheck runs SQLite's quick_check. It returns nil when the database reports ok.
func (*Store) ListAccounts ¶
ListAccounts returns every account ordered by address.
func (*Store) ListAddresses ¶
ListAddresses returns all addresses for an account.
func (*Store) ListMailboxes ¶
ListMailboxes returns all mailboxes for an account ordered by name.
func (*Store) ListOutbound ¶
ListOutbound returns recent outbound messages, optionally filtered by account.
func (*Store) MailboxByID ¶
MailboxByID returns one mailbox by database identifier.
func (*Store) MailboxByName ¶
MailboxByName returns one mailbox. INBOX is matched case-insensitively.
func (*Store) MailboxState ¶
MailboxState returns the UID, flags, and keywords for every message in a mailbox, ordered by UID.
func (*Store) MessageByRawSHA ¶
MessageByRawSHA returns the first message for an account with the given raw SHA-256.
func (*Store) MessageByS3Key ¶
MessageByS3Key returns the message bound to an S3 object key.
func (*Store) MessageByTaskID ¶
MessageByTaskID returns one message by mxRaven task identifier.
func (*Store) MessageByUID ¶
MessageByUID returns one message.
func (*Store) MessageCount ¶
MessageCount returns the number of messages in a mailbox.
func (*Store) MessagesByIDs ¶
MessagesByIDs returns messages in a mailbox by database ID, ordered by UID.
func (*Store) MessagesByUIDs ¶
func (s *Store) MessagesByUIDs(ctx context.Context, mailboxID int64, uids []uint32) ([]Message, error)
MessagesByUIDs returns messages for the given UIDs, ordered by UID.
func (*Store) MoveMessages ¶
func (s *Store) MoveMessages(ctx context.Context, sourceMailboxID, destMailboxID int64, uids []uint32) (CopyResult, error)
MoveMessages copies messages and removes the source rows atomically.
func (*Store) PurgeDeadLetters ¶
PurgeDeadLetters deletes dead letters older than before.
func (*Store) RawBlob ¶
RawBlob returns the raw message bytes for a message. It prefers a local copy and returns ErrBlobUnavailable when only a remote reference exists.
func (*Store) RecordOutboundAttempt ¶
RecordOutboundAttempt updates the latest attempt status for a submission.
func (*Store) RemoveAddress ¶
RemoveAddress removes an alias or catch-all. Primary addresses cannot be removed.
func (*Store) RenameMailbox ¶
RenameMailbox renames a mailbox and its descendants. INBOX cannot be renamed; clients should create a new mailbox and move messages instead.
func (*Store) ResolveRecipient ¶
ResolveRecipient maps an envelope recipient to an account. It tries an exact address, then the plus-tag-stripped form, then a domain catch-all.
func (*Store) S3Tombstones ¶
S3Tombstones returns deleted-message blob rows whose S3 objects still exist.
func (*Store) SearchContentByIDs ¶
func (s *Store) SearchContentByIDs(ctx context.Context, ids []int64) (map[int64]SearchContent, error)
SearchContentByIDs loads FTS text for the given message IDs.
func (*Store) SetAccountDisabled ¶
SetAccountDisabled enables or disables an account.
func (*Store) SetPasswordHash ¶
SetPasswordHash replaces an account's password hash.
func (*Store) SetS3Key ¶
SetS3Key binds a message to its mxRaven S3 object. taskID may be either the accepted task ID or the S3 attempt's correlation ID.
func (*Store) SetSubscribed ¶
func (s *Store) SetSubscribed(ctx context.Context, accountID int64, name string, subscribed bool) error
SetSubscribed changes a mailbox's subscription state.
func (*Store) SpoolStats ¶
SpoolStats reports the compressed size and count of local spool copies for S3-backed messages.