Perl:使用 Office 365 发送邮件

标签 perl ssl openssl smtp tls1.3

我正在尝试使用 perl 通过 server office 365 发送邮件

操作成功 10 次中的 8 次(即在 20% 的情况下随机失败)。

use Net::SMTPS;
my $mailer = Net::SMTPS->new("smtp.office365.com", 
     Port => "587", 
     doSSL => "starttls", 
     SSL_version => "TLSv1", 
     Debug => 4
);
...

$mailer 返回 undef ;

以下是日志:

Net::SMTPS>>> Net::SMTPS(0.10)
Net::SMTPS>>>   IO::Socket::IP(0.41)
Net::SMTPS>>>     IO::Socket(1.48)
Net::SMTPS>>>       IO::Handle(1.48)
Net::SMTPS>>>         Exporter(5.73)
Net::SMTPS>>>   Net::SMTP(3.13)
Net::SMTPS>>>     Net::Cmd(3.13)
Net::SMTPS=GLOB(0x30816b0)<<< 220 DU2PR04CA0355.outlook.office365.com Microsoft ESMTP MAIL Service ready at Fri, 22 Oct 2021 09:15:28 +0000
Net::SMTPS=GLOB(0x30816b0)>>> EHLO localhost.localdomain
Net::SMTPS=GLOB(0x30816b0)<<< 250-DU2PR04CA0355.outlook.office365.com Hello [54.77.44.87]
Net::SMTPS=GLOB(0x30816b0)<<< 250-SIZE 157286400
Net::SMTPS=GLOB(0x30816b0)<<< 250-PIPELINING
Net::SMTPS=GLOB(0x30816b0)<<< 250-DSN
Net::SMTPS=GLOB(0x30816b0)<<< 250-ENHANCEDSTATUSCODES
Net::SMTPS=GLOB(0x30816b0)<<< 250-STARTTLS
Net::SMTPS=GLOB(0x30816b0)<<< 250-8BITMIME
Net::SMTPS=GLOB(0x30816b0)<<< 250-BINARYMIME
Net::SMTPS=GLOB(0x30816b0)<<< 250-CHUNKING
Net::SMTPS=GLOB(0x30816b0)<<< 250 SMTPUTF8
Net::SMTPS=GLOB(0x30816b0)>>> STARTTLS
Net::SMTPS=GLOB(0x30816b0)<<< 220 2.0.0 SMTP server ready
DEBUG: .../IO/Socket/SSL.pm:3010: new ctx 51201296
DEBUG: .../IO/Socket/SSL.pm:1620: start handshake
DEBUG: .../IO/Socket/SSL.pm:787: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:832: not using SNI because hostname is unknown
DEBUG: .../IO/Socket/SSL.pm:864: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:880: set socket to non-blocking to enforce timeout=120
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:907: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:917: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:937: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:894: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:897: done Net::SSLeay::connect -> 0
DEBUG: .../IO/Socket/SSL.pm:945: connection failed - connect returned 0
DEBUG: .../IO/Socket/SSL.pm:946: local error: SSL connect attempt failed because of handshake problems
DEBUG: .../IO/Socket/SSL.pm:2043: downgrading SSL only, not closing socket
DEBUG: .../IO/Socket/SSL.pm:3059: free ctx 51201296 open=51201296
DEBUG: .../IO/Socket/SSL.pm:3063: free ctx 51201296 callback
DEBUG: .../IO/Socket/SSL.pm:3070: OK free ctx 51201296

感谢您的帮助

最佳答案

my $mailer = Net::SMTPS->new("smtp.office365.com", 
     ... 
     SSL_version => "TLSv1", 

由于某些未知原因,您尝试使用 SSL_version => 'TLSv1' 强制实现 TLS 1.0。但是 smtp.office365.com 后面的一些服务器只支持 TLS 1.1 及更高版本:

$ dig smtp.office365.com
...
SXF-efz.ms-acdc.office.com. 36  IN      A       52.98.199.194
SXF-efz.ms-acdc.office.com. 36  IN      A       40.101.61.130
SXF-efz.ms-acdc.office.com. 36  IN      A       52.98.208.114

前两个支持 TLS 1.0,最后一个仅支持 TLS 1.1 及更高版本,这意味着取决于实际选择的服务器,TLS 握手将成功或失败。请注意,从您的角度或在不同的时间,您可能会看到其他 IP 地址表现出不同的行为。

解决方案很简单:停止显式限制 SSL_version。在这种情况下,它将提供 OpenSSL 的链接版本提供的最佳版本,多年来应该比 TLS 1.0 更好。

除此之外,CORE 模块 Net::SMTP 已经内置了对 TLS 的支持好几年了,所以可能不需要使用 Net::SMTPS(反正里面使用的是 Net::SMTP)。

关于Perl:使用 Office 365 发送邮件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69677931/

相关文章:

ruby-on-rails - 如何在 ruby​​ 中使用 AES 256 ECB PKCS5Padding 加密数据

perl - 大量数据的哈希效率

C HTTP 服务器和 OpenSSL - 适用于 HTTP - 使用 HTTPS 丢弃多个/快速/并发连接

java - Perl 从右到左替换

macos - 如何修复 curl : (35) error when updating homebrew?

authentication - ReSTLet with Simple - 尽管 needClientAuthentication 设置为 true,它接受任何没有客户端证书的连接

angularjs - Meteor、Angular 路由、Nginx 和 SSL - 如何通过重写路由/路径到另一台服务器

openssl - 如何在VS2015中构建OpenSSL : x86cpuid. asm是一个空文件

Perl 兼容性

perl - 为什么 Perl 的 GD::Graph 提示 "Invalid data set"?