使用 Rust lettre 库从 Exchange SMTP 获取 "Client was not authenticated to send anonymous mail during MAIL FROM" 错误

Getting "Client was not authenticated to send anonymous mail during MAIL FROM" error from Exchange SMTP using Rust lettre library

我正在编写一个 Rust 应用程序,它将通过启用了 SMTP 功能的 Exchange 服务器发送电子邮件。根据Microsoft's webpage,需要的设置是:

网络邮件服务的 POP/IMAP 设置证实了这些。

这是我的代码(经过一些审查):

extern crate lettre;

use self::lettre::email::EmailBuilder;
use self::lettre::transport::smtp::{SecurityLevel, SmtpTransportBuilder, SUBMISSION_PORT};
use self::lettre::transport::smtp::authentication::Mechanism;
use self::lettre::transport::EmailTransport;

pub fn send_mail() {
    let email = EmailBuilder::new()
        .from("my email")
        .to("destination email")
        .body("testing")
        .subject("testing")
        .build()
        .unwrap();

    // Connect to SMTP server
    let mut transport = SmtpTransportBuilder::new(("smtp.office365.com", SUBMISSION_PORT))
        .expect("Failed to create email transport")
        .encrypt()
        .smtp_utf8(true)
        .credentials("my email", "my password")
        .authentication_mechanism(Mechanism::Login)
        .build();
    println!("Mail transport built");

    println!("{:?}", transport.send(email.clone()));
}

当我编译 运行 代码时,它给我这个错误:

Err(Permanent(Response { code: Code { severity: PermanentNegativeCompletion, category: Unspecified3, detail: 0 }, message: ["5.7.57 SMTP; Client was not authenticated to send anonymous mail during MAIL FROM [SYXPR01CA0106.ausprd01.prod.outlook.com]"] }))

为什么会这样?

我研究中最接近的问题是 GitHub 与不支持 Login 身份验证机制(Office 365 使用)的字母库相关的问题;但是,代码库已更新以支持 Login,并且我直接从 GitHub 使用 master 分支,因此理论上我的应用程序应该支持 Login 机制。

编辑:忘记提及我尝试向服务器发送 EHLO,但它返回了一个 (Client:(Connection closed)) 错误。

我使用 telnet 和 openssl 尝试直接连接到我的 SMTP 服务器,我发现 AUTH LOGIN 需要 3 个命令;一个发送 AUTH LOGIN 代码,一个发送用户名,另一个发送密码。我发现 lettre 库将其所有 AUTH 命令实现为单个命令,因此这不适用于服务器。我下载了该库的源代码,更改了发送函数以执行三个单独的命令,重新编译了我的代码,一切正常:)

我对字母代码的补充:

if (accepted_mechanisms[0] == Mechanism::Login) &&
            (accepted_mechanisms.capacity() == 1) {
            try_smtp!(self.client.command("AUTH LOGIN"), self);
            try_smtp!(self.client.command(base64::encode_config(
                                            &username.as_bytes(),
                                            base64::STANDARD).as_str()), self);
            try_smtp!(self.client.command(base64::encode_config(
                                                        &password.as_bytes(),
                                                        base64::STANDARD).as_str()), self);