Ошибка отправки Perl TLS SMTP на этапе аутентификации

Я пытаюсь отправить почту, используя аутентифицированный SMTP через Perl на сервере Debian buster. Вот мой код:

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    = '[email protected]' ;
my $to      = '[email protected]' ;
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 не работает? Это Вопрос Stackoverflow не помог. (Почему бы просто не использовать код Python? Нужный код Perl является частью более крупного проекта Perl, поэтому мне нужно отправить электронное письмо на Perl.)


person rlandster    schedule 22.01.2021    source источник
comment
No such file or directory at test.pl line 25 -- строка 25 if (!$mailer->auth($principal, $password)) {.... Отсутствующий файл кажется несовместимым с ошибкой аутентификации. Можете ли вы выполнить отладку/пошаговый ввод в auth(), чтобы увидеть, что происходит?   -  person Jim Garrison    schedule 23.01.2021


Ответы (2)


if (!$mailer->auth($principal, $password)) {
    die "error authenticating: $!" ;
}

Как правило, просмотр $! не является правильным способом отладки проблем, когда Net::SMTP возвращает ошибки. Вместо этого статус и message должен быть проверен.

Мое обоснованное предположение состоит в том, что статус вернет 500, а сообщение вернет:

Need MIME::Base64 and Authen::SASL todo auth 

Это будет означать, что вы, скорее всего, не установили Authen::SASL, который необходим для аутентификации. Этот модуль является необязательным предварительным условием для Net::SMTP, поскольку он необходим только тогда, когда необходимо выполнить аутентификацию. См. также документацию по методу аутентификации:

Попробуйте аутентификацию SASL. Требуется модуль Authen::SASL.

person Steffen Ullrich    schedule 22.01.2021
comment
Я обновил свой код, чтобы показать более полезную диагностическую информацию об ошибке аутентификации, как вы предложили. - person rlandster; 23.01.2021
comment
@rlandster: Странно. Сообщаемое состояние и сообщение относятся к предыдущему вызову EHLO. И видно, что команда AUTH даже не пробовалась. Вы проверили, что Authen::SASL установлен, то есть perl -MAuthen::SASL -e ''? - person Steffen Ullrich; 23.01.2021
comment
Пакет Authen::SASL Perl установлен (и был) установлен. - person rlandster; 24.01.2021
comment
@rlandster: Вы сталкиваетесь с этой проблемой (ошибка при вызове auth, но команда AUTH даже не пробовала) с другими серверами или только с этим конкретным сервером? - person Steffen Ullrich; 24.01.2021

Что, наконец, сработало для меня, так это использование 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        = '[email protected]';
my $to          = '[email protected]';
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; не работает.

person rlandster    schedule 28.01.2021