【问题标题】:Sending mail via SMTP in Perl在 Perl 中通过 SMTP 发送邮件
【发布时间】:2012-04-17 23:50:21
【问题描述】:

我正在尝试在 Perl 中通过 SMTP 发送邮件。

我为此编写了一个脚本。

#!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;

当我运行这个脚本时,我的输出如下:

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}

我没有足够的关于 Perl 和 SMTP 的信息,所以我无法理解这个错误。

我该如何解决这个问题?

【问题讨论】:

    标签: perl email smtp


    【解决方案1】:

    它抱怨缺少MAIL FROM: SMTP 命令。 不看任何文档,我猜它看起来像$smtp-&gt;from('you@example.net')就像@cjm 写的那样,你需要$smtp-&gt;mail('you@example.net');

    当然,在您刚刚通过身份验证后必须提供用户名似乎有点愚蠢,但从历史和向后兼容性的角度来看,这是有道理的(STARTTLS ESMTP 规范可以简单地说明您需要做什么来进行身份验证,然后会话的其余部分就像在身份验证完成后的常规 SMTP 中一样发生)。不过,Net::SMTP 让您免受这些实现细节的影响是有意义的。

    【讨论】:

    • Net::SMTP 是一个低级模块;它并非旨在保护您免受细节的影响。有更高级别的模块(如 Email::Sender)可以做到这一点。
    【解决方案2】:

    您必须使用提供发件人电子邮件地址的 MAIL 命令启动 SMTP 会话(在授权后,如有必要)。这就是为什么响应说“MAIL first”(5xx 是错误响应)。所以:

    $smtp->auth($smtpuser, $smtppassword);
    $smtp->mail('sender@example.com');
    $smtp->to('mymail@gmail.com');
    

    但是,如果您不是 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      => 'mymail@gmail.com',
        From    => 'sender@example.com',
        Subject => 'Hi!',
      ],
      body => "This is my message\n",
    );
    
    sendmail($email, { transport => $transport });
    

    【讨论】:

    • 我相信您的回答会解决我的问题,但我有一个新问题。我在窗户上工作。我试图将 Email::Sender 安装到 perl 库。我使用了 mingw32 但它没有安装。
    • 发布一个带有正确诊断的单独问题,可能在 SuperUser 上。
    • 如何发送 HTML 内容而不是纯文本?
    • @LintoPD,使用 Email::MIME 代替 Email::Simple。或者试试Email::Simple::Markdown。或者...
    • @Cjm 谢谢,现在我正在使用以下代码及其工作 my $email = Email::MIME->create_html( header => [ From => 'test@lintotest.com', To = > 'linodavis@gmail.com', 主题 => '测试邮件', ], body => $html, text_body => $plain_text );发送邮件($电子邮件,{ 运输 => $运输 });但是让我知道,我怎样才能得到响应代码,错误消息来知道它是否成功?
    【解决方案3】:

    顺便说一句 - 虽然有点晚了,但对于未来的读者来说,你真的收到了邮件吗?

    附加的输出中没有错误。您已在构造函数中启用调试 (Debug=>1)。一旦您将其设置为 0,这些消息就会消失。 使用 SMTP 的优点是它包含在库存安装中。无需添加模块。

    【讨论】:

      【解决方案4】:

      遗憾的是,在 2014 年末(非常),Net::SMTP::SSL 在 1 次安装测试中失败了 1 次,因此无法访问 gmail(和任何其他)基于 Web 的服务器。在不安装我自己的邮件服务器的情况下,我能找到从 Perl 发送电子邮件的唯一方法是将 OLE 发送到 Outlook。然后 Outlook 将使用其连接来实现。

      我希望有人能证明我错了。

      【讨论】:

        【解决方案5】:

        这是 cjm 脚本的更新版本,该脚本当前可用于使用 STARTTLS 的 Gmail(未使用其他 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   = '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 });
        

        【讨论】:

          【解决方案6】:

          对于使用 STARTTLS 的电子邮件服务,最好使用较新的 NET::SMTPS 模块。试试下面的代码:

          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;
          

          【讨论】:

            猜你喜欢
            • 2014-03-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-11-13
            • 2023-03-19
            • 1970-01-01
            相关资源
            最近更新 更多