postalsys / mailauth Goto Github PK
View Code? Open in Web Editor NEWCommand line utility and a Node.js library for email authentication
License: Other
Command line utility and a Node.js library for email authentication
License: Other
Latest mailauth
depends on a vulnerable library, please provide an update.
# npm audit report
fast-xml-parser <4.2.4
Severity: high
fast-xml-parser vulnerable to Regex Injection via Doctype Entities - https://github.com/advisories/GHSA-6w63-h3fj-q4vw
fix available via `npm audit fix --force`
Will install [email protected], which is a breaking change
node_modules/fast-xml-parser
mailauth >=3.0.2
Depends on vulnerable versions of fast-xml-parser
node_modules/mailauth
Right now getDmarcRecord
could easily be exposed via exports
or module.exports
.
However there's no getSpfRecord
, albeit one could be added similarly with a returned object including values such as qualifier
.
Describe the bug
I think but I'm not entirely sure the SPF tester is unhappy with domain names having MX records pointing at uppercase mail exchange hostnames
To Reproduce
Steps to reproduce the behavior:
Testing SPF record validity on a domain like: vgpt.dk
results in this error:
permanent error in processing during lookup of [email protected]: Invalid domain ASPMX.L.GOOGLE.COM)\r\n
dig vgpt.dk MX
vgpt.dk. 3505 IN MX 5 ALT1.ASPMX.L.GOOGLE.COM.
vgpt.dk. 3505 IN MX 5 ALT2.ASPMX.L.GOOGLE.COM.
vgpt.dk. 3505 IN MX 10 ALT3.ASPMX.L.GOOGLE.COM.
vgpt.dk. 3505 IN MX 1 ASPMX.L.GOOGLE.COM.
vgpt.dk. 3505 IN MX 10 ALT4.ASPMX.L.GOOGLE.COM.
Expected behavior
Uppercase mail exchanger hostnames should not be an issue
I think that this might only occur with large bodies (e.g. messages that get forwarded/replied to etc).
Our usage is here, and we apply and verify a signature from our side (not dependent on a third party).
Here's where we use mailauth
to sign and then verify:
Any idea what might be wrong @andris9?
Here's what dkim
variable output is from above linked code for this case where body hash did not verify
occurs:
{
"id": "97d0704fa6532ffc464d91848bfff529c3a7901418f6a5ae96c4da743aea78eb",
"signingDomain": "redacted.com",
"selector": "fe-redacted",
"signature": "xOsyw/9QxTmDGWSe3pqI/a+JA+KvDCleqTKmzQxpB5ABrvq0ywEjBAd4W4YqbwJLaN5TDOC6KIZJqKPLPHKb83KyIUrPXtw84Ecv7D+1OOVeZDBjUW4GoykQFYuSAFGBpjSwENu3mva5D5aN6rEHkhi9KIUmPt4GdZAWBErnVFY=",
"algo": "rsa-sha256",
"format": "relaxed/relaxed",
"bodyHash": "MEyQD56x/T6mAyiOCf9Wb3Bbv+F5uc5F2JyGTfkYXiY=",
"bodyHashExpecting": "nNcD0wNn1JDvNR4xBIDnXZfySkjnkuY9D6YZ/PaDeJI=",
"signingHeaders": {
"keys": "Content-Type: To: Subject: Message-ID: Date: From: Reply-To: In-Reply-To: References: MIME-Version",
"headers": [
"Content-Type: multipart/alternative; boundary=\"000000000000d28675061495178e\"",
"To: redacted",
"Subject: Re: Redacted",
"Message-ID: <[email protected]>",
"Date: Tue, 26 Mar 2024 15:13:51 -0400",
"From: redacted redacted <[email protected]>",
"Reply-To: [email protected]",
"In-Reply-To: <[email protected]>",
"References: <[email protected]>\r\n <[email protected]>\r\n <[email protected]>\r\n <[email protected]>\r\n <[email protected]>\r\n <[email protected]>\r\n <[email protected]>\r\n <[email protected]>\r\n <[email protected]>\r\n <[email protected]>\r\n <[email protected]>\r\n <[email protected]>\r\n <[email protected]>\r\n <[email protected]>\r\n <[email protected]>\r\n <[email protected]> <[email protected]>",
"MIME-Version: 1.0"
],
"canonicalizedHeader": "Y29udGVudC10eXBlOm11bHRpcGFydC9hbHRlcm5hdGl2ZTsgYm91bmRhcnk9IjAwMDAwMDAwMDAwMGQyODY3NTA2MTQ5NTE3OGUiDQp0bzpDaGFudGVsIER1cHVpcyA8Y2hhbnRlbC5kdXB1aXNAZGl2ZXJzaWNvLmNhPg0Kc3ViamVjdDpSZTogUkVTUCBJbmZvcm1hdGlvbg0KbWVzc2FnZS1pZDo8Q0FPVWNyZmZ1KzhNOUZRU3ZiYVRBNGJfNHNvOXZfNmtpZ09WPVNwRktTQi1xRHRaaUV3QG1haWwuZ21haWwuY29tPg0KZGF0ZTpUdWUsIDI2IE1hciAyMDI0IDE1OjEzOjUxIC0wNDAwDQpmcm9tOkdhcnkgQmVsYW5nZXIgPGdhcnlAYmVsYW5nZXJob21lLmNvbT4NCnJlcGx5LXRvOmdhcnlAYmVsYW5nZXJob21lLmNvbQ0KaW4tcmVwbHktdG86PENBTHN2WkVZb1pIV2hrd1lvdERFZ0c1V09xM2U5c1NBPWErRHVaQnBZU1BKdjZRdHBmd0BtYWlsLmdtYWlsLmNvbT4NCnJlZmVyZW5jZXM6PENBTHN2WkVac2dmRWlEKzVwYVc5K09reE9QVEc5YVMwRzYtcGJNblI9XzBIRUpZNXE0QUBtYWlsLmdtYWlsLmNvbT4gPENBQTNxU0VGdUZMLVhBZFE4a3NlemEwTEV1VC01TE0wUkpGTmNZdD1VUndpZEpCRkNwUUBtYWlsLmdtYWlsLmNvbT4gPENBTHN2WkVZU3M1VitVeV9aNk5WNExZLXJzdFRLVmJFWDVTYW9xQTRpWGM2enJ5Wjk5d0BtYWlsLmdtYWlsLmNvbT4gPENBQTNxU0VIbWJtazFrUGYzWVF4anRHYzRzbk1NSFA3YXdBcEJFYnVHZVpoUHY3TlBfd0BtYWlsLmdtYWlsLmNvbT4gPENBTHN2WkViK1pFTGgyZk1ISnRnWE95Y2lnWjl5c2kzWXpXdHJ3d3J0ZWlTUGkwY1NFd0BtYWlsLmdtYWlsLmNvbT4gPENBQTNxU0VIV2Z6b2hCZzNVM2QyS282NTVMTnBzVzJVNG5RdEdzYjNWZ3ctOGVWV25WQUBtYWlsLmdtYWlsLmNvbT4gPENBTHN2WkViNjBqVU5NOWk9S3JwM2lubWt0ZVBNR2dRb2pmYT1BelZPeUNXTjMzaW9pQUBtYWlsLmdtYWlsLmNvbT4gPENBQTNxU0VHVkhLNkhjQyt4NHB2K2RTNisrcmtFVldieFY2dm01cHM3NVNhN3grZGdld0BtYWlsLmdtYWlsLmNvbT4gPENBTHN2WkViN1VBcWQ4RGRLRU5xNWpvb2RxXzIzWVV3TXhVUFFYVldqdWFHMzRnMllmUUBtYWlsLmdtYWlsLmNvbT4gPENBQTNxU0VIdFRKZFJQTzFwNnErYndPSDJQME1talprRTRFSEtHa3ZUVlVPOV8xdkw1Z0BtYWlsLmdtYWlsLmNvbT4gPENBTHN2WkVhUzBtOT15ZStPclBaMGZnUD1tODIzV3hET01OOVZCdE1pU249Wkc3R1pld0BtYWlsLmdtYWlsLmNvbT4gPENBQTNxU0VGVzltbWtQeVZYUGZjREV3ZXE3QmhqYUFveFhkVjViTUdZNnE0Y1VEV3NqQUBtYWlsLmdtYWlsLmNvbT4gPENBTHN2WkVZNjZ2b29OVmVvQV9rZHpFenJBdU8yMjE5cnZ1LV9RM3ZqeVRtNDcxUD0yZ0BtYWlsLmdtYWlsLmNvbT4gPENBQTNxU0VFM0FSU1h6bl82Q0EyVllYNDB5U1VvRWM0Z19VZUNqRit3Yys9MWY1QUZpZ0BtYWlsLmdtYWlsLmNvbT4gPENBTHN2WkVZR0FHakM3eHpXWVFQY2lZNlYrTlVkVHErYWlkZGtmQjgzWk5oPXp3SnRkUUBtYWlsLmdtYWlsLmNvbT4gPENBT1VjcmZkRFpqLWQ0UHdTYTJBS1EyTU1FcTRZYjljdFpyZkZoT1g5QmRoN0MySlROQUBtYWlsLmdtYWlsLmNvbT4gPENBTHN2WkVZb1pIV2hrd1lvdERFZ0c1V09xM2U5c1NBPWErRHVaQnBZU1BKdjZRdHBmd0BtYWlsLmdtYWlsLmNvbT4NCm1pbWUtdmVyc2lvbjoxLjANCmRraW0tc2lnbmF0dXJlOnY9MTsgYT1yc2Etc2hhMjU2OyBjPXJlbGF4ZWQvcmVsYXhlZDsgZD1iZWxhbmdlcmhvbWUuY29tOyBoPUNvbnRlbnQtVHlwZTogVG86IFN1YmplY3Q6IE1lc3NhZ2UtSUQ6IERhdGU6IEZyb206IFJlcGx5LVRvOiBJbi1SZXBseS1UbzogUmVmZXJlbmNlczogTUlNRS1WZXJzaW9uOyBxPWRucy90eHQ7IHM9ZmUtZWE5NjlmNmYxMDsgdD0xNzExNjY0Nzg3OyBiaD1uTmNEMHdObjFKRHZOUjR4QklEblhaZnlTa2pua3VZOUQ2WVovUGFEZUpJPTsgYj0="
},
"status": {
"result": "neutral",
"comment": "body hash did not verify",
"header": {
"i": "@redacted.com",
"s": "fe-redacted",
"a": "rsa-sha256",
"b": "xOsyw/9Q"
},
"aligned": "redacted.com"
},
"sourceBodyLength": 94578,
"canonBodyLength": 94314,
"canonBodyLengthTotal": 94314,
"canonBodyLengthLimited": false,
"mimeStructureStart": 0,
"info": "dkim=neutral (body hash did not verify) [email protected] header.s=fe-redacted header.a=rsa-sha256 header.b=\"xOsyw/9Q\""
}
DMARC lookups are not returning accurate data right now due to the psl
library being used.
An example use case is a headerFrom
of [email protected]
.
> require('psl').get('pay-dartford-crossing-fine.service.gov.uk')
'pay-dartford-crossing-fine.service.gov.uk'
Since it is not returning service.gov.uk
in the psl.get('pay-dartford-crossing-fine.service.gov.uk')
invocation, the orgDomain
is not being properly looked up and therefore the DMARC policy returned is none
, when it should actually be this one:
❯ dig _dmarc.service.gov.uk txt
_dmarc.service.gov.uk. 1124 IN TXT "v=DMARC1; p=reject; sp=reject; fo=1; rua=mailto:[email protected]; ruf=mailto:[email protected]"
We are submitting a pull request now to swap out psl
in favor of a different more maintained project.
Is your feature request related to a problem? Please describe.
I would like to use mailauth in a Cloudflare Worker, it's currently not possible
Describe the solution you'd like
mailauth uses XMLHttpRequest, this is not supported by Cloudflare workers, they use fetch instead
mailauth depends an a package with a known security vulnerability.
# npm audit report
undici <5.26.2
Undici's cookie header not cleared on cross-origin redirect in fetch - https://github.com/advisories/GHSA-wqq4-5wpv-mx2g
fix available via `npm audit fix --force`
Will install [email protected], which is a breaking change
node_modules/undici
mailauth >=4.5.1
Depends on vulnerable versions of undici
node_modules/mailauth
Steps to reproduce the behavior:
dig +short TXT officedepot.com | grep spf
"v=spf1 include:%{i}._ip.%{h}._ehlo.%{d}._spf.vali.email ~all"
dig +short TXT 205.157.110.125._ip.odmailout01.officedepot.com._ehlo.officedepot.com._spf.vali.email
"v=spf1 ip4:205.157.110.125 -all"
It looks like macros aren't supported by this library or standard Node.js DNS lookups?
Hello!
Encountered CPU stuck at 100% on all our inbound email microservices fleet this night and morning, for a repeated number of times after manual NodeJS process restarts probably due to SMTP delivery retries.
The issue seems to be a DOS, which was traced to origin in mailauth
DKIM module after performing a Node profile (--prof
), here's the trace extract from the processed profile:
ticks parent name
813252 88.5% /usr/lib/x86_64-linux-gnu/libc.so.6
755301 92.9% JS: *fixLineBuffer /app/node_modules/mailauth/lib/dkim/body/relaxed.js:125:18
755299 100.0% JS: *update /app/node_modules/mailauth/lib/dkim/body/relaxed.js:169:11
755297 100.0% JS: *processChunk /app/node_modules/mailauth/lib/dkim/message-parser.js:40:23
755291 100.0% JS: ^writeAsync /app/node_modules/mailauth/lib/dkim/message-parser.js:112:21
755291 100.0% JS: ^_write /app/node_modules/mailauth/lib/dkim/message-parser.js:128:11
96000 10.4% UNKNOWN
60769 63.3% JS: *fixLineBuffer /app/node_modules/mailauth/lib/dkim/body/relaxed.js:125:18
60761 100.0% JS: *update /app/node_modules/mailauth/lib/dkim/body/relaxed.js:169:11
60751 100.0% JS: *processChunk /app/node_modules/mailauth/lib/dkim/message-parser.js:40:23
60718 99.9% JS: ^writeAsync /app/node_modules/mailauth/lib/dkim/message-parser.js:112:21
60718 100.0% JS: ^_write /app/node_modules/mailauth/lib/dkim/message-parser.js:128:11
1144 1.2% JS: *isSignature /app/node_modules/email-reply-parser/lib/parser/emailparser.js:143:14
1144 100.0% JS: ^<anonymous> /app/node_modules/email-reply-parser/lib/parser/emailparser.js:43:50
1144 100.0% JS: ^parse /app/node_modules/email-reply-parser/lib/parser/emailparser.js:37:8
1144 100.0% JS: ^read /app/node_modules/email-reply-parser/lib/emailreplyparser.js:4:9
1144 100.0% JS: ^<anonymous> /app/src/helpers/parser.js:1491:15
1083 1.1% JS: ^createPublicKey node:internal/crypto/keys:611:25
1082 99.9% JS: ^getPublicKey /app/node_modules/mailauth/lib/tools.js:237:22
841 77.7% JS: *processTicksAndRejections node:internal/process/task_queues:67:35
241 22.3% JS: ^processTicksAndRejections node:internal/process/task_queues:67:35
When tracing the code, there appears to be some O(n^2) algorithm involved here (no Regex, this does not appear to be a ReDOS to me): https://github.com/postalsys/mailauth/blob/master/lib/dkim/body/relaxed.js#L212
I unfortunately do not have the original mail data which triggered this possible DOS vulnerability, since we do not keep a record of emails that went through before processing them. I'm trying to obtain the email content now.
Right now there is no way to internally call the tools that mailauth
uses such as getAligment
and getDmarcRecord
to get whether dkim
and spf
were aligned based off the DMARC policy.
It would be helpful to expose these in DMARC resulting object as properties such as spfAligned: boolean
and dkimAligned: boolean
, based off the same value exposed here:
https://github.com/postalsys/mailauth/blob/master/lib/dmarc/verify.js#L149-L158
Hi, I saw a 4.6.1 release was published 🎉 but the assets seem to be missing. For example, the mailauth-arm.pkg
referenced in the Install docs. Is there some CI script that needs to run to generate these?
the RFC for SPF defines a DNS lookup limit of 10. It seems like the current SPF validation check does not detect that.
Describe the solution you'd like
Have a correct SPF softfail if there are over 10 lookups. Also, it would be great to have
https://github.com/mediamonks/node-spf-check is an older project that has some code related to handling lookup limits.
spf({
sender: '[email protected]',
ip: '2607:f8b0:4864:20::b2b',
helo: 'mail-yb1-xb2b.google.com',
mta: 'mta.mydomain.com'
}).then((sr) => {
console.log(sr)
}).catch(e=>{
});
this giving result as softfail
? i think it should be pass
i also tried wrapping ip inside [ ] it gives neutral
Describe the bug
The used node-forge
package has a security vulnerability. While the code in question may not be triggered by mailauth
, the vulnerable module breaks out CI/CD process. Please upgrade node-forge
:
$ npm audit --production
# npm audit report
node-forge <1.3.0
Severity: moderate
Improper Verification of Cryptographic Signature in `node-forge` - https://github.com/advisories/GHSA-2r2c-g63r-vccr
No fix available
node_modules/mailauth/node_modules/node-forge
mailauth *
Depends on vulnerable versions of node-forge
node_modules/mailauth
2 moderate severity vulnerabilities
Some issues need review, and may require choosing
a different dependency.
What are your problems replacing node-forge
with webcrypto
completely?
Describe the bug
When the SPF check is performed on certain domains the "rr" field is not set.
To Reproduce
Perform an SPF check on bimco.org
Expected behavior
Valid SPF records (rr field) should always be returned
Describe the bug
Not really bug, just a question, and I couldn't find another way to contact you.
Is there a way to configure DNS timeout values?
From time to time, I detect invalid SPF records, and if I try again, the issue is gone.
DNS timeouts are the only reason I can think of.
Is your feature request related to a problem? Please describe.
After checking a DKIM signature and finding that results.status.result === "pass" how can I find out what headers were signed?
I would like to know which headers I can now trust, and which I might treat with skepticism.
Describe the solution you'd like
I would like the list of headers returned.
Describe alternatives you've considered
The alternative is for me to search for and parse this signature myself, I guess.
Additional context
We're writing as we discovered an edge case where vacation auto-responders from Yahoo would normally have passing SPF and DKIM (thus a passing DMARC), but when using mailauth
, not only do we get a negative DMARC result, we also get a negative SPF and DKIM result too. Gmail for example reports these vacation response messages from Yahoo as having passing DMARC, DKIM, and SPF.
We've included a complete test for you as well so you can see the result.
mailauth --verbose --client-ip 66.163.189.147 --sender [email protected] --helo sonic314-21.consmr.mail.ne1.yahoo.com --mta mx1.forwardemail.net test.txt
Reading email message from test.txt
{
"dkim": {
"headerFrom": [
"[email protected]"
],
"envelopeFrom": "[email protected]",
"results": [
{
"signingDomain": "yahoo.com",
"selector": "s2048",
"signature": "U6xSIk/z+xTpR2vRhfKVn9ONotJWf2WTvroxSg5/kCtQ+zxcvUdCaH80Py+Cz7TtieCy77/kRqFzpJTp1R1OJf+m9TeS2DUaijVM8RKdbmHmZhRY6/YwKyJdhj9+9z6y7jVcxqS+7+ib+wqipOKE5Q6p87zLlXfOXgYsFh/Bott86PFmf5sKhf1C/LkmPreJE4ep21AU7NM4zaTLhY8fS2fdKDDXq2cyaE8LKu9CkWCcUaMqmFJ11GQetDZvCD5nBIR89GvM8IAWmPWWFGSD7c1AJcOC51+1ILcfsg8IqPhLUPpDPsRbT2Z31LI9clxlPvaI6yRanTnj0Cf3LJ5UIQ==",
"algo": "rsa-sha256",
"format": "relaxed/relaxed",
"bodyHash": "mD4IKcP0SaNBDF959LqTWtanj/53dx+DHlUfLpHedO4=",
"bodyHashExpecting": "mD4IKcP0SaNBDF959LqTWtanj/53dx+DHlUfLpHedO4=",
"signingHeaders": {
"keys": "Date: From: To: Subject",
"headers": [
"Date: Fri, 29 Jul 2022 19:22:11 +0000 (UTC)",
"From: Forwared Email <[email protected]>",
"To: <[email protected]>",
"Subject: Auto Response: Attempt to show failure"
]
},
"status": {
"result": "fail",
"header": {
"i": "@yahoo.com",
"s": "s2048",
"a": "rsa-sha256",
"b": "U6xSIk/z"
},
"aligned": "yahoo.com"
},
"canonBodyLength": 371,
"publicKey": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuoWufgbWw58MczUGbMv1\n76RaxdZGOMkQmn8OOJ/HGoQ6dalSMWiLaj8IMcHC1cubJx2gziAPQHVPtFYayyLA\n4ayJUSNk10/uqfByiU8qiPCE4JSFrpxflhMIKV4bt+g1uHw7wLzguCf4YAoR6XxU\nKRsAoHuoF7M+v6bMZ/X1G+viWHkBl4UfgJQ6O8F1ckKKoZ5KqUkJH5pDaqbgs+F3\nPpyiAUQfB6EEzOA1KMPRWJGpzgPtKoukDcQuKUw9GAul7kSIyEcizqrbaUKNLGAm\nz0elkqRnzIsVpz6jdT1/YV5Ri6YUOQ5sN5bqNzZ8TxoQlkbVRy6eKOjUnoSSTmSA\nhwIDAQAB\n-----END PUBLIC KEY-----",
"modulusLength": 2048,
"rr": "k=rsa;p=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAuoWufgbWw58MczUGbMv176RaxdZGOMkQmn8OOJ/HGoQ6dalSMWiLaj8IMcHC1cubJx2gziAPQHVPtFYayyLA4ayJUSNk10/uqfByiU8qiPCE4JSFrpxflhMIKV4bt+g1uHw7wLzguCf4YAoR6XxUKRsAoHuoF7M+v6bMZ/X1G+viWHkBl4UfgJQ6O8F1ckKKoZ5KqUkJH5pDaqbgs+F3PpyiAUQfB6EEzOA1KMPRWJGpzgPtKoukDcQuKUw9GAul7kSIyEcizqrbaUKNLGAmz0elkqRnzIsVpz6jdT1/YV5Ri6YUOQ5sN5bqNzZ8TxoQlkbVRy6eKOjUnoSSTmSAhwIDAQAB;",
"info": "dkim=fail [email protected] header.s=s2048 header.a=rsa-sha256 header.b=\"U6xSIk/z\""
}
]
},
"spf": {
"domain": "yahoo.com",
"client-ip": "66.163.189.147",
"helo": "sonic314-21.consmr.mail.ne1.yahoo.com",
"envelope-from": "[email protected]",
"rr": "v=spf1 redirect=_spf.mail.yahoo.com",
"status": {
"result": "neutral",
"comment": "mx1.forwardemail.net: 66.163.189.147 is neither permitted nor denied by domain of [email protected]",
"smtp": {
"mailfrom": "[email protected]",
"helo": "sonic314-21.consmr.mail.ne1.yahoo.com"
}
},
"header": "Received-SPF: neutral (mx1.forwardemail.net: 66.163.189.147 is neither permitted nor denied by domain of [email protected]) client-ip=66.163.189.147;",
"info": "spf=neutral (mx1.forwardemail.net: 66.163.189.147 is neither permitted nor denied by domain of [email protected]) [email protected] smtp.helo=sonic314-21.consmr.mail.ne1.yahoo.com",
"lookups": {
"limit": 50,
"count": 2
}
},
"dmarc": {
"status": {
"result": "fail",
"comment": "p=REJECT arc=none",
"header": {
"from": "yahoo.com",
"d": "yahoo.com"
}
},
"domain": "yahoo.com",
"policy": "reject",
"p": "reject",
"sp": "reject",
"pct": 100,
"rr": "v=DMARC1; p=reject; pct=100; rua=mailto:[email protected]; ruf=mailto:[email protected];",
"alignment": {
"spf": {
"result": false,
"strict": false
},
"dkim": {
"result": false,
"strict": false
}
},
"info": "dmarc=fail (p=REJECT arc=none) header.from=yahoo.com header.d=yahoo.com"
},
"arc": {
"status": {
"result": "none"
},
"i": 0,
"authResults": "mx1.forwardemail.net;\r\n dkim=fail [email protected] header.s=s2048 header.a=rsa-sha256 header.b=\"U6xSIk/z\";\r\n spf=neutral (mx1.forwardemail.net: 66.163.189.147 is neither permitted nor denied by domain of [email protected])\r\n [email protected] smtp.helo=sonic314-21.consmr.mail.ne1.yahoo.com;\r\n dmarc=fail (p=REJECT arc=none) header.from=yahoo.com header.d=yahoo.com;\r\n bimi=skipped (message failed DMARC)"
},
"bimi": {
"status": {
"header": {},
"result": "skipped",
"comment": "message failed DMARC"
},
"info": "bimi=skipped (message failed DMARC)"
},
"receivedChain": [
{
"from": {
"value": "sonic.gate.mail.ne1.yahoo.com"
},
"by": {
"value": "sonic314.consmr.mail.ne1.yahoo.com"
},
"with": {
"value": "HTTP"
},
"timestamp": "Fri, 29 Jul 2022 19:22:11 +0000",
"full": "Received: from sonic.gate.mail.ne1.yahoo.com by sonic314.consmr.mail.ne1.yahoo.com with HTTP; Fri, 29 Jul 2022 19:22:11 +0000"
}
],
"headers": "Received-SPF: neutral (mx1.forwardemail.net: 66.163.189.147 is neither permitted nor denied by domain of [email protected]) client-ip=66.163.189.147;\r\nAuthentication-Results: mx1.forwardemail.net;\r\n dkim=fail [email protected] header.s=s2048 header.a=rsa-sha256 header.b=\"U6xSIk/z\";\r\n spf=neutral (mx1.forwardemail.net: 66.163.189.147 is neither permitted nor denied by domain of [email protected])\r\n [email protected] smtp.helo=sonic314-21.consmr.mail.ne1.yahoo.com;\r\n dmarc=fail (p=REJECT arc=none) header.from=yahoo.com header.d=yahoo.com;\r\n bimi=skipped (message failed DMARC)\r\n"
}
Contents of test-new.eml
are attached: test.txt
why does a DKIM body hash not verify if message body starts with \
character?
Twitter has issue with mailauth
in that DKIM results have random "invalid public key" results.
Filing this here and will follow-up if can get more details.
BIMI spec
The README has an example of using sealMessage
function. In this example the documentation has incorrectly written the package name as @postalsys/mailauth
instead of the newly updated name mailauth
. Also, the function sealMessage
is not exported top level, instead it must be required via lib folder.
Is your feature request related to a problem? Please describe.
Currently, it's hard to know what properties are available on the result object and there is no type safety when using TypeScript.
Describe the solution you'd like
I'd love to have TypeScript types either shipped with the package or published under @types/
Describe alternatives you've considered
Typing everything as any
:)
Additional context
I tried writing types with some AI help from the example JSON: https://gist.githubusercontent.com/andris9/6514b5e7c59154a5b08636f99052ce37/raw/a6fa78c400fd7068de502e878f0da1eb9334cd7b/mailauth.json
It seems that is currently the only documentation of what properties are available?
Unfortunately I don't know nearly enough about the internals of the library and all the email specs to know which properties should be optional/required etc so some help would be greatly appreciated — even if in the form of written API documentation (list of fields and types) or JSDoc. It would also be nice to add descriptions for the fields. I'd be happy to help writing types from that.
Here's what I got with AI help (which unfortunately still has some type errors with the result JSON):
export interface EmailAuthenticationResult {
dkim: DKIM
spf: SPF
dmarc: DMARC
arc: ARC
bimi: BIMI
headers: string
}
export interface DKIM {
headerFrom: string[]
envelopeFrom: string
results: DKIMResult[]
}
export interface DKIMResult {
signingDomain: string
selector: string
signature: string
algo: string
format: string
bodyHash: string
bodyHashExpecting: string
status: DKIMStatus
publicKey: string
info: string
}
export interface DKIMStatus {
result: string
comment?: boolean
header: DKIMHeader
policy?: Record<string, unknown>
aligned: string | boolean
}
export interface DKIMHeader {
i: string
s: string
a: string
b: string
}
export interface SPF {
domain: string
"client-ip": string
helo: string
"envelope-from": string
status: SPFStatus
header: string
info: string
}
export interface SPFStatus {
result: string
comment: string
smtp: SPFSMTP
}
export interface SPFSMTP {
mailfrom: string
helo: string
}
export interface DMARC {
status: DMARCStatus
domain: string
policy: string
p: string
sp: string
info: string
}
export interface DMARCStatus {
result: string
comment: string
header: DMARCHeader
}
export interface DMARCHeader {
from: string
}
export interface ARC {
status: ARCStatus
i: number
signature: ARCSignature
authenticationResults: ARCResults
info: string
authResults: string
}
export interface ARCStatus {
result: string
comment: string | boolean
}
export interface ARCSignature {
signingDomain: string
selector: string
signature: string
algo: string
format: string
bodyHash: string
bodyHashExpecting: string
status: ARCStatus // Reusing ARCStatus as it matches the structure
publicKey: string
}
export interface ARCResults {
[key: string]: ARCResult | ARCDKIM[] | SPF // key is the domain, e.g., "mx.google.com"
}
export interface ARCResult {
value: string
}
export interface ARCDKIM {
header: DKIMHeader
result: string
}
export interface BIMI {
status: BIMIStatus
location: string
info: string
}
export interface BIMIStatus {
header: BIMIHeader
result: string
}
export interface BIMIHeader {
selector: string
d: string
}
It appears that there is a breaking change in v4.6.0 @andris9
Specifically the DKIM results have invalid publicKey
values. You can see the result here has a part of the key that is present in the rr
but not in the resulting publicKey
:
v4.5.2...v4.6.0#diff-7f88797c7db38a6af7a3283e3af30f2cdd3c2489bd9c85a7a25b32ec2485f724R272-R292
Hey @andris9, thank you so much for your work on mailauth
. I'd frandkly have built this library myself if you did not do it first, thanks again for that.
I'm using mailauth
on a busy inbound mail server, successfully, however I'm seeing instances where SPF validation fails, with the following eg. output:
digitalocean.com does not designate permitted sender hosts
Checking digitalocean.com
manually, it appears that their SPF policy is valid. Note that I've raised the DNS resolution limit from 10 to 20 just to be safe, as they are well above the 10 resolutions limit.
Their policy is as such:
"v=spf1 include:spf.digitalocean.com include:_spf.google.com include:_spf.salesforce.com include:mg-spf.greenhouse.io include:helpscoutemail.com -all"
When digging _spf.salesforce.com
, it appears that they are using the SPF exists
method:
"v=spf1 exists:%{i}._spf.mta.salesforce.com -all"
I got the very same error for the siemens.com
domain name, which has a valid (though huge) SPF policy, and which is also using the exists
method:
"v=spf1 exists:%{i}.spf.siemens.com include:spf.protection.outlook.com include:amazonses.com include:all.spf.avature.net include:mail.zendesk.com -all"
It appears that SPF results containing the following pattern: exists:%{i}
lead to mailauth
thinking that there is no SPF policy at all on the domain.
hi @andris9 Thanks for your great libraries,
if a domain dns server does not return any TXT record does that mean we should always get temperror
?
in the result object i am getting status as temperror
, in comment dns error code ENODATA
DKIM relaxed body hash calculation should trim all whitespace and newlines from the end of the email. Instead it trims starting from the last line that has at least one whitespace byte
Header\r\n
\r\n
Trims correctly\r\n
\r\n
\r\n
\r\n
-->
Header\r\n
\r\n
Trims correctly\r\n
Header\r\n
\r\n
Does not trim correctly\r\n
\r\n
\t\r\n
\r\n
-->
Header\r\n
\r\n
Does not trim correctly\r\n
\r\n
mailauth generates invalid signatures and fails to validate valid ed25519 DKIM signatures. For now, this feature is not usable at all.
dkimpy reports a valid signature for the following email but mailauth reports dkim=none which is false:
Describe the bug
The RR field is not returned for SPF records where the default mechanism is missing
To Reproduce
mailauth spf -f bellcom.dk -i 1.2.3.4
{
"domain": "bellcom.dk",
"client-ip": "1.2.3.4",
"envelope-from": "[email protected]",
"status": {
"result": "neutral",
"comment": "STL-R7N4H9RQF6: 1.2.3.4 is neither permitted nor denied by domain of [email protected]",
"smtp": {
"mailfrom": "[email protected]"
}
},
"header": "Received-SPF: neutral (STL-R7N4H9RQF6: 1.2.3.4 is neither permitted nor denied by domain of [email protected]) client-ip=1.2.3.4;",
"info": "spf=neutral (STL-R7N4H9RQF6: 1.2.3.4 is neither permitted nor denied by domain of [email protected]) smtp.mailfrom=[email protected]"
}
However:
dig +short bellcom.dk txt
"v=spf1 include:_spf.bellcom.dk"
"google-site-verification: mrYNF5E8kEkNacSV-zrITF03H7FSh6-qTTki86F6k84"
Expected behavior
I think to remember the default mechanish is ?all (neutral), so while the record is sort of meaningless it is valid, and it would be nice if the RR field in the result was set.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.