【问题标题】:How do I use Perl to send mail via a relay that only supports certificate based authentication如何使用 Perl 通过仅支持基于证书的身份验证的中继发送邮件
【发布时间】:2011-08-02 05:33:24
【问题描述】:

我一直在使用Email::SenderEmail::Sender::Transport::SMTP::TLS 使用启用了STARTTLS 的中继发送电子邮件。中继最近更改为使用 X.509 证书进行身份验证。但是我注意到Email::Sender::Transport::SMTP::TLS 无法指向我的证书。 Email::Sender::Transport::SMTP::TLS 所基于的 Net::SMTP::TLS 也不是。

有人可以提出解决方案吗?另一个模块可能允许我使用证书进行身份验证。

谢谢

【问题讨论】:

    标签: perl email authentication certificate


    【解决方案1】:

    检查依赖树:Email::Sender::Transport::SMTP::TLS ==> Net::SMTP::TLS::ButMaintained ==> IO::Socket::SSL ==> Net::SSLeay

    IO::Socket::SSLNet::SSLeay 都支持 X.509 客户端证书。所以Net::SMTP::TLS::ButMaintainedEmail::Sender::Transport::SMTP::TLS 应该被增强以支持客户端证书。正确的方法应该更新两个模块以允许 SSL_key|SSL_key_fileSSL_cert|SSL_cert_file 参数。

    这是一个快速脏的——您需要创建修改后的Net::SMTP::TLS::ButMaintained 并将其保存在本地。

    # modify the Net::SMTP::TLS::ButMaintained; 
    # built a private version which have client certificates
    sub starttls {
        my $me = shift;
        $me->_command("STARTTLS");
        my ( $num, $txt ) = $me->_response();
        if ( not $num == 220 ) {
            croak "Invalid response for STARTTLS: $num $txt\n";
        }
        if (
            not IO::Socket::SSL::socket_to_SSL(
                $me->{sock}, 
                SSL_version => "SSLv3 TLSv1", 
                ### private changes begin: append following two lines. 
                SSL_use_cert => 1,
                SSL_cert_file => "path_to/your/certificate_file.pem",
                SSL_key_file => "path_to/your/private_key_file.pem"
                ### private changes end:
            )
          )
        {
            croak "Couldn't start TLS: " . IO::Socket::SSL::errstr . "\n";
        }
        $me->hello();
    }
    

    请将用户和密码参数留空。

    祝你好运!

    【讨论】:

    • 谢谢!!那真的很有用。将更新此问题以反映实施情况
    【解决方案2】:

    为了完整起见,如果 IO::Socket::SSL 可用,Net::SMTP 可以执行此操作(不要问我从什么时候开始,但我知道它适用于两个模块的最新版本)。

    代码:

    use strict;
    use warnings;
    use Net::SMTP;
    
    my $smtp = Net::SMTP->new(
        Host    => 'host.domain.tld',
        Hello   => 'hi there',
        Port    => 587,
        Timeout => 5,
        Debug   => 4,
    );
    
    $smtp->starttls(
        SSL_cert_file   => "/path/to/crt",
        SSL_key_file    => "/path/to/key",
    );
    
    $smtp->mail("user\+perl\@domain\.nl\n");
    $smtp->to("user\@otherdomain\.tld\n");
    $smtp->data;
    $smtp->datasend("From: Your Name <user\@domain.tld>\n");
    $smtp->datasend("To: Recipient <user\@otherdomain.tld>\n");
    $smtp->datasend("Subject: certificate based relay testing\n");
    $smtp->datasend("MIME-Version: 1.0\n");
    $smtp->datasend("Content-Type: text/plain; charset=us-ascii\n");
    $smtp->datasend("X-Mailer: Net::SMTP IO::Socket::SSL\n");
    $smtp->datasend( "X-mydate: " . localtime() . "\n" );
    $smtp->datasend("\n");
    $smtp->datasend("testing again\n");
    $smtp->dataend;
    $smtp->quit;
    

    主机必须与证书中的主题完全匹配,否则将无法验证。

    我假设您的系统信任中继服务器的证书颁发机构,否则您也需要修复它。

    【讨论】:

    • 感谢您提供更多信息
    猜你喜欢
    • 2019-11-30
    • 1970-01-01
    • 2020-08-02
    • 2011-05-03
    • 2017-09-22
    • 2019-06-01
    • 2016-10-02
    • 2018-02-24
    • 2012-07-12
    相关资源
    最近更新 更多