Documentation
¶
Overview ¶
Package imap implements the chassis's IMAP head: a personality that serves a tenant's durable mailbox store (chassis/imap) to any IMAP4rev1 client — Apple Mail, Thunderbird, mutt — so a mail client becomes a UI over state that stacks project into the store with txco://imap/* ops.
The head is a GENERIC IMAP server: it knows no folder names and no product. Reads (LIST/SELECT/FETCH/SEARCH/IDLE) never touch the processor; they are served from the index columns cached at append and, for BODY[], from a deterministic render of the retained record. Writes that reach the store from an op are fanned out to selected sessions through a head-local hub (EXISTS / EXPUNGE / FETCH on Poll and IDLE).
Phase 0a scope (authentication first): LOGIN against argon2id account rows with per-IP and per-account throttles, a verified-login cache and the tenant admission check; NAMESPACE, LIST, STATUS, SELECT, FETCH, SEARCH, STORE (flags, local policy), POLL/IDLE, SUBSCRIBE. Mutating verbs (CREATE/DELETE/RENAME/APPEND/COPY/MOVE/EXPUNGE) answer NO [CANNOT] until the observe/answer lanes land.
IMAP is OFF by default. Both gates must be flipped:
- `imap` must appear in `--personalities`
- `--imap-listen-addrs` and/or `--imap-tls-addrs` must be non-empty
Index ¶
- func DecodeBodyStructure(b []byte) (imap.BodyStructure, error)
- func EncodeBodyStructure(bs imap.BodyStructure) ([]byte, error)
- func LoadOrMintSelfSigned(certPath, keyPath string, hosts []string) (*tls.Config, bool, error)
- func SelfSignedPaths(dbPath string) (certPath, keyPath string)
- func SelfSignedTLS(hosts []string) (*tls.Config, error)
- func StoreVerbatim(ctx context.Context, fcas filecas.Store, ix blob.Index, tenant string, ...) error
- type Controller
- type Ingested
- type Verbatim
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func DecodeBodyStructure ¶
func DecodeBodyStructure(b []byte) (imap.BodyStructure, error)
DecodeBodyStructure restores a cached body structure.
func EncodeBodyStructure ¶
func EncodeBodyStructure(bs imap.BodyStructure) ([]byte, error)
EncodeBodyStructure serialises a body structure for the row cache.
func LoadOrMintSelfSigned ¶
LoadOrMintSelfSigned reuses the certificate at certPath/keyPath when it is still valid for 30 days and covers exactly these hosts; otherwise it mints a new one and writes both files (key 0600). A stable file is what lets a developer trust the certificate ONCE in the OS keychain instead of clicking through a warning on every chassis restart.
func SelfSignedPaths ¶
SelfSignedPaths derives the dev certificate + key file paths from the index path (`imap.db` → `imap-selfsigned.crt` / `.key` beside it).
func SelfSignedTLS ¶
SelfSignedTLS builds a self-signed ECDSA certificate for the given hosts (DNS names, wildcards, or IPs) valid for a year, and a TLS config serving it. Development only — the bundled cert manager or cert files are the real paths (§25.3). See LoadOrMintSelfSigned for the on-disk variant a developer can trust once in the OS keychain.
func StoreVerbatim ¶
func StoreVerbatim(ctx context.Context, fcas filecas.Store, ix blob.Index, tenant string, raw []byte, v *Verbatim, now time.Time) error
StoreVerbatim writes the message bytes and every part into the CAS, recording the tenant's ownership rows (ix may be nil: bytes only). Write order CAS → sha rows; the index row is the caller's AppendMessage.
Types ¶
type Controller ¶
type Controller struct {
// contains filtered or unexported fields
}
Controller owns the IMAP listeners and their go-imap servers. It satisfies the server's Start()/Stop() controller contract.
func NewController ¶
NewController constructs (but does not start) an IMAP controller. A nil store (imap personality not active) yields an inert controller whose Start is a no-op.
func (*Controller) SetBlobIndex ¶
func (c *Controller) SetBlobIndex(ix blob.Index)
SetBlobIndex wires the tenant sha-ownership index so message and part bytes a client APPENDs are owned by the account's tenant (readable through the blob plane by sha). Nil-safe.
func (*Controller) SetFileCAS ¶
func (c *Controller) SetFileCAS(f filecas.Store)
SetFileCAS wires the content store BODY[] renders from. Nil-safe: without it, metadata still serves and BODY[] answers NO [UNAVAILABLE].
func (*Controller) SetTLSConfig ¶
func (c *Controller) SetTLSConfig(t *tls.Config)
SetTLSConfig wires the certificate source for --imap-tls-addrs (implicit TLS) and for STARTTLS on the plaintext listeners.
func (*Controller) Start ¶
func (c *Controller) Start()
Start binds the configured listeners and serves IMAP on each. The double-gate (personality string AND non-empty listen addrs) means an upgrade cannot acquire a new listener without explicit opt-in.
func (*Controller) Stop ¶
func (c *Controller) Stop()
Stop closes the listeners and every connection. go-imap's Close is immediate (no drain); an IDLE client reconnects on its own.
type Ingested ¶
Ingested is a record turned into everything the store row and the CAS need: the canonical bytes (the CAS object, keyed by SHA256), the rendered RFC 5322 bytes (for the size + the cached structures — discarded after), and the row with ENVELOPE/BODYSTRUCTURE already cached.
func BuildRecordMessage ¶
func BuildRecordMessage(rec *chimap.Record, objectKey, domain string, internal time.Time, flags []string) (Ingested, error)
BuildRecordMessage runs the formatter once over a record and caches what FETCH needs. objectKey/domain/internal are the RenderOptions and are stored on the row so the render is reproducible on every BODY[] fetch.