可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
I am trying to send mail via SMTP in Perl.
I have written a script for this.
#!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('mymail@gmail.com');
$smtp->data();
$smtp->datasend("To: mymail\@gmail.com\n");
$smtp->quit;
When I run this script, my output is like following:
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:<mymail@gmail.com>
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: mymail@gmail.com
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}
I don't have enough information about Perl and SMTP, so I couldn't understand this error.
How can I solve this?
回答1:
You have to start a SMTP session (after authorization, if necessary) with a MAIL command giving the sender's email address. That's why the responses say "MAIL first" (5xx is an error response). So:
$smtp->auth($smtpuser, $smtppassword);
$smtp->mail('sender@example.com');
$smtp->to('mymail@gmail.com');
But if you're not a SMTP expert, why not use a higher-level module like Email::Sender instead of the low-level 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 => 'mymail@gmail.com',
From => 'sender@example.com',
Subject => 'Hi!',
],
body => "This is my message\n",
);
sendmail($email, { transport => $transport });
回答2:
Here's an updated version of cjm's script that currently works with Gmail using STARTTLS (not tested with other SMTP services)
It uses Email::Sender::Transport::SMTPS instead of Email::Sender::Transport::SMTP
Your gmail account will have to have "Access for less secure apps" allowed ("turned on") -- where "less secure" does not mean unencrypted, it just seems to mean not using 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 = 'user@gmail.com';
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 => 'user@example.com',
From => 'whatever@gmail.com',
Subject => 'Hi!',
],
body => "This is my message\n",
);
sendmail($email, { transport => $transport });
回答3:
It complains about the lack of a MAIL FROM:
SMTP command. Without looking at any documentation, I'd guess it'd look something like $smtp->from('you@example.net')
Like @cjm writes, you need $smtp->mail('you@example.net');
Granted, it seems a bit silly to have to supply a user name after you have just authenticated, but it makes sense from a historical and backwards compatibility point of view (the STARTTLS ESMTP spec can simply state what you need to do to authenticate, then the rest of the session happens just like in regular SMTP after the authentication is done). It would make sense for Net::SMTP
to shield you from these implementation details, though.
回答4:
Btw - although a bit late, anyway for future readers, Did you actually recv the mail?
There are no errors in the output attached. You have enabled debug (Debug=>1) in your constructor. These messages will go away once you set that to 0.
Advantage of using SMTP is that it is included in stock install. No need to add modules.
回答5:
Sadly, in (very) late 2014, Net::SMTP::SSL fails 1 of 1 installation tests, thus gmail (and any other) web based server is unreachable. Without installing my own mail server, the only way I can find to send email from Perl is to OLE it to Outlook. Outlook will then use its connections to make things happen.
I hope someone can prove me wrong.
回答6:
For email services that use STARTTLS, it's best to use the newer NET::SMTPS module. Try the following code:
my $msg = MIME::Lite ->new (
From => 'from@bellsouth.net',
To => 'to@gmail.com',
Subject => 'Test Message',
Data => 'This is a test',
Type => 'text/html'
);
my $USERNAME = 'from@bellsouth.net';
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('from@bellsouth.net');
$smtps->to('to@gmail.com');
$smtps->data();
$smtps->datasend( $msg->as_string() );
$smtps->dataend();
$smtps->quit;