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

Rust lettre库在Windows 10下无法发送邮件问题求助

Rust脚本Windows下无法发送邮件问题排查与修复

问题背景

开发的Rust脚本用于监控文件夹新文件,上传API后发送邮件。Linux下完全正常,Windows 10中API上传正常,但邮件无法发送。已配置防火墙允许连接,邮件凭证与Linux一致,使用lettre 0.10版本(官方示例Windows可正常运行)。

核心问题分析与修复方案

1. 错误处理不当导致线程崩溃

原代码中send_email_with_attachment函数在发送失败时使用panic!,而notify的监控回调运行在独立线程中,Windows下线程panic不会将错误信息输出到控制台,导致看似无反应,实际线程已崩溃。

修复代码(email_sender.rs):
将panic替换为错误返回:

// 替换原有的match块
match mailer.send(&email) {
    Ok(_) => {
        println!("Correo enviado exitosamente!");
        Ok(())
    },
    Err(e) => Err(Box::new(e) as Box<dyn Error>),
}

2. TLS配置差异导致SMTP连接失败

lettre 0.10的SmtpTransport::relay在Windows下可能默认TLS配置与Linux不一致,比如Gmail等服务商需要显式启用STARTTLS。建议改用SmtpTransport::builder手动配置TLS:

修改email_sender.rs中的SMTP构建部分:

// 替换原有的SmtpTransport::relay代码
let mailer = SmtpTransport::builder((&smtp_host, 587)) // 明确指定端口,比如Gmail是587
    .credentials(creds)
    .starttls_auto() // 自动启用STARTTLS
    .build()?;

3. 文件占用问题(Windows特有)

Windows下文件刚创建时可能被写入进程锁定,导致fs::read失败。可增加短暂延迟后重试,或检查文件是否可访问:

在upload_file函数中调用send_email前增加延迟(可选):

// 等待文件写入完成
std::thread::sleep(std::time::Duration::from_millis(500));
// 然后调用send_email_with_attachment

4. 环境变量加载路径问题

Windows下脚本运行的工作目录可能与预期不符,导致.env文件未正确加载。可显式指定.env文件路径:

修改main.rs中的dotenv加载:

// 替换原有的dotenv().ok();
dotenv::from_path(".env").ok(); // 或使用绝对路径,比如Path::new("C:/scripts/.env")

完整修改后的email_sender.rs示例

use std::path::Path;
use std::error::Error;
use lettre::message::{header, Message};
use lettre::message::{header::ContentType, MultiPart, SinglePart, Attachment};
use lettre::transport::smtp::authentication::Credentials;
use lettre::{SmtpTransport, Transport};
use std::{fs, env};

pub fn send_email_with_attachment(file_path: &Path, recipient_email: &str, file_name: &str) -> Result<(), Box<dyn Error>> {
    let file_name = file_name.to_string();
    let file_content = fs::read(file_path)?;

    // Use the correct ContentType for MiniSEED files
    let content_type = ContentType::parse("application/vnd.fdsn.mseed").unwrap();

    // Create a single part for the attachment
    let attachment = Attachment::new(file_name.clone()).body(file_content, content_type);

    let message = String::from("Envio MSeed");

    let email = Message::builder()
        .from("mi_email@gmail.com".parse()?)
        .to(recipient_email.parse()?)
        .subject("Envio Miniseed")
        .multipart(
            MultiPart::mixed()
                .singlepart(
                    SinglePart::builder()
                        .header(header::ContentType::TEXT_PLAIN)
                        .body(message), 
                )
                .singlepart(attachment),
        )?;

    let smtp_username = env::var("SMTP_USERNAME")?;
    let smtp_password = env::var("SMTP_PASSWORD")?;
    let smtp_host = env::var("SMTP_HOST")?;

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

    // Open a remote connection with explicit STARTTLS
    let mailer = SmtpTransport::builder((&smtp_host, 587))
        .credentials(creds)
        .starttls_auto()
        .build()?;

    // Send the email
    match mailer.send(&email) {
        Ok(_) => {
            println!("Correo enviado exitosamente!");
            Ok(())
        },
        Err(e) => Err(Box::new(e)),
    }
}

额外排查建议

  • 运行脚本时打开命令提示符(CMD)而非PowerShell,确保错误信息能正常输出
  • 测试时直接调用send_email_with_attachment函数,排除监控回调的线程影响
  • 检查SMTP服务器的日志,确认连接请求是否到达服务器

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 11:14:55