Rust邮件认证库mail-auth的使用,支持SMTP、DKIM和SPF等邮件安全协议验证
Rust邮件认证库mail-auth的使用,支持SMTP、DKIM和SPF等邮件安全协议验证
mail-auth是一个用Rust编写的电子邮件认证和报告库,支持DKIM、ARC、SPF和DMARC协议。该库旨在快速、安全和正确,同时支持所有主要的消息认证和报告RFC。
功能特性
-
DomainKeys Identified Mail (DKIM):
- ED25519-SHA256 (Edwards-Curve Digital Signature Algorithm), RSA-SHA256和RSA-SHA1签名和验证
- DKIM授权第三方签名
- 使用Abuse Reporting Format进行DKIM失败报告
- 为RSA和Ed25519生成密钥对(通过
generate
功能启用)
-
Authenticated Received Chain (ARC):
- ED25519-SHA256 (Edwards-Curve Digital Signature Algorithm), RSA-SHA256和RSA-SHA1链验证
- ARC密封
-
Sender Policy Framework (SPF):
- 策略评估
- 使用Abuse Reporting Format进行SPF失败报告
-
Domain-based Message Authentication, Reporting and Conformance (DMARC):
- 策略评估
- DMARC聚合报告解析和生成
-
Abuse Reporting Format (ARF):
- 滥用和认证失败报告
- 反馈报告解析和生成
-
SMTP TLS Reporting:
- 报告解析和生成
使用示例
DKIM签名验证
// 创建一个使用Cloudflare DNS的认证器
let authenticator = MessageAuthenticator::new_cloudflare_tls().unwrap();
// 解析消息
let authenticated_message = AuthenticatedMessage::parse(RFC5322_MESSAGE.as_bytes()).unwrap();
// 验证签名
let result = authenticator.verify_dkim(&authenticated_message).await;
// 确保所有签名都通过了验证
assert!(result.iter().all(|s| s.result() == &DkimResult::Pass));
DKIM签名
// 使用RSA-SHA256签名电子邮件消息
let pk_rsa = RsaKey::<Sha256>::from_pkcs1_pem(RSA_PRIVATE_KEY).unwrap();
let signature_rsa = DkimSigner::from_key(pk_rsa)
.domain("example.com")
.selector("default")
.headers(["From", "To", "Subject"])
.sign(RFC5322_MESSAGE.as_bytes())
.unwrap();
// 使用ED25519-SHA256签名电子邮件消息
let pk_ed = Ed25519Key::from_bytes(
&base64_decode(ED25519_PUBLIC_KEY.as_bytes()).unwrap(),
&base64_decode(ED25519_PRIVATE_KEY.as_bytes()).unwrap(),
)
.unwrap();
let signature_ed = DkimSigner::from_key(pk_ed)
.domain("example.com")
.selector("default-ed")
.headers(["From", "To", "Subject"])
.sign(RFC5322_MESSAGE.as_bytes())
.unwrap();
// 打印包含两个签名的消息到stdout
println!(
"{}{}{}",
signature_rsa.to_header(),
signature_ed.to_header(),
RFC5322_MESSAGE
);
ARC链验证
// 创建一个使用Cloudflare DNS的认证器
let authenticator = MessageAuthenticator::new_cloudflare_tls().unwrap();
// 解析消息
let authenticated_message = AuthenticatedMessage::parse(RFC5322_MERENCE.as_bytes()).unwrap();
// 验证ARC链
let result = authenticator.verify_arc(&authenticated_message).await;
// 确保ARC通过了验证
assert_eq!(result.result(), &DkimResult::Pass);
SPF策略评估
// 创建一个使用Cloudflare DNS的认证器
let authenticator = MessageAuthenticator::new_cloudflare_tls().unwrap();
// 验证HELO身份
let result = authenticator
.verify_spf(SpfParameters::verify_ehlo(
"127.0.0.1".parse().unwrap(),
"gmail.com",
"my-local-domain.org",
))
.await;
assert_eq!(result.result(), SpfResult::Fail);
// 验证MAIL-FROM身份
let result = authenticator
.verify_spf(SpfParameters::verify_mail_from(
"::1".parse().unwrap(),
"gmail.com",
"my-local-domain.org",
"sender@gmail.com",
))
.await;
assert_eq!(result.result(), SpfResult::Fail);
完整示例代码
以下是一个完整的示例,展示了如何使用mail-auth库进行DKIM签名和验证:
use mail_auth::{
AuthenticatedMessage, DkimResult, DkimSigner, MessageAuthenticator,
dkim::RsaKey,
};
use sha2::Sha256;
use std::error::Error;
#[tokio::main]
async fn main() -> Result<(), Box<dyn Error>> {
// 示例邮件内容
const RFC5322_MESSAGE: &str = "From: sender@example.com\r\n\
To: recipient@example.com\r\n\
Subject: Test message\r\n\
\r\n\
This is a test message.";
// 创建签名器
let private_key = "-----BEGIN RSA PRIVATE KEY-----\n..."; // 替换为实际的RSA私钥
let pk_rsa = RsaKey::<Sha256>::from_pkcs1_pem(private_key)?;
// 签名邮件
let signature = DkimSigner::from_key(pk_rsa)
.domain("example.com")
.selector("default")
.headers(["From", "To", "Subject"])
.sign(RFC5322_MESSAGE.as_bytes())?;
// 创建带签名的完整邮件
let signed_message = format!("{}{}", signature.to_header(), RFC5322_MESSAGE);
// 创建验证器
let authenticator = MessageAuthenticator::new_cloudflare_tls()?;
// 解析消息
let authenticated_message = AuthenticatedMessage::parse(signed_message.as_bytes())?;
// 验证签名
let result = authenticator.verify_dkim(&authenticated_message).await;
// 检查验证结果
assert!(result.iter().all(|s| s.result() == &DkimResult::Pass));
println!("DKIM验证成功!");
Ok(())
}
测试和模糊测试
运行测试套件:
$ cargo test
使用cargo-fuzz
进行模糊测试:
$ cargo +nightly fuzz run mail_auth
许可证
可以选择以下任一许可证:
- Apache License, Version 2.0
- MIT license
版权
版权所有 © 2020, Stalwart Labs LLC
1 回复
Rust邮件认证库mail-auth使用指南
mail-auth
是一个Rust库,用于处理邮件认证相关的协议验证,包括SMTP、DKIM和SPF等邮件安全协议。它可以帮助开发者构建安全的邮件发送和接收系统。
主要功能
- DKIM (DomainKeys Identified Mail) 签名和验证
- SPF (Sender Policy Framework) 验证
- SMTP协议相关认证
- 邮件头验证
安装
在Cargo.toml
中添加依赖:
[dependencies]
mail-auth = "0.2"
完整示例代码
1. DKIM签名完整示例
use mail_auth::{Authenticator, DkimSigner, common::headers::HeaderWriter};
use std::fs;
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 读取私钥文件
let private_key = fs::read_to_string("private_key.pem")?;
// 创建DKIM签名器
let signer = DkimSigner::from_pem(&private_key)
.expect("Failed to parse private key")
.domain("example.com")
.selector("default")
.headers(&["From", "To", "Subject", "Date"]);
// 构建邮件头
let date = chrono::Local::now().to_rfc2822();
let mut headers = Vec::new();
headers.push(("From", "sender@example.com"));
headers.push(("To", "recipient@example.com"));
headers.push(("Subject", "Test email with DKIM"));
headers.push(("Date", &date));
// 邮件正文
let body = "Hello,\n\nThis is a test email with DKIM signature.\n\nBest regards,\nSender";
// 签名邮件
let signature = signer.sign(&headers, body)?;
// 输出带签名的完整邮件
println!("From: sender@example.com");
println!("To: recipient@example.com");
println!("Subject: Test email with DKIM");
println!("Date: {}", date);
println!("DKIM-Signature: {}", signature);
println!("\n{}", body);
Ok(())
}
2. DKIM验证完整示例
use mail_auth::{Authenticator, DkimVerifier};
fn main() -> Result<(), Box<dyn std::error::Error>> {
// 示例邮件内容(实际应用中从文件或网络读取)
let email = r#"From: sender@example.com
To: recipient@example.com
Subject: Test email
DKIM-Signature: v=1; a=rsa-sha256; d=example.com; s=default;
c=relaxed/relaxed; q=dns/txt; t=1234567890; h=from:to:subject;
bh=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOP;
b=ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890ABCD
Hello, this is a test email!"#;
// 验证DKIM签名
let verifier = DkimVerifier::from_email(email)?;
let result = verifier.verify()?;
if result.is_passed() {
println!("✅ DKIM验证成功");
println!("签名域名: {}", result.domain().unwrap_or("未知"));
} else {
println!("❌ DKIM验证失败: {:?}", result.error());
}
Ok(())
}
3. SPF验证完整示例
use mail_auth::spf::SpfVerifier;
use std::net::{IpAddr, Ipv4Addr};
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 客户端IP地址
let ip = IpAddr::V4(Ipv4Addr::new(192, 0, 2, 1));
// 发件人地址
let sender = "sender@example.com";
// HELO/EHLO域名
let helo_domain = "mail.example.com";
// 执行SPF验证
let result = SpfVerifier::new(ip, sender, helo_domain)
.verify()
.await?;
match result.result() {
mail_auth::spf::SpfResult::Pass => println!("✅ SPF验证通过"),
mail_auth::spf::SpfResult::Fail => println!("❌ SPF验证失败"),
mail_auth::spf::SpfResult::SoftFail => println!("⚠️ SPF软失败"),
mail_auth::spf::SpfResult::Neutral => println!("➖ SPF中立"),
mail_auth::spf::SpfResult::None => println!("❓ 无SPF记录"),
mail_auth::spf::SpfResult::TempError => println!("⚠️ 临时错误"),
mail_auth::spf::SpfResult::PermError => println!("❌ 永久错误"),
}
println!("验证结果详情: {:?}", result);
Ok(())
}
4. 综合验证完整示例
use mail_auth::{verify::verify_email, Authenticator};
use std::net::{IpAddr, Ipv4Addr};
use tokio::fs;
#[tokio::main]
async fn main() -> Result<(), Box<dyn std::error::Error>> {
// 读取测试邮件文件
let email = fs::read_to_string("test_email.eml").await?;
// 客户端IP地址
let client_ip = IpAddr::V4(Ipv4Addr::new(192, 0, 2, 100));
// 综合验证邮件
let result = verify_email(&email, client_ip).await?;
println!("=== 邮件验证结果 ===");
println!("DKIM: {:?}", result.dkim());
println!("SPF: {:?}", result.spf());
if result.is_passed() {
println!("✅ 邮件通过所有验证");
} else {
println!("❌ 邮件验证失败");
}
Ok(())
}
项目结构
mail_auth_demo/
├── Cargo.toml
├── src/
│ ├── main.rs # 主程序入口
│ ├── dkim.rs # DKIM相关功能
│ ├── spf.rs # SPF相关功能
│ └── verification.rs # 综合验证功能
├── private_key.pem # DKIM私钥
├── test_email.eml # 测试用邮件
└── README.md # 项目说明
注意事项
- DKIM签名需要有效的RSA私钥,格式为PEM
- SPF验证需要正确的DNS记录配置
- 生产环境建议使用异步API以提高性能
- 所有验证操作都应包含错误处理
- 邮件内容应符合RFC标准格式