如何使用 Perl 通过仅支持基于证书的身份验证的中继发送邮件

发布于 2024-10-31 06:03:40 字数 544 浏览 0 评论 0原文

我一直在使用 Email::Sender 和 < a href="http://search.cpan.org/perldoc?Email%3a%3aSender%3a%3aTransport%3a%3aSMTP%3a%3aTLS" rel="nofollow">电子邮件::发件人::传输::SMTP::TLS 使用启用 STARTTLS 的中继发送电子邮件。中继最近已更改为使用 X.509 证书进行身份验证。但是我注意到 Email::Sender::Transport::SMTP::TLS 没有选项指向我的证书。 Email::Sender::Transport::SMTP::TLS 所基于的 Net::SMTP::TLS 也没有。

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

谢谢

I have been using Email::Sender with Email::Sender::Transport::SMTP::TLS send email using a STARTTLS enabled relay. The relay has recently changed to using X.509 certificates for authentication. However I note that Email::Sender::Transport::SMTP::TLS has no option to point to my certificate. Neither does Net::SMTP::TLS on which Email::Sender::Transport::SMTP::TLS is based.

Can someone suggest a solution? Another module perhaps that will allow me to authenticate using a certificate.

Thank you

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

难忘№最初的完美 2024-11-07 06:03:40

检查依赖树: 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|SS​​L_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();
}

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

祝你好运!

Checking the dependency tree: Email::Sender::Transport::SMTP::TLS ==> Net::SMTP::TLS::ButMaintained ==> IO::Socket::SSL ==> Net::SSLeay

Both IO::Socket::SSL and Net::SSLeay supporting the X.509 client certificates. So Net::SMTP::TLS::ButMaintained and Email::Sender::Transport::SMTP::TLS should be enhanced to support client certificates. A proper way should update both modules to allow the SSL_key|SSL_key_file and SSL_cert|SSL_cert_file parameters.

Here is a quick dirty one -- you need to create modified Net::SMTP::TLS::ButMaintained and keep it locally.

# 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();
}

Please leave the User and Password parameter as blank.

Good luck!

℡Ms空城旧梦 2024-11-07 06:03:40

为了完整起见,如果 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;

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

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

for completeness sake, Net::SMTP can do this if IO::Socket::SSL is available (don't ask me since when, but I know it works with recent versions of both modules).

Code:

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;

The host must exactly match the subject in the certificate, or it will not validate.

I assume your system trusts the certificate authority of the relay server, otherwise you need to fix that too.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文