{"id":13637022,"url":"https://github.com/stalwartlabs/mail-auth","last_synced_at":"2025-04-04T17:07:49.934Z","repository":{"id":64061347,"uuid":"560888166","full_name":"stalwartlabs/mail-auth","owner":"stalwartlabs","description":"DKIM, ARC, SPF and DMARC library for Rust","archived":false,"fork":false,"pushed_at":"2024-08-11T18:05:36.000Z","size":618,"stargazers_count":83,"open_issues_count":2,"forks_count":15,"subscribers_count":6,"default_branch":"main","last_synced_at":"2024-10-13T11:09:15.586Z","etag":null,"topics":["arc","arf","dkim","dkim-signature","dkim-verifier","dmarc","email","mail","marf","rust","spf"],"latest_commit_sha":null,"homepage":"https://docs.rs/mail-auth/","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/stalwartlabs.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE-APACHE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"stalwartlabs","patreon":null,"open_collective":null,"ko_fi":"stalwartlabs","tidelift":null,"community_bridge":null,"liberapay":"stalwartlabs","issuehunt":null,"otechie":null,"lfx_crowdfunding":null,"custom":null}},"created_at":"2022-11-02T13:46:06.000Z","updated_at":"2024-09-07T05:05:12.000Z","dependencies_parsed_at":"2023-02-15T10:46:18.551Z","dependency_job_id":"ed29e6d0-7750-4531-bc99-ce43b9b35b09","html_url":"https://github.com/stalwartlabs/mail-auth","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stalwartlabs%2Fmail-auth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stalwartlabs%2Fmail-auth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stalwartlabs%2Fmail-auth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/stalwartlabs%2Fmail-auth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/stalwartlabs","download_url":"https://codeload.github.com/stalwartlabs/mail-auth/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247217183,"owners_count":20903009,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arc","arf","dkim","dkim-signature","dkim-verifier","dmarc","email","mail","marf","rust","spf"],"created_at":"2024-08-02T00:01:09.379Z","updated_at":"2025-04-04T17:07:49.911Z","avatar_url":"https://github.com/stalwartlabs.png","language":"Rust","funding_links":["https://github.com/sponsors/stalwartlabs","https://ko-fi.com/stalwartlabs","https://liberapay.com/stalwartlabs"],"categories":["Libraries"],"sub_categories":["Email"],"readme":"# mail-auth\n\n[![crates.io](https://img.shields.io/crates/v/mail-auth)](https://crates.io/crates/mail-auth)\n[![build](https://github.com/stalwartlabs/mail-auth/actions/workflows/rust.yml/badge.svg)](https://github.com/stalwartlabs/mail-auth/actions/workflows/rust.yml)\n[![docs.rs](https://img.shields.io/docsrs/mail-auth)](https://docs.rs/mail-auth)\n[![crates.io](https://img.shields.io/crates/l/mail-auth)](http://www.apache.org/licenses/LICENSE-2.0)\n\n_mail-auth_ is an e-mail authentication and reporting library written in Rust that supports the **DKIM**, **ARC**, **SPF** and **DMARC**\nprotocols. The library aims to be fast, safe and correct while supporting all major [message authentication and reporting RFCs](#conformed-rfcs). \n\nFeatures:\n\n- **DomainKeys Identified Mail (DKIM)**:\n  - ED25519-SHA256 (Edwards-Curve Digital Signature Algorithm), RSA-SHA256 and RSA-SHA1 signing and verification.\n  - DKIM Authorized Third-Party Signatures.\n  - DKIM failure reporting using the Abuse Reporting Format.\n  - Key-pair generation for both RSA and Ed25519 (enabled by the `generate` feature).\n- **Authenticated Received Chain (ARC)**:\n  - ED25519-SHA256 (Edwards-Curve Digital Signature Algorithm), RSA-SHA256 and RSA-SHA1 chain verification.\n  - ARC sealing.\n- **Sender Policy Framework (SPF)**:\n  - Policy evaluation.\n  - SPF failure reporting using the Abuse Reporting Format.\n- **Domain-based Message Authentication, Reporting, and Conformance (DMARC)**:\n  - Policy evaluation.\n  - DMARC aggregate report parsing and generation.\n- **Abuse Reporting Format (ARF)**:\n  - Abuse and Authentication failure reporting.\n  - Feedback report parsing and generation.\n- **SMTP TLS Reporting**:\n  - Report parsing and generation.\n\n## Usage examples\n\n### DKIM Signature Verification\n\n```rust\n    // Create an authenticator using Cloudflare DNS\n    let authenticator = MessageAuthenticator::new_cloudflare_tls().unwrap();\n\n    // Parse message\n    let authenticated_message = AuthenticatedMessage::parse(RFC5322_MESSAGE.as_bytes()).unwrap();\n\n    // Validate signature\n    let result = authenticator.verify_dkim(\u0026authenticated_message).await;\n\n    // Make sure all signatures passed verification\n    assert!(result.iter().all(|s| s.result() == \u0026DkimResult::Pass));\n```\n\n### DKIM Signing\n\n```rust\n    // Sign an e-mail message using RSA-SHA256\n    let pk_rsa =  RsaKey::\u003cSha256\u003e::from_pkcs1_pem(RSA_PRIVATE_KEY).unwrap();\n    let signature_rsa = DkimSigner::from_key(pk_rsa)\n        .domain(\"example.com\")\n        .selector(\"default\")\n        .headers([\"From\", \"To\", \"Subject\"])\n        .sign(RFC5322_MESSAGE.as_bytes())\n        .unwrap();\n\n    // Sign an e-mail message using ED25519-SHA256\n    let pk_ed = Ed25519Key::from_bytes(\n        \u0026base64_decode(ED25519_PUBLIC_KEY.as_bytes()).unwrap(),\n        \u0026base64_decode(ED25519_PRIVATE_KEY.as_bytes()).unwrap(),\n    )\n    .unwrap();\n    let signature_ed = DkimSigner::from_key(pk_ed)\n        .domain(\"example.com\")\n        .selector(\"default-ed\")\n        .headers([\"From\", \"To\", \"Subject\"])\n        .sign(RFC5322_MESSAGE.as_bytes())\n        .unwrap();    \n\n    // Print the message including both signatures to stdout\n    println!(\n        \"{}{}{}\",\n        signature_rsa.to_header(),\n        signature_ed.to_header(),\n        RFC5322_MESSAGE\n    );\n```\n\n### ARC Chain Verification\n\n```rust\n    // Create an authenticator using Cloudflare DNS\n    let authenticator = MessageAuthenticator::new_cloudflare_tls().unwrap();\n\n    // Parse message\n    let authenticated_message = AuthenticatedMessage::parse(RFC5322_MESSAGE.as_bytes()).unwrap();\n\n    // Validate ARC chain\n    let result = authenticator.verify_arc(\u0026authenticated_message).await;\n\n    // Make sure ARC passed verification\n    assert_eq!(result.result(), \u0026DkimResult::Pass);\n```\n\n### ARC Chain Sealing\n\n```rust\n    // Create an authenticator using Cloudflare DNS\n    let authenticator = MessageAuthenticator::new_cloudflare_tls().unwrap();\n\n    // Parse message to be sealed\n    let authenticated_message = AuthenticatedMessage::parse(RFC5322_MESSAGE.as_bytes()).unwrap();\n\n    // Verify ARC and DKIM signatures\n    let arc_result = authenticator.verify_arc(\u0026authenticated_message).await;\n    let dkim_result = authenticator.verify_dkim(\u0026authenticated_message).await;\n\n    // Build Authenticated-Results header\n    let auth_results = AuthenticationResults::new(\"mx.mydomain.org\")\n        .with_dkim_result(\u0026dkim_result, \"sender@example.org\")\n        .with_arc_result(\u0026arc_result, \"127.0.0.1\".parse().unwrap());\n\n    // Seal message\n    if arc_result.can_be_sealed() {\n        // Seal the e-mail message using RSA-SHA256\n        let pk_rsa = RsaKey::\u003cSha256\u003e::from_pkcs1_pem(RSA_PRIVATE_KEY).unwrap();\n        let arc_set = ArcSealer::from_key(pk_rsa)\n            .domain(\"example.org\")\n            .selector(\"default\")\n            .headers([\"From\", \"To\", \"Subject\", \"DKIM-Signature\"])\n            .seal(\u0026authenticated_message, \u0026auth_results, \u0026arc_result)\n            .unwrap();\n\n        // Print the sealed message to stdout\n        println!(\"{}{}\", arc_set.to_header(), RFC5322_MESSAGE)\n    } else {\n        eprintln!(\"The message could not be sealed, probably an ARC chain with cv=fail was found.\")\n    }\n```\n\n### SPF Policy Evaluation\n\n```rust\n    // Create an authenticator using Cloudflare DNS\n    let authenticator = MessageAuthenticator::new_cloudflare_tls().unwrap();\n\n    // Verify HELO identity\n    let result = authenticator\n        .verify_spf(SpfParameters::verify_ehlo(\n            \"127.0.0.1\".parse().unwrap(),\n            \"gmail.com\",\n            \"my-local-domain.org\",\n        ))\n        .await;\n    assert_eq!(result.result(), SpfResult::Fail);\n\n    // Verify MAIL-FROM identity\n    let result = authenticator\n        .verify_spf(SpfParameters::verify_mail_from(\n            \"::1\".parse().unwrap(),\n            \"gmail.com\",\n            \"my-local-domain.org\",\n            \"sender@gmail.com\",\n        ))\n        .await;\n    assert_eq!(result.result(), SpfResult::Fail);\n```\n\n### DMARC Policy Evaluation\n\n```rust\n    // Create an authenticator using Cloudflare DNS\n    let authenticator = MessageAuthenticator::new_cloudflare_tls().unwrap();\n\n    // Verify DKIM signatures\n    let authenticated_message = AuthenticatedMessage::parse(RFC5322_MESSAGE.as_bytes()).unwrap();\n    let dkim_result = authenticator.verify_dkim(\u0026authenticated_message).await;\n\n    // Verify SPF MAIL-FROM identity\n    let spf_result = authenticator\n        .verify_spf(SpfParameters::verify_mail_from(\n            \"::1\".parse().unwrap(),\n            \"example.org\",\n            \"my-host-domain.org\",\n            \"sender@example.org\",\n        ))\n        .await;\n\n    // Verify DMARC\n    let dmarc_result = authenticator\n        .verify_dmarc(\n            DmarcParameters::new(\n                \u0026authenticated_message,\n                \u0026dkim_result,\n                \"example.org\",\n                \u0026spf_result,\n            )\n            .with_domain_suffix_fn(|domain| psl::domain_str(domain).unwrap_or(domain)),\n        )\n        .await;\n    assert_eq!(dmarc_result.dkim_result(), \u0026DmarcResult::Pass);\n    assert_eq!(dmarc_result.spf_result(), \u0026DmarcResult::Pass);\n```\n\nMore examples available under the [examples](examples) directory.\n\n## Testing \u0026 Fuzzing\n\nTo run the testsuite:\n\n```bash\n $ cargo test\n```\n\nTo fuzz the library with `cargo-fuzz`:\n\n```bash\n $ cargo +nightly fuzz run mail_auth\n```\n\n## Conformed RFCs\n\n### DKIM\n\n- [RFC 6376 - DomainKeys Identified Mail (DKIM) Signatures](https://datatracker.ietf.org/doc/html/rfc6376)\n- [RFC 6541 - DomainKeys Identified Mail (DKIM) Authorized Third-Party Signatures](https://datatracker.ietf.org/doc/html/rfc6541)\n- [RFC 6651 - Extensions to DomainKeys Identified Mail (DKIM) for Failure Reporting](https://datatracker.ietf.org/doc/html/rfc6651)\n- [RFC 8032 - Edwards-Curve Digital Signature Algorithm (EdDSA)](https://datatracker.ietf.org/doc/html/rfc8032)\n- [RFC 4686 - Analysis of Threats Motivating DomainKeys Identified Mail (DKIM)](https://datatracker.ietf.org/doc/html/rfc4686)\n- [RFC 5016 - Requirements for a DomainKeys Identified Mail (DKIM) Signing Practices Protocol](https://datatracker.ietf.org/doc/html/rfc5016)\n- [RFC 5585 - DomainKeys Identified Mail (DKIM) Service Overview](https://datatracker.ietf.org/doc/html/rfc5585)\n- [RFC 5672 - DomainKeys Identified Mail (DKIM) Signatures -- Update](https://datatracker.ietf.org/doc/html/rfc5672)\n- [RFC 5863 - DomainKeys Identified Mail (DKIM) Development, Deployment, and Operations](https://datatracker.ietf.org/doc/html/rfc5863)\n- [RFC 6377 - DomainKeys Identified Mail (DKIM) and Mailing Lists](https://datatracker.ietf.org/doc/html/rfc6377)\n\n### SPF\n- [RFC 7208 - Sender Policy Framework (SPF)](https://datatracker.ietf.org/doc/html/rfc7208)\n- [RFC 6652 - Sender Policy Framework (SPF) Authentication Failure Reporting Using the Abuse Reporting Format](https://datatracker.ietf.org/doc/html/rfc6652)\n\n### DMARC\n- [RFC 7489 - Domain-based Message Authentication, Reporting, and Conformance (DMARC)](https://datatracker.ietf.org/doc/html/rfc7489)\n- [RFC 8617 - The Authenticated Received Chain (ARC) Protocol](https://datatracker.ietf.org/doc/html/rfc8617)\n- [RFC 8601 - Message Header Field for Indicating Message Authentication Status](https://datatracker.ietf.org/doc/html/rfc8601)\n- [RFC 8616 - Email Authentication for Internationalized Mail](https://datatracker.ietf.org/doc/html/rfc8616)\n- [RFC 7960 - Interoperability Issues between Domain-based Message Authentication, Reporting, and Conformance (DMARC) and Indirect Email Flows](https://datatracker.ietf.org/doc/html/rfc7960)\n\n### ARF\n- [RFC 5965 - An Extensible Format for Email Feedback Reports](https://datatracker.ietf.org/doc/html/rfc5965)\n- [RFC 6430 - Email Feedback Report Type Value: not-spam](https://datatracker.ietf.org/doc/html/rfc6430)\n- [RFC 6590 - Redaction of Potentially Sensitive Data from Mail Abuse Reports](https://datatracker.ietf.org/doc/html/rfc6590)\n- [RFC 6591 - Authentication Failure Reporting Using the Abuse Reporting Format](https://datatracker.ietf.org/doc/html/rfc6591)\n- [RFC 6650 - Creation and Use of Email Feedback Reports: An Applicability Statement for the Abuse Reporting Format (ARF)](https://datatracker.ietf.org/doc/html/rfc6650)\n\n### SMTP TLS Reporting\n- [RFC 8460 - SMTP TLS Reporting](https://datatracker.ietf.org/doc/html/rfc8460)\n\n## License\n\nLicensed under either of\n\n * Apache License, Version 2.0 ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)\n * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n\n## Copyright\n\nCopyright (C) 2020, Stalwart Labs LLC\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstalwartlabs%2Fmail-auth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fstalwartlabs%2Fmail-auth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fstalwartlabs%2Fmail-auth/lists"}