MeowMail — Inbound email authentication (SPF, DKIM, DMARC).
Verifies incoming messages and adds Authentication-Results header. SPF checks the connecting IP against the sender's DNS record. DKIM verifies cryptographic signatures. DMARC checks alignment between SPF and DKIM results.
Types
AuthHeader = object spf*: AuthResult spfDetail*: string ## e.g. "smtp.mailfrom=alice@example.com" dkim*: AuthResult dkimDetail*: string ## e.g. "header.d=example.com" dkimDomains*: seq[string] ## domains of passing signatures (for DMARC) dmarc*: AuthResult dmarcDetail*: string dmarcReject*: bool ## DMARC p=reject applied and enforcement on combined*: string ## Full Authentication-Results header value
AuthResult = enum arPass, arFail, arSoftFail, arNeutral, arNone, arTempError, arPermError
Procs
proc authenticateMessage(spfServerPtr: pointer; clientIp, heloDomain: string; headers: seq[Header]; body: string; envelopeFrom: string = ""; rawHeaderBlock: string = ""; keyLookup: DkimKeyLookup = nil; dmarcFetch: DmarcRecordLookup = nil; dmarcMode = "report"; authHost = "meowmail.local"; verifyDkimSigs = true): AuthHeader {. ...raises: [Exception], tags: [TimeEffect, RootEffect], forbids: [].}
-
Run all authentication checks on an incoming message and build the Authentication-Results header value.
SPF is evaluated against the envelope sender (RFC 7208), falling back to the From: domain only when the envelope is unavailable. DKIM signatures are cryptographically verified (RFC 6376) and DMARC is evaluated (RFC 7489) with SPF/DKIM alignment. dmarcMode controls enforcement: "report" never rejects, "quarantine" accepts and reports, "reject" marks dmarcReject when a p=reject policy applies so the caller can refuse the message.
proc renderAuthHeader(auth: AuthHeader): string {....raises: [], tags: [], forbids: [].}
- Render the Authentication-Results header.
proc verifyDkim(headers: seq[Header]; body: string; keyLookup: DkimKeyLookup = nil; rawHeaderBlock: string = ""): ( AuthResult, seq[string], string) {....raises: [Exception], tags: [TimeEffect, RootEffect], forbids: [].}
-
Cryptographically verify DKIM signature(s) in the message headers. Returns (result, passing domains, detail string).
The raw header block is preferred: simple canonicalization is only byte-exact when the original wire bytes are available. Without it the fields are rebuilt from parsed headers, which is exact for relaxed but best-effort for simple.
proc verifySpf(spfServerPtr: pointer; clientIp, heloDomain, mailFrom: string): ( AuthResult, string) {....raises: [], tags: [], forbids: [].}
- Verify the connecting IP against the sender's SPF record. Returns (result, detail string).