mailauth provides a command-line utility for email authentication, complementing its Node.js library. This guide explains how to use the mailauth CLI to perform various email authentication tasks.
Note
mailauth is used by EmailEngine for validating email authentication settings. See the Email Authentication Testing documentation for details.
- Installation
- Getting Help
- Available Commands
report— Validate SPF, DKIM, DMARC, ARC, and BIMIsign— Sign an email with DKIMdkim2-sign— Sign an email with DKIM2 (experimental)dkim2-verify— Verify the DKIM2 signatures of an email (experimental)dkim2-hash— Generate the DKIM2 header and body hashes for an emailseal— Seal an email with ARCspf— Validate SPF for an IP address and email addressvmc— Validate BIMI VMC logo filesbodyhash— Generate the body hash value for an emaillicense— Display licenses for mailauth and included modules
- DNS Cache File
- License
Install the mailauth CLI by downloading the appropriate package for your platform or via npm:
- MacOS:
- Linux:
- Windows:
- NPM Registry:
-
Install globally using npm:
npm install -g mailauth
-
To display help information for the mailauth CLI or any specific command, use the --help flag:
mailauth --help
mailauth report --help
mailauth sign --help
mailauth seal --help
mailauth spf --helpThe mailauth CLI offers several commands to perform different email authentication tasks:
report— Validate SPF, DKIM, DMARC, ARC, and BIMI, and optionally DKIM2.sign— Sign an email with DKIM.dkim2-sign— Sign an email with DKIM2 (experimental).dkim2-verify— Verify the DKIM2 signatures of an email (experimental).dkim2-hash— Generate the DKIM2 header and body hashes for an email.seal— Seal an email with ARC.spf— Validate SPF for an IP address and email address.vmc— Validate BIMI VMC logo files.bodyhash— Generate the body hash value for an email.license— Display licenses for mailauth and included modules.
Warning
DKIM2 is not a published RFC yet. The DKIM2 commands are experimental and built against draft-ietf-dkim-dkim2-spec-06, draft-ietf-dkim-dkim2-dns-00 and draft-ietf-dkim-dkim2-bcp-01, see DKIM2.
The report command analyzes an email message and returns a JSON-formatted report detailing the results of SPF, DKIM, DMARC, ARC, and BIMI validations.
mailauth report [options] [email]- email: (Optional) Path to the EML-formatted email message file. If omitted, the email is read from standard input.
--client-ip x.x.x.x,-i x.x.x.x: IP address of the remote client that sent the email. If not provided, it's parsed from the latestReceivedheader: the connecting address in the TCP-info comment of itsfromclause (RFC 5321 section 4.4), never an address the client gave in its HELO.--sender user@example.com,-f user@example.com: Email address from the MAIL FROM command. If not provided, it's parsed from the latestReturn-Pathheader.--helo hostname,-e hostname: Hostname from the HELO/EHLO command. Used in some SPF validations.--mta hostname,-m hostname: Hostname of the server performing validations. Defaults to the local hostname.--dns-cache /path/to/dns.json,-n /path/to/dns.json: Path to a DNS cache file. When provided, DNS queries use cached responses.--verbose,-v: Enables verbose output, displaying debugging information.--max-lookups number,-x number: Sets the maximum number of DNS lookups for SPF checks. Defaults to10.--max-void-lookups number,-z number: Sets the maximum number of void DNS lookups for SPF checks. Defaults to2.--strict: Follows the RFCs exactly instead of the lenient defaults, for example anrsa-sha1DKIM signature is reported asdkim=policy. See Strict mode.--reject-rsa-sha1: Reports anrsa-sha1DKIM signature asdkim=policyand does not count it for DMARC, as--strictdoes, while every other check keeps the lenient default.--dkim2: Verifies DKIM2 header fields as well. The result is in thedkim2key of the report and adkim2=entry is added to Authentication-Results. DKIM2 does not take part in DMARC.--rcpt-to user@example.com,-r user@example.com: RCPT TO address of the delivery, checked against the highest DKIM2-Signature together with--sender. Can be repeated. Without it the DKIM2 result has thercpt-to-not-checkedwarning.
mailauth report --verbose --dns-cache examples/dns-cache.json test/fixtures/message2.emlSample Output:
Reading email message from test/fixtures/message2.eml
DNS query for TXT mail.projectpending.com: not found
DNS query for TXT _dmarc.projectpending.com: not found
{
"receivedChain": [
"..."
]
}
For a detailed example of DKIM checks, refer to this gist.
The sign command signs an email message using a DKIM signature.
mailauth sign [options] [email]- email: (Optional) Path to the EML-formatted email message file. If omitted, the email is read from standard input.
--private-key /path/to/private.key,-k /path/to/private.key: Path to the private key used for signing.--domain example.com,-d example.com: Domain name for the DKIM signature (d=tag).--selector selector,-s selector: Selector for the DKIM key (s=tag).--algo algorithm,-a algorithm: Signing algorithm (e.g.,rsa-sha256). Defaults torsa-sha256for an RSA key anded25519-sha256for an Ed25519 key.--canonicalization method,-c method: Canonicalization method (e.g.,relaxed/relaxed). Defaults torelaxed/relaxed.--time timestamp,-t timestamp: Signing time as a Unix timestamp (t=tag).--header-fields "field1:field2",-h "field1:field2": Colon-separated list of header fields to include in the signature (h=tag). It must includeFrom.--body-length length,-l length: Maximum length of the body to include in the signature (l=tag).--headers-only,-o: Outputs only the DKIM signature headers without the entire message.--strict: Refuses to sign withrsa-sha1or with an RSA key shorter than 1024 bits (RFC 8301), and with a domain or selector that is not valid RFC 6376 syntax. Without it these are signed, and--verboseprints a warning.
mailauth sign /path/to/message.eml --domain example.com --selector s1 --private-key /path/to/private.key --verboseSample Output:
Reading email message from /path/to/message.eml
Signing domain: example.com
Key selector: s1
Canonicalization algorithm: relaxed/relaxed
Hashing algorithm: rsa-sha256
Signing time: 2023-03-15T12:00:00.000Z
--------
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=example.com;
h=MIME-Version:Date:Message-ID:Subject:To:From:Content-Type;
...
The dkim2-sign command signs an email message with DKIM2. It adds a DKIM2-Signature header field, and a Message-Instance header field when the message has none yet or has changed since its last instance. Use it as the originator of a message, or as a forwarder that adds its own hop to a message that is already DKIM2 signed.
mailauth dkim2-sign [options] [email]- email: (Optional) Path to the EML-formatted email message file. If omitted, the email is read from standard input.
--private-key /path/to/private.key,-k /path/to/private.key: Path to a private key, RSA (at least 1024 bits) or Ed25519. Repeat it to sign with several keys, each with its own--selector.--selector selector,-s selector: Selector of the private key in the same position. Can be repeated. At most two keys can use the same algorithm.--domain example.com,-d example.com: Signing domain (d=tag). It has to be the MAIL FROM domain or a parent of it.--mail-from user@example.com,-f user@example.com: MAIL FROM address the message is sent with (mf=tag),<>for the null sender.--rcpt-to user@example.net,-r user@example.net: RCPT TO address the message is sent to (rt=tag). Can be repeated.--next-domain example.net: For a hop across a trust boundary, the domain of the next DKIM2 signature (nd=tag). Used instead of--mail-fromand--rcpt-to.--flag flag: Flag to set (f=tag):donotmodify,donotexplode,exploded,feedbackorfeedhere. Can be repeated.--nonce value: A value for your own use (n=tag), at most 64 characters.--hash algorithm: Hash algorithm of a newMessage-Instance,sha256orsha512. Can be repeated. Defaults tosha256.--recipe /path/to/recipe.json: For a forwarder that changed the message, a JSON file with the Recipe that recreates the previous instance (r=tag). It is checked before signing, and the command fails if it does not recreate the previous instance.--time timestamp,-t timestamp: Signing time as a Unix timestamp (t=tag). Defaults to the current time.--headers-only,-o: Outputs only the DKIM2 header fields without the message.
Either --mail-from and --rcpt-to, or --next-domain, is required.
mailauth dkim2-sign /path/to/message.eml \
-k /path/to/rsa.key -s rsa2026 -k /path/to/ed25519.key -s ed2026 \
-d example.com -f bounces@example.com -r user@example.netSample Output:
DKIM2-Signature: i=1; m=1; t=1791646747; d=example.com; mf=
PGJvdW5jZXNAZXhhbXBsZS5jb20+; rt=PHVzZXJAZXhhbXBsZS5uZXQ+; s=rsa2026:rsa-sha256:
MXp6X81Tuu/cwbedt/kFqdO1sE4yPkfYVnFzfBMO2ZjfAtoXuptS+G79SYEpEaAo
...
Message-Instance: m=1; h=sha256:
sbKYVMaA7tqVLzGg5HTTU3o95q7ufdnBincKg/jBBQc=:
GjyEkbey2OupCW5AKJv4dzTPsPHSaZjRDMqUSmhpTyQ=;
From: ...
A mailing list that replaced the Subject header field, added a List-Id header field and appended a footer after the first 3 body lines signs its revision with a Recipe:
{ "h": { "subject": [{ "d": ["Original subject"] }], "list-id": [] }, "b": [{ "c": [1, 3] }] }mailauth dkim2-sign revised.eml -k list.key -s list -d list.example.org \
-f bounce@list.example.org -r member@example.net --recipe recipe.jsonThe dkim2-verify command verifies only the DKIM2 header fields of an email message and returns a JSON report. See DKIM2 Result Reference for the structure. Use report --dkim2 to check DKIM2 together with everything else.
mailauth dkim2-verify [options] [email]- email: (Optional) Path to the EML-formatted email message file. If omitted, the email is read from standard input.
--mail-from user@example.com,-f user@example.com: MAIL FROM address the message was delivered with,<>for the null sender. Checked against the highest DKIM2-Signature.--rcpt-to user@example.net,-r user@example.net: RCPT TO address the message was delivered to, checked against the highest DKIM2-Signature. Can be repeated.--dns-cache /path/to/dns.json,-n /path/to/dns.json: Path to a DNS cache file. When provided, DNS queries use cached responses.--time timestamp,-t timestamp: Time to verify against as a Unix timestamp. Defaults to the current time.--max-age seconds: Seconds after which a signature expires,0to not check. Defaults to 14 days.--max-future seconds: Seconds a signature timestamp may be ahead of the current time,0to not check. Defaults to300.--max-instances number: The mostMessage-Instance, and the mostDKIM2-Signature, header fields to process. Defaults to20.--headers-only,-o: Outputs only the Authentication-Results entry (dkim2=...) instead of the JSON report.--verbose,-v: Shows the DNS queries, and the parts of the envelope that were not checked.
The chain of custody against the delivery, which is what stops DKIM2 replay, is only checked for the parts of the envelope given with --mail-from and --rcpt-to. A missing part is reported in status.warnings.
mailauth dkim2-verify -f bounces@example.com -r user@example.net -o /path/to/message.emlSample Output:
dkim2=pass (i=1 example.com pass) header.d=example.com
The dkim2-hash command computes the DKIM2 header and body hashes of an email message, in the algorithm:header-hash:body-hash form of the h= tag of a Message-Instance header field. Use it to check what a Message-Instance should contain, for example when writing a Recipe.
mailauth dkim2-hash [options] [email]- email: (Optional) Path to the EML-formatted email message file. If omitted, the email is read from standard input.
--algo algorithm,-a algorithm: Hash algorithm,sha256orsha512. Can be repeated. Defaults tosha256.--verbose,-v: Also lists the header fields that go into the header hash. DKIM2 does not sign trace header fields,X-header fields, DKIM1, ARC and Authentication-Results header fields, or its own header fields.
mailauth dkim2-hash -v /path/to/message.emlSample Output:
Reading email message from /path/to/message.eml
Hashed header fields: content-type, date, from, message-id, mime-version, subject, to
--------
sha256:sbKYVMaA7tqVLzGg5HTTU3o95q7ufdnBincKg/jBBQc=:GjyEkbey2OupCW5AKJv4dzTPsPHSaZjRDMqUSmhpTyQ=
The seal command adds an ARC (Authenticated Received Chain) seal to an email message.
mailauth seal [options] [email]- email: (Optional) Path to the EML-formatted email message file. If omitted, the email is read from standard input.
Sealing Options:
--private-key /path/to/private.key,-k /path/to/private.key: Path to the private key used for sealing.--domain example.com,-d example.com: Domain name for the ARC seal (d=tag).--selector selector,-s selector: Selector for the ARC key (s=tag).--algo algorithm,-a algorithm: Sealing algorithm (e.g.,rsa-sha256). Defaults based on the private key type.--time timestamp,-t timestamp: Sealing time as a Unix timestamp (t=tag).--header-fields "field1:field2",-h "field1:field2": Colon-separated list of header fields to include in the seal (h=tag).--headers-only,-o: Outputs only the ARC seal headers without the entire message.--strict: Follows the RFCs exactly instead of the lenient defaults.
Seal-Only Options:
By default, seal authenticates the message (SPF, DKIM, DMARC, ARC) and embeds the computed results in the ARC-Authentication-Results header. If the message was already authenticated elsewhere (for example at an edge MTA) and modified afterwards, you can instead provide the original Authentication-Results value yourself. When one of the following options is set, no authentication checks or DNS lookups are performed:
--auth-results "authserv-id; spf=pass ...":Authentication-Resultsvalue to embed in theARC-Authentication-Resultsheader (the part afteri=N;). Used as is, except that line breaks are written as CRLF. A multi-line value must be folded: every line after the first starts with a space or a tab. A value with any other line break is refused, as it would start a new header field.--auth-results-file /path/to/value.txt: Same as--auth-results, but the value is read from a file. Useful for long or multi-line values. Cannot be combined with--auth-results.--cv status: Chain validation status for theARC-Sealheader (cv=tag):none,pass, orfail. Defaults tonone.--instance number: ARC instance number (i=tag). Defaults to the next instance number based on the existing ARC chain of the message, or1.
mailauth seal message.eml -d example.com -s s1 -k private.key \
--cv pass --auth-results-file auth-results.txt --headers-onlyAuthentication Options (from report command):
--client-ip x.x.x.x,-i x.x.x.x: IP address of the remote client that sent the email.--sender user@example.com,-f user@example.com: Email address from the MAIL FROM command.--helo hostname,-e hostname: Hostname from the HELO/EHLO command.--mta hostname,-m hostname: Hostname of the server performing validations.--dns-cache /path/to/dns.json,-n /path/to/dns.json: Path to a DNS cache file.--verbose,-v: Enables verbose output.
Note: The canonicalization method (c= tag) for ARC sealing is always relaxed/relaxed and cannot be changed.
mailauth seal /path/to/message.eml --domain example.com --selector s1 --private-key /path/to/private.key --verboseSample Output:
Reading email message from /path/to/message.eml
Signing domain: example.com
Key selector: s1
Canonicalization algorithm: relaxed/relaxed
Hashing algorithm: rsa-sha256
Sealing time: 2023-03-15T12:05:00.000Z
--------
ARC-Seal: i=3; a=rsa-sha256; t=1678884300; cv=pass; d=example.com; s=s1;
b=Fo3hayVos+J77lzzgmr6J92gsUBKlPt/ZkoQt9ZCi514zy8+1WLvTHmI8CMUXAcegdcqP0NHt
...
The spf command checks the SPF (Sender Policy Framework) record for a given email address and IP address.
mailauth spf [options]--sender user@example.com,-f user@example.com: Email address from the MAIL FROM command. Required.--client-ip x.x.x.x,-i x.x.x.x: IP address of the remote client that sent the email. Required.--helo hostname,-e hostname: Hostname from the HELO/EHLO command.--mta hostname,-m hostname: Hostname of the server performing the SPF check.--dns-cache /path/to/dns.json,-n /path/to/dns.json: Path to a DNS cache file.--verbose,-v: Enables verbose output.--headers-only,-o: Outputs only the SPF authentication header.--max-lookups number,-x number: Sets the maximum number of DNS lookups. Defaults to10.--max-void-lookups number,-z number: Sets the maximum number of void DNS lookups. Defaults to2.--max-elapsed-time ms: Maximum time in milliseconds for the whole SPF evaluation, after which the result istemperror. Not limited by default.--strict: Follows RFC 7208 exactly instead of the lenient defaults.
mailauth spf --verbose -f user@example.com -i 192.0.2.1Sample Output:
Checking SPF for user@example.com
Maximum DNS lookups: 10
--------
DNS query for TXT example.com: [["v=spf1 include:_spf.example.com -all"]]
DNS query for TXT _spf.example.com: [["v=spf1 ip4:192.0.2.0/24 -all"]]
{
"domain": "example.com",
"client-ip": "192.0.2.1",
"result": "pass",
"..."
}
The vmc command validates a Verified Mark Certificate (VMC) used in BIMI (Brand Indicators for Message Identification).
mailauth vmc [options]--authority <url>,-a <url>: URL of the VMC resource.--authorityPath <path>,-p <path>: Path to a local VMC file, used to avoid network requests.--domain <domain>,-d <domain>: Sender domain to validate against the certificate.--date <timestamp>,-t <timestamp>: ISO-formatted timestamp for certificate expiration checks. Defaults to the current time.
mailauth vmc -a https://example.com/path/to/vmc.pem -d example.comSample Output:
{
"url": "https://example.com/path/to/vmc.pem",
"success": true,
"domainVerified": true,
"vmc": {
"mediaType": "image/svg+xml",
"hashAlgo": "sha256",
"hashValue": "abc123...",
"logoFile": "<Base64 encoded SVG>",
"validHash": true,
"type": "VMC",
"certificate": {
"subject": {
"commonName": "Example Inc.",
"markType": "Registered Mark",
"..."
},
"subjectAltName": ["example.com"],
"fingerprint": "12:34:56:78:9A:BC:DE:F0...",
"serialNumber": "0123456789ABCDEF",
"validFrom": "2023-01-01T00:00:00.000Z",
"validTo": "2024-01-01T23:59:59.000Z",
"issuer": {
"commonName": "Trusted CA"
"..."
}
}
}
}If validation fails, the output includes error details:
{
"success": false,
"error": {
"message": "Self signed certificate in certificate chain",
"details": {
"..."
},
"code": "SELF_SIGNED_CERT_IN_CHAIN"
}
}The bodyhash command computes the body hash value of an email message, which is used in DKIM signatures.
mailauth bodyhash [options] [email]- email: (Optional) Path to the EML-formatted email message file. If omitted, the email is read from standard input.
--algo algorithm,-a algorithm: Hashing algorithm (e.g.,sha256). Defaults tosha256. Can also specify DKIM-style algorithms (e.g.,rsa-sha256).--canonicalization method,-c method: Body canonicalization method (e.g.,relaxed). Defaults torelaxed. Can use DKIM-style (e.g.,relaxed/relaxed).--body-length length,-l length: Maximum length of the body to hash (l=tag).--verbose,-v: Enables verbose output.
mailauth bodyhash /path/to/message.eml -a sha1 --verboseSample Output:
Hashing algorithm: sha1
Body canonicalization algorithm: relaxed
--------
j+dD7whKXS1yDmyoWtvClYSyYiQ=
The license command displays the licenses for mailauth and its included modules.
mailauth licensemailauth licenseSample Output:
mailauth License: MIT License
Included Modules:
- module1: MIT License
- module2: Apache License 2.0
...
The --dns-cache option allows you to use a JSON-formatted DNS cache file for testing purposes. This avoids the need to set up a DNS server or wait for DNS propagation.
The DNS cache file is a JSON object where:
- Keys: Fully qualified domain names (e.g.,
"example.com"). DKIM and DKIM2 keys are looked up asselector._domainkey.domain. - Values: Objects with DNS record types as keys (e.g.,
"TXT","MX") and their corresponding values.
Example:
{
"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;"]]
}
}Specify the DNS cache file using the --dns-cache option:
mailauth report --dns-cache /path/to/dns-cache.json email.emlWhen this option is used, mailauth will not perform actual DNS queries but will use the data from the cache file instead.
© 2020-2026 Postal Systems OÜ
Licensed under the MIT License.
