it-roy-ru.com

Отправка почты через SMTP в Perl

Я пытаюсь отправить почту через SMTP в Perl. 

Я написал сценарий для этого. 

#!Perl
use warnings;
use strict;
use Net::SMTP;

my $smtpserver = 'server';
my $smtpport = 25;
my $smtpuser   = 'username';
my $smtppassword = 'password';

my $smtp = Net::SMTP->new($smtpserver, Port=>$smtpport, Timeout => 10, Debug => 1);
die "Could not connect to server!\n" unless $smtp;

$smtp->auth($smtpuser, $smtppassword);
$smtp->to('[email protected]');
$smtp->data();
$smtp->datasend("To: mymail\@gmail.com\n");
$smtp->quit;

Когда я запускаю этот скрипт, мой вывод выглядит следующим образом:

Net::SMTP>>> Net::SMTP(2.31)
Net::SMTP>>>   Net::Cmd(2.29)
Net::SMTP>>>     Exporter(5.65)
Net::SMTP>>>   IO::Socket::INET(1.31)
Net::SMTP>>>     IO::Socket(1.32)
Net::SMTP>>>       IO::Handle(1.31)
Net::SMTP=GLOB(0x273faf0)<<< 220 server GMX Mailservices E
Net::SMTP=GLOB(0x273faf0)>>> EHLO localhost.localdomain
Net::SMTP=GLOB(0x273faf0)<<< 250-server GMX Mailservices
Net::SMTP=GLOB(0x273faf0)<<< 250-8BITMIME
Net::SMTP=GLOB(0x273faf0)<<< 250-ENHANCEDSTATUSCODES
Net::SMTP=GLOB(0x273faf0)<<< 250-SIZE
Net::SMTP=GLOB(0x273faf0)<<< 250-AUTH=LOGIN PLAIN
Net::SMTP=GLOB(0x273faf0)<<< 250-AUTH LOGIN PLAIN
Net::SMTP=GLOB(0x273faf0)<<< 250 STARTTLS
Net::SMTP=GLOB(0x273faf0)>>> RCPT TO:<[email protected]>
Net::SMTP=GLOB(0x273faf0)<<< 503 5.5.1 MAIL first {mp-eu001}
Net::SMTP=GLOB(0x273faf0)>>> DATA
Net::SMTP=GLOB(0x273faf0)<<< 503 5.5.1 MAIL first {mp-eu001}
Net::SMTP=GLOB(0x273faf0)>>> To: [email protected]
Net::SMTP=GLOB(0x273faf0)>>> .
Net::SMTP=GLOB(0x273faf0)<<< 502 5.5.2 Unimplemented {mp-eu001}
Net::SMTP=GLOB(0x273faf0)>>> QUIT
Net::SMTP=GLOB(0x273faf0)<<< 502 5.5.2 Unimplemented {mp-eu001}

У меня недостаточно информации о Perl и SMTP, поэтому я не мог понять эту ошибку.

Как я могу решить это?

17
Selin

Вы должны начать SMTP-сеанс (после авторизации, если необходимо) с помощью команды MAIL с указанием адреса электронной почты отправителя. Вот почему в ответах написано «MAIL first» (5xx - ответ об ошибке). Так:

$smtp->auth($smtpuser, $smtppassword);
$smtp->mail('[email protected]');
$smtp->to('[email protected]');

Но если вы не являетесь экспертом по SMTP, почему бы не использовать модуль более высокого уровня, например Email :: Sender вместо низкоуровневого Net :: SMTP ?

use strict;
use warnings;

use Email::Sender::Simple qw(sendmail);
use Email::Sender::Transport::SMTP ();
use Email::Simple ();
use Email::Simple::Creator ();

my $smtpserver = 'server';
my $smtpport = 25;
my $smtpuser   = 'username';
my $smtppassword = 'password';

my $transport = Email::Sender::Transport::SMTP->new({
  Host => $smtpserver,
  port => $smtpport,
  sasl_username => $smtpuser,
  sasl_password => $smtppassword,
});

my $email = Email::Simple->create(
  header => [
    To      => '[email protected]',
    From    => '[email protected]',
    Subject => 'Hi!',
  ],
  body => "This is my message\n",
);

sendmail($email, { transport => $transport });
26
cjm

Вот обновленная версия скрипта cjm, который в настоящее время работает с Gmail с использованием STARTTLS (не тестируется с другими службами SMTP) Он использует Email :: Sender :: Transport :: SMTPS вместо Email :: Sender :: Transport :: SMTP

В вашей учетной записи Gmail должен быть разрешен «Доступ к менее защищенным приложениям» («включен») - там, где «менее безопасный» не означает незашифрованный, просто кажется, что он не использует OAuth 2.0 

use strict;
use warnings;

use Email::Sender::Simple qw(sendmail);
use Email::Sender::Transport::SMTPS;
use Email::Simple ();
use Email::Simple::Creator ();

my $smtpserver = 'smtp.gmail.com';
my $smtpport = 587;
my $smtpuser   = '[email protected]';
my $smtppassword = 'password';

my $transport = Email::Sender::Transport::SMTPS->new({
  Host => $smtpserver,
  ssl  => 'starttls',
  port => $smtpport,
  sasl_username => $smtpuser,
  sasl_password => $smtppassword,
  debug => 1,
});


my $email = Email::Simple->create(
  header => [
    To      => '[email protected]',
    From    => '[email protected]',
    Subject => 'Hi!',
  ],
  body => "This is my message\n",
);

sendmail($email, { transport => $transport });
6
Michael Johnson

Он жалуется на отсутствие SMTP-команды MAIL FROM:Не смотря на какую-либо документацию, я думаю, что это будет выглядеть примерно так: $smtp->from('[email protected]') Как пишет @cjm, вам нужна функция $smtp->mail('[email protected]');

Конечно, кажется немного глупым предоставлять имя пользователя после того, как вы только что завершили аутентификацию, но это имеет смысл с точки зрения исторической и обратной совместимости (спецификация STARTTLS ESMTP может просто указать, что вам нужно сделать для аутентификации, затем остальная часть сеанса происходит так же, как в обычном SMTP после аутентификации). Хотя Net::SMTP имеет смысл защитить вас от этих деталей реализации.

1
tripleee

К сожалению, в (очень) конце 2014 года Net :: SMTP :: SSL не прошел тесты установки 1 из 1, поэтому сервер gmail (и любой другой) недоступен. Без установки моего собственного почтового сервера я могу найти единственный способ отправки электронной почты из Perl - OLE отправить его в Outlook. Outlook будет использовать свои соединения, чтобы все произошло.

Я надеюсь, что кто-то может доказать, что я не прав. 

0
Mike

Для почтовых сервисов, использующих STARTTLS, лучше использовать новый модуль NET :: SMTPS. Попробуйте следующий код:

my $msg = MIME::Lite ->new (  
From => '[email protected]',
To => '[email protected]',
Subject => 'Test Message',
Data => 'This is a test',
Type => 'text/html'
);

my $USERNAME = '[email protected]';
my $PASSWORD = 'abc123'; 

my $smtps = Net::SMTPS->new("smtp.mail.att.net", Port => 587,  doSSL => 'starttls', SSL_version=>'TLSv1');

$smtps->auth ( $USERNAME, $PASSWORD ) or die("Could not authenticate with bellsouth.\n");

$smtps ->mail('[email protected]');
$smtps->to('[email protected]');
$smtps->data();
$smtps->datasend( $msg->as_string() );  
$smtps->dataend();  
$smtps->quit;
0
Morey

Кстати, хотя в любом случае для будущих читателей, хотя и с некоторым опозданием, вы действительно получили письмо?

Там нет ошибок в выводе прилагается. Вы включили отладку (Debug => 1) в своем конструкторе. Эти сообщения исчезнут, как только вы установите значение 0. Преимущество использования SMTP заключается в том, что он включен в стандартную установку. Не нужно добавлять модули. 

0
RB1987