【问题标题】: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::Sender 和Email::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::SSL 和 Net::SSLeay 都支持 X.509 客户端证书。所以Net::SMTP::TLS::ButMaintained 和Email::Sender::Transport::SMTP::TLS 应该被增强以支持客户端证书。正确的方法应该更新两个模块以允许 SSL_key|SSL_key_file 和 SSL_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;
主机必须与证书中的主题完全匹配,否则将无法验证。
我假设您的系统信任中继服务器的证书颁发机构,否则您也需要修复它。