mailauth

repository·master·Indexed 41 days ago

https://github.com/postalsys/mailauth

A comprehensive Node.js library and command-line utility for email authentication. Version 5.0.3 supports verifying and signing emails using SPF, DKIM, DMARC, ARC, BIMI, and MTA-STS protocols. It provides a primary `authenticate()` function for multi-protocol validation, `dkimSign()` for digital signatures, and specialized tools for ARC sealing and MTA-STS policy retrieval.

Tokens
26.3K
Snippets
81
Records
121
Agent score
99%

What's inside mailauth

  1. Overview of mailauth features

    master

    mailauth is a pure JavaScript library and CLI utility for email authentication in Node.js. It supports the following security protocols:

    • SPF: Verification
    • DKIM: Signing and verification
    • DMARC: Verification
    • ARC: Verification and sealing (both during authentication and after message modifications)
    • BIMI: Resolving and VMC validation
    • MTA-STS: Helper functions for policy retrieval and MX validation
  2. Understand MTA-STS policy modes

    master

    MTA-STS policies operate in one of three modes which dictate how a client should behave when encountering a policy:

    • enforce: Strictly enforce TLS and MX restrictions. If an MX host does not match the policy, delivery should be rejected.
    • testing: Policy is in test mode. Violations should be reported, but delivery should not be blocked.
    • none: No policy is in effect; no restrictions are applied.
  3. Get help with mailauth CLI commands

    master

    Use the --help flag to display help information for the main utility or for any specific subcommand. This is useful for discovering available flags and arguments for commands like report, sign, seal, or spf.

    mailauth --help
    mailauth report --help
    mailauth sign --help
    mailauth seal --help
    mailauth spf --help
  4. Use mailauth as a Node.js library

    master

    After installing via npm, you can import the required methods into your JavaScript project. For example, to access the authentication functionality, use require('mailauth').

    const { authenticate } = require('mailauth');
  5. Use a DNS cache file for testing

    master

    To avoid performing actual DNS queries or waiting for DNS propagation during testing, you can provide a JSON-formatted DNS cache file using the --dns-cache option. When this option is used, mailauth will use the data from the file instead of querying live DNS servers.

    DNS Cache File Format

    The file must be a JSON object where:

    • Keys: Fully qualified domain names (e.g., "example.com").
    • Values: Objects containing DNS record types (e.g., "TXT", "MX") as keys and their corresponding values as arrays.

    Usage Example

    mailauth report --dns-cache /path/to/dns-cache.json email.eml
    {
        "example.com": {
            "TXT": [["v=spf1 include:_spf.example.com -all"]],
            "MX": [{ "exchange": "mail.example.com", "priority": 10 }]
        },
        "_dmarc.example.com": {
            "TXT": [["v=DMARC1; p=reject; rua=mailto:dmarc@example.com;"]]
        }
    }
  6. Seal messages with ARC

    master

    ARC (Authenticated Received Chain) can be handled in two ways:

    1. Sealing during authentication

    If you provide a seal object in the authenticate() options, the message will be automatically sealed during the authentication process.

    const { authenticate } = require('mailauth');
    const fs = require('fs');
    
    const { headers } = await authenticate(message, {
      trustReceived: true,
      seal: {
        signingDomain: 'tahvel.info',
        selector: 'test.rsa',
        privateKey: fs.readFileSync('./test/fixtures/private-rsa.pem'),
      },
    });

    2. Sealing after modifications

    If you must modify the message after authentication, use sealMessage(). You must pass the authentication results from the initial authenticate() call to ensure the chain is valid.

    const { authenticate, sealMessage } = require('mailauth');
    const fs = require('fs');
    
    // 1. Authenticate
    const { arc, headers } = await authenticate(message, {
      ip: '217.146.67.33',
      helo: 'uvn-67-33.tll01.zonevs.eu',
      mta: 'mx.ethereal.email',
      sender: 'andris@ekiri.ee',
    });
    
    // 2. Modify message...
    
    // 3. Seal
    const sealHeaders = await sealMessage(message, {
      signingDomain: 'tahvel.info',
      selector: 'test.rsa',
      privateKey: fs.readFileSync('./test/fixtures/private-rsa.pem'),
      authResults: arc.authResults,
      cv: arc.status.result,
    });
  7. Validate VMC with validateVMC()

    master

    To perform full VMC (Verified Mark Certificate) validation, use validateVMC() from mailauth/lib/bimi. This process fetches the logo and authority documents to ensure they are valid and match.

    Usage Pattern

    1. Resolve BIMI via authenticate.
    2. Pass the bimi result to validateVMC.
    3. If successful, use the headers object from the result to add BIMI headers to the message.

    Note for MTAs: When adding headers after successful validation, you should first remove any existing BIMI-* headers from the incoming message.

    const { bimi, validateVMC } = require('mailauth/lib/bimi');
    
    const bimiResult = await bimi(data); // Note: bimi(data) is used in the context of the library's internal flow
    const vmcResult = await validateVMC(bimiResult, options);
    const { bimi, validateVMC } = require('mailauth/lib/bimi');
    
    const bimiResult = await bimi(data);
    const vmcResult = await validateVMC(bimiResult, options);
  8. Understand BIMI validation status results

    master

    When using the BIMI module, the status.result field indicates why a BIMI check succeeded or failed. This is useful for debugging email authentication flows.

    ResultMeaning
    passBIMI record is valid and present.
    skippedBIMI was not checked because prerequisites weren't met (e.g., DMARC not enabled, too lax DMARC policy, Aligned DKIM signature required, or undersized DKIM signature).
    failThe BIMI record exists but is malformed (e.g., multiple BIMI-Selector headers, missing bimi version in selector header, missing bimi version in dns record, invalid location value in dns record, or missing location value in dns record).
    noneNo BIMI record was found in DNS.
    temperrA temporary error occurred (e.g., failed to resolve <domain>).