Perl TLS SMTP 在身份验证步骤中发送失败
Perl TLS SMTP send failing on authentication step
我正在尝试在 Debian buster 服务器上通过 Perl 使用经过身份验证的 SMTP 发送邮件。这是我的代码:
use strict ;
use warnings ;
use autodie ;
use Net::SMTP; # version 3.11
use Authen::SASL;
my $smtp_server = 'smtp.example.com' ;
my $principal = 'myusername' ;
print "Password: ";
my $password = <STDIN>;
chomp($password);
my $from = 'joeuser@example.com' ;
my $to = 'joeuser@example.com' ;
my $subject = 'Test message' ;
my $body = "The body of the e-mail message.";
my $mailer = Net::SMTP->new($smtp_server, 'SSL' => 1, 'Port' => 465, 'Debug' => 1);
if (!$mailer) { die $@ ; }
if (!$mailer->auth($principal, $password)) {
warn "error authenticating; status is '" . $mailer->status() . "'\n";
warn "error authenticating; message is '" . $mailer->message() . "'\n";
exit 1;
}
这是输出:
Password: secretsecretsecret
Net::SMTP::_SSL>>> Net::SMTP::_SSL
Net::SMTP::_SSL>>> IO::Socket::SSL(2.060)
Net::SMTP::_SSL>>> IO::Socket::IP(0.39)
Net::SMTP::_SSL>>> IO::Socket(1.39)
Net::SMTP::_SSL>>> IO::Handle(1.39)
Net::SMTP::_SSL>>> Exporter(5.73)
Net::SMTP::_SSL>>> Net::SMTP(3.11)
Net::SMTP::_SSL>>> Net::Cmd(3.11)
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 220 smtp.example.com ESMTP Postfix
Net::SMTP::_SSL=GLOB(0x562cc320f080)>>> EHLO localhost.localdomain
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-smtp.example.com
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-PIPELINING
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-SIZE 51200000
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-ETRN
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-AUTH PLAIN LOGIN GSSAPI
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-ENHANCEDSTATUSCODES
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-8BITMIME
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-DSN
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250 CHUNKING
error authenticating; status is '2'
error authenticating; message is 'smtp.example.com
PIPELINING
SIZE 51200000
ETRN
AUTH PLAIN LOGIN GSSAPI
ENHANCEDSTATUSCODES
8BITMIME
DSN
CHUNKING
'
但是请注意,以下 Python 代码 运行 在同一台计算机上 有效 :
#!/usr/bin/python3
username = 'joeuser'
principal = 'myusername'
smtp_server = 'smtp.example.com'
import smtplib
from email.mime.text import MIMEText
from getpass import getpass
conn = smtplib.SMTP_SSL(smtp_server, 465)
password = getpass()
conn.login(principal, password)
usermail = username + '@example.com'
content="""\
Test message.
"""
msg = MIMEText(content, 'plain')
msg['Subject'] = 'Testing authenticated mail send using ' + principal
msg['From'] = usermail
conn.sendmail(usermail, usermail, msg.as_string())
为什么 Perl 代码不起作用?这 Whosebug question 没有帮助。 (为什么不直接使用 Python 代码?所需的 Perl 代码是一个更大的 Perl 项目的一部分,所以我需要用 Perl 发送电子邮件。)
if (!$mailer->auth($principal, $password)) {
die "error authenticating: $!" ;
}
一般来说,当 return 由 Net::SMTP 编辑错误时,查看 $!
并不是调试问题的正确方法。相反,应该检查 status and message。
我有根据的猜测是状态将 return 500,消息将 return:
Need MIME::Base64 and Authen::SASL todo auth
这意味着您很可能还没有安装 Authen::SASL which is needed for doing authentication. This module is only an optional prerequisite of Net::SMTP since it is only needed when authentication should be done. See also the documentation for the auth method:
Attempt SASL authentication. Requires Authen::SASL module.
最终对我有用的是使用 use Authen::SASL qw(Perl)
:
use strict ;
use warnings ;
use Net::SMTP
#use Authen::SASL; # This did NOT work.
use Authen::SASL qw(Perl); # This DID work.
my $smtp_server = 'smtp.example.com';
my $principal = 'myusername';
my $password = 'secretsecretsecret';
my $from = 'myname@example.com';
my $to = 'afriend@example.net';
my $subject = 'Hello friend';
my $body = 'Give me a call when you can.';
my $mailer = Net::SMTP->new($smtp_server, 'SSL' => 1, 'Port' => 465, 'Debug' => 1);
if (!$mailer) { die $@ ; }
if (!$mailer->auth($principal, $password)) {
print "error authenticating; status is '" . $mailer->status() . "'\n";
print "error authenticating; message is '" . $mailer->message() . "\n'";
exit 1;
}
$mailer->mail($from) ;
$mailer->to($to) ;
$mailer->data();
$mailer->datasend("To: $to");
$mailer->datasend("\n");
$mailer->datasend("Subject: $subject");
$mailer->datasend("\n");
$mailer->datasend($body);
$mailer->dataend();
$mailer->quit;
这引出了一个问题,即 为什么 use Authen::SASL;
不起作用。
我正在尝试在 Debian buster 服务器上通过 Perl 使用经过身份验证的 SMTP 发送邮件。这是我的代码:
use strict ;
use warnings ;
use autodie ;
use Net::SMTP; # version 3.11
use Authen::SASL;
my $smtp_server = 'smtp.example.com' ;
my $principal = 'myusername' ;
print "Password: ";
my $password = <STDIN>;
chomp($password);
my $from = 'joeuser@example.com' ;
my $to = 'joeuser@example.com' ;
my $subject = 'Test message' ;
my $body = "The body of the e-mail message.";
my $mailer = Net::SMTP->new($smtp_server, 'SSL' => 1, 'Port' => 465, 'Debug' => 1);
if (!$mailer) { die $@ ; }
if (!$mailer->auth($principal, $password)) {
warn "error authenticating; status is '" . $mailer->status() . "'\n";
warn "error authenticating; message is '" . $mailer->message() . "'\n";
exit 1;
}
这是输出:
Password: secretsecretsecret
Net::SMTP::_SSL>>> Net::SMTP::_SSL
Net::SMTP::_SSL>>> IO::Socket::SSL(2.060)
Net::SMTP::_SSL>>> IO::Socket::IP(0.39)
Net::SMTP::_SSL>>> IO::Socket(1.39)
Net::SMTP::_SSL>>> IO::Handle(1.39)
Net::SMTP::_SSL>>> Exporter(5.73)
Net::SMTP::_SSL>>> Net::SMTP(3.11)
Net::SMTP::_SSL>>> Net::Cmd(3.11)
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 220 smtp.example.com ESMTP Postfix
Net::SMTP::_SSL=GLOB(0x562cc320f080)>>> EHLO localhost.localdomain
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-smtp.example.com
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-PIPELINING
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-SIZE 51200000
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-ETRN
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-AUTH PLAIN LOGIN GSSAPI
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-ENHANCEDSTATUSCODES
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-8BITMIME
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250-DSN
Net::SMTP::_SSL=GLOB(0x562cc320f080)<<< 250 CHUNKING
error authenticating; status is '2'
error authenticating; message is 'smtp.example.com
PIPELINING
SIZE 51200000
ETRN
AUTH PLAIN LOGIN GSSAPI
ENHANCEDSTATUSCODES
8BITMIME
DSN
CHUNKING
'
但是请注意,以下 Python 代码 运行 在同一台计算机上 有效 :
#!/usr/bin/python3
username = 'joeuser'
principal = 'myusername'
smtp_server = 'smtp.example.com'
import smtplib
from email.mime.text import MIMEText
from getpass import getpass
conn = smtplib.SMTP_SSL(smtp_server, 465)
password = getpass()
conn.login(principal, password)
usermail = username + '@example.com'
content="""\
Test message.
"""
msg = MIMEText(content, 'plain')
msg['Subject'] = 'Testing authenticated mail send using ' + principal
msg['From'] = usermail
conn.sendmail(usermail, usermail, msg.as_string())
为什么 Perl 代码不起作用?这 Whosebug question 没有帮助。 (为什么不直接使用 Python 代码?所需的 Perl 代码是一个更大的 Perl 项目的一部分,所以我需要用 Perl 发送电子邮件。)
if (!$mailer->auth($principal, $password)) {
die "error authenticating: $!" ;
}
一般来说,当 return 由 Net::SMTP 编辑错误时,查看 $!
并不是调试问题的正确方法。相反,应该检查 status and message。
我有根据的猜测是状态将 return 500,消息将 return:
Need MIME::Base64 and Authen::SASL todo auth
这意味着您很可能还没有安装 Authen::SASL which is needed for doing authentication. This module is only an optional prerequisite of Net::SMTP since it is only needed when authentication should be done. See also the documentation for the auth method:
Attempt SASL authentication. Requires Authen::SASL module.
最终对我有用的是使用 use Authen::SASL qw(Perl)
:
use strict ;
use warnings ;
use Net::SMTP
#use Authen::SASL; # This did NOT work.
use Authen::SASL qw(Perl); # This DID work.
my $smtp_server = 'smtp.example.com';
my $principal = 'myusername';
my $password = 'secretsecretsecret';
my $from = 'myname@example.com';
my $to = 'afriend@example.net';
my $subject = 'Hello friend';
my $body = 'Give me a call when you can.';
my $mailer = Net::SMTP->new($smtp_server, 'SSL' => 1, 'Port' => 465, 'Debug' => 1);
if (!$mailer) { die $@ ; }
if (!$mailer->auth($principal, $password)) {
print "error authenticating; status is '" . $mailer->status() . "'\n";
print "error authenticating; message is '" . $mailer->message() . "\n'";
exit 1;
}
$mailer->mail($from) ;
$mailer->to($to) ;
$mailer->data();
$mailer->datasend("To: $to");
$mailer->datasend("\n");
$mailer->datasend("Subject: $subject");
$mailer->datasend("\n");
$mailer->datasend($body);
$mailer->dataend();
$mailer->quit;
这引出了一个问题,即 为什么 use Authen::SASL;
不起作用。