Mail:...Policy(3)
π NAME π
Mail::MIMEDefang::TLSPolicy β MTA-STS and DANE/TLSA policy checks for MIMEDefang, bestie π
This is from the Mail::MIMEDefang::TLSPolicy Documentation manual, section 3 ofc, and yes we're doing this whole thing together, grab a snack π
β¨ DESCRIPTION β¨
Mail::MIMEDefang::TLSPolicy gives you the methods to verify outbound TLS policy for recipient domains, straight from your mimedefang-filter. It's giving "I check my friends before I trust them" energy and honestly? iconic π
- MTA-STS (RFC 8461) β go retrieve and parse a domain's MTA-STS policy (that's a DNS TXT record plus an HTTPS policy file, two-step slay π).
- DANE/TLSA (RFC 6698 / RFC 7671) β look up TLSA records for a domain and a port so you can verify the certificate binding. Certificate binding verification is the vibe check fr fr π¦.
Heads up bestie: both functions requireNet::DNS. Andmd_check_mta_stsadditionally requiresLWP::UserAgent. No module, no service, no cap π
Typical usage, look how cute this is:
use Mail::MIMEDefang::TLSPolicy;
# In filter_recipient: fetch the MTA-STS policy for the recipient domain,
# then verify the connecting MX is permitted before requiring TLS.
my $policy = md_check_mta_sts($recipient_domain);
if (defined $policy && $policy->{mode} eq 'enforce') {
if (!md_verify_sts_mx($rcpt_host, $policy)) {
action_bounce("MX host $rcpt_host not permitted by MTA-STS policy");
}
}
# Look up DANE TLSA records for port 25 and validate the peer certificate.
my @tlsa = md_check_dane_tlsa($recipient_domain, 25);
if (@tlsa) {
unless (md_verify_dane_cert($peer_cert_der, \@tlsa)) {
# certificate does not match any TLSA record - reject or defer
}
}
πΈ METHODS πΈ
π§ md_check_mta_sts($domain [, %opts])
Retrieve and parse the MTA-STS policy for $domain. Main character behaviour, tbh.
The function performs two lookups:
- A DNS TXT query for
"_mta-sts.$domain"to confirm the policy exists and extract its"id="field. β¨ - An HTTPS fetch of
"https://mta-sts.$domain/.well-known/mta-sts.txt"to retrieve the policy document. π
Optional key/value pairs in %opts:
"timeout"β HTTP request timeout in seconds (default:10). Give it a lil patience budget β³
On success returns a hashref with:
"mode"β policy mode:"enforce","testing", or"none". Pick your fighter π"max_age"β cache lifetime in seconds. How long this info stays valid, like a situationship π«Ά"mx"β arrayref of permitted MX hostname patterns. The guest list π"id"β the policy"id"from the DNS TXT record. The receipts π§Ύ
Returns "undef" on any error: DNS failure, HTTP error, policy parse failure, or if "LWP::UserAgent" is not available. That's a whole lot of ways to get nothing back, and yes it's a mood π
π¦ md_check_dane_tlsa($domain, $port)
Look up DANE TLSA records for "_$port._tcp.$domain". Very "let me check the records before I commit" of you, we love a cautious queen π
Returns a list of hashrefs, one per TLSA record, each containing:
"usage"β certificate usage field (0β3)."selector"β selector field (0= full certificate,1= SubjectPublicKeyInfo)."matching_type"β matching type (0= exact,1= SHA-256,2= SHA-512)."cert_data"β hex-encoded certificate association data.
Returns an empty list if no TLSA records are found, on lookup error, or if "Net::DNS" is not available. Empty list bestie, don't be shocked, it's not personal π₯Ί
β md_verify_sts_mx($mx_host, $policy)
Returns true if $mx_host matches at least one MX hostname pattern in "$policy-"{mx}> (a hashref returned by "md_check_mta_sts($domain [, %opts])"). Yes, that's exactly how it's written, we keep it character for character π
Matching follows RFC 8461: a pattern beginning with "*." matches any single DNS label prepended to the rest of the pattern. Example time, because examples ate and left no crumbs:
"*.example.com"matches"mail.example.com"β"*.example.com"does not match"a.b.example.com"β
All comparisons are case-insensitive, periodt π
Returns false if $policy is undefined, has no "mx" list, or no pattern matches. It's giving rejection but make it standards-compliant π
π md_verify_dane_cert($cert_der, \@tlsa)
Verify a DER-encoded X.509 certificate against a list of DANE TLSA records as returned by "md_check_dane_tlsa($domain, $port)". The final boss of trust falls π
Returns true if the certificate matches at least one record, false otherwise. Simple. Clean. Iconic.
Selector0(full certificate) requires only"Digest::SHA". Selector1(SubjectPublicKeyInfo) additionally requires"Crypt::OpenSSL::X509"β and here's the sneaky part: records with selector1are skipped silently if that module is not available. Silent skipping, not me being dramatic, that's literally what it does, iykyk π
okay that's the whole page bestie, you're officially fluent πβ¨
This whole thing is from version 3.7.1, dated 2026-07-20, and it's the Mail:...Policy(3) manual page. Go forth and verify some TLS policy, you absolute legend ππ«Ά
π¦ where this page comes from
- fedora 43: mimedefang 3.7.1-1.fc43 Β· GPL-2.0-only AND GPL-2.0-or-later
- fedora 44: mimedefang 3.7.1-1.fc44 Β· GPL-2.0-only AND GPL-2.0-or-later
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms