You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Rust Lettre库发邮件遇STARTTLS命令未识别及证书验证问题

问题描述

场景

用Rust的lettre库后端发送邮件到Postfix服务器,Python的smtplib脚本或邮件客户端都能正常发送,但lettre脚本报两类错误。

错误1:使用域名连接时

lettre报错内容:

lettre::transport::smtp::Error { kind: Permanent(Code { severity: PermanentNegativeCompletion, category: Syntax, detail: Zero }), source: "5.5.2 Error: command not recognized" }

Postfix服务器日志:

improper command pipelining after EHLO from x.x.x.x: QUIT\r\n

错误2:使用Postfix容器内网IP连接时

Some(lettre::transport::smtp::Error { kind: Connection, source: Failure(Ssl(Error { code: ErrorCode(1), cause: Some(Ssl(ErrorStack([Error { code: 337047686, library: "SSL routines", function: "tls_process_server_certificate", reason: "certificate verify failed", file: "ssl/statem/statem_clnt.c", line: 1919 }]))) }, X509VerifyResult { code: 64, error: "IP address mismatch" })) })

实现代码

use lettre::{
    message::header::ContentType, transport::smtp::authentication::Credentials, Message,
    SmtpTransport, Transport,
};

fn main() {
    let email = Message::builder()
        .from("nobody@domain.tld".parse().unwrap())
        .to("mailer@domain.tld".parse().unwrap())
        .subject("Test mailer")
        .header(ContentType::TEXT_PLAIN)
        .body(String::from("Hello world !"))
        .unwrap();

    let creds = Credentials::new("smtp_username".to_owned(), "smtp_password".to_owned());

    let mailer = SmtpTransport::starttls_relay("mydomain.tld")
        .unwrap()
        .credentials(creds)
        .build();

    // Send the email
    match mailer.send(&email) {
        Ok(_) => println!("Email sent successfully!"),
        Err(e) => panic!("Could not send email: {e:?}"),
    }
}
解决方案

解决域名连接的命令管道错误

问题根源是lettre默认启用SMTP命令管道,但你的Postfix服务器不兼容或配置了严格的管道检查。只需禁用管道功能:

修改SmtpTransport构建代码,添加.disable_pipelining():

let mailer = SmtpTransport::starttls_relay("mydomain.tld")
    .unwrap()
    .credentials(creds)
    .disable_pipelining() // 新增该行禁用管道
    .build();

禁用后lettre会逐个发送SMTP命令,避免触发Postfix的管道规则错误。

解决内网IP连接的SSL证书验证错误

错误原因是SSL证书绑定的是域名,用IP访问时证书主题与IP不匹配,导致验证失败。有三种解决方式:

  • 优先方案:用域名连接:内网环境配置DNS解析,让域名指向Postfix容器IP,保持访问地址与证书一致,无需修改代码。
  • 安全长期方案:更新证书:给Postfix的SSL证书添加内网IP作为SAN(备用名称),这样IP访问时证书验证也能通过。
  • 临时应急方案:跳过证书验证(不推荐生产):必须用IP连接时,添加.danger_accept_invalid_certs(true)跳过验证,但会引入安全风险:
let mailer = SmtpTransport::starttls_relay("192.168.x.x") // 替换为你的内网IP
    .unwrap()
    .credentials(creds)
    .disable_pipelining()
    .danger_accept_invalid_certs(true) // 新增该行跳过验证
    .build();

内容的提问来源于stack exchange,提问作者Yok0

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 08:50:12