Perl 发送电子邮件
Perl - 发送电子邮件
Section titled “Perl - 发送电子邮件”从 Perl 脚本发送电子邮件是通知、报告或应用程序警报的常见任务。现代 Perl 在 CPAN 上提供了几个模块,用于强大而灵活的电子邮件处理。虽然在类 Unix 系统上直接使用像 sendmail 这样的系统工具是可能的,但通常更推荐使用模块,以提高可移植性、功能和易用性。
使用系统 sendmail 工具(Unix/Linux)
Section titled “使用系统 sendmail 工具(Unix/Linux)”在配置了 sendmail(或兼容的邮件传输代理 MTA,如 Postfix 或 Exim)的类 Unix 系统上,你可以将电子邮件内容通过管道发送给它。这种方法对于基本电子邮件来说很简单,但缺乏高级功能和可移植性。
使用 sendmail 发送纯文本消息
Section titled “使用 sendmail 发送纯文本消息”#!/usr/bin/perluse strict;use warnings;
my $to = 'recipient@example.com';my $from = 'sender@example.com';my $subject = 'Test Email from Perl (sendmail)';my $message_body = "This is a test email sent by a Perl script using sendmail.
Regards,Perl Script";
# Adjust path to sendmail if necessary# 如有必要,调整 sendmail 的路径my $sendmail_path = "/usr/sbin/sendmail";
unless (open(MAIL, "|- ", "$sendmail_path -t -oi")) { die "Could not open pipe to sendmail: $!"; # 无法打开到 sendmail 的管道:$!}
print MAIL "To: $to\n";print MAIL "From: $from\n";print MAIL "Subject: $subject\n";print MAIL "\n"; # Blank line separates headers from body# 空行将头部与正文分开print MAIL $message_body;
unless (close(MAIL)) { die "Sendmail command failed: $? $!"; # $? for exit status # sendmail 命令失败:$? $! # $? 表示退出状态}
print "Email sent successfully via sendmail (hopefully!)\n";# 通过 sendmail 成功发送电子邮件(希望如此!)注意:-t 选项告诉 sendmail 从头部读取收件人。-oi 防止将只有单个点的行视为消息结束。此方法依赖于正确配置的本地 MTA。
使用 Perl 模块发送电子邮件(推荐)
Section titled “使用 Perl 模块发送电子邮件(推荐)”使用 CPAN 模块是 Perl 中处理电子邮件的标准和推荐方式。像 Email::Stuffer、Email::Sender 和较旧的 MIME::Lite 等模块提供了全面的功能。
要安装模块,通常使用 cpanm(App::cpanminus):
cpanm Module::Name # e.g., cpanm Email::Stuffer# 例如,cpanm Email::Stuffer使用 MIME::Lite 模块(较旧,但仍然可用)
Section titled “使用 MIME::Lite 模块(较旧,但仍然可用)”MIME::Lite 是一个历史悠久的模块,用于创建和发送 MIME 消息。虽然较新的模块提供了更现代的 API,但对于基本任务来说,MIME::Lite 相对简单。对于新项目,可以考虑使用 Email::Stuffer 或将 Email::Sender 与 Email::MIME::Creator 结合使用。
使用 MIME::Lite 发送纯文本消息:
#!/usr/bin/perluse strict;use warnings;use MIME::Lite;
my $to = 'recipient@example.com';my $from = 'sender@example.com';my $subject = 'Test Email from Perl (MIME::Lite)';my $message_body = "This is a test email sent via MIME::Lite.";# 这是通过 MIME::Lite 发送的测试电子邮件。
try { my $msg = MIME::Lite->new( From => $from, To => $to, Subject => $subject, Data => $message_body, Type => 'text/plain' # Explicitly set type # 明确设置类型 );
# By default, MIME::Lite tries to use sendmail. # 默认情况下,MIME::Lite 尝试使用 sendmail。 # For other transport methods, see send_by_smtp below. # 对于其他传输方法,请参阅下面的 send_by_smtp。 $msg->send; print "Email sent successfully via MIME::Lite!\n"; # 通过 MIME::Lite 成功发送电子邮件!}catch { warn "Failed to send email: $_\n"; # 发送电子邮件失败:$_\n};使用 MIME::Lite 发送 HTML 消息:
#!/usr/bin/perluse strict;use warnings;use MIME::Lite;
my $to = 'recipient@example.com';my $from = 'sender@example.com';my $subject = 'HTML Test Email from Perl (MIME::Lite)';my $html_body = <<'END_HTML';<h1>Hello from Perl!</h1><p>This is an **HTML** email sent using <code>MIME::Lite</code>.</p><p><a href="https://www.perl.org">Visit Perl.org</a></p>END_HTML
try { my $msg = MIME::Lite->new( From => $from, To => $to, Subject => $subject, Type => 'text/html', # Set content type to HTML # 设置内容类型为 HTML Data => $html_body ); $msg->send; print "HTML Email sent successfully via MIME::Lite!\n"; # 通过 MIME::Lite 成功发送 HTML 电子邮件!}catch { warn "Failed to send HTML email: $_\n"; # 发送 HTML 电子邮件失败:$_\n};使用 MIME::Lite 发送带附件的电子邮件:
#!/usr/bin/perluse strict;use warnings;use MIME::Lite;
my $to = 'recipient@example.com';my $from = 'sender@example.com';my $subject = 'Email with Attachment (MIME::Lite)';my $text_body = "Please find the attached report.";# 请查收附件报告。my $attachment_path = './report.txt'; # Create a dummy report.txt for testing# 为测试创建一个虚拟的 report.txt 文件
# Create a dummy attachment file for testing# 为测试创建虚拟附件文件open my $fh, '>', $attachment_path or die "Cannot create dummy attachment: $!";# 无法创建虚拟附件:$!print $fh "This is a test report.\nLine 2 of report.\n";# 这是测试报告。# 报告的第 2 行。close $fh;
try { my $msg = MIME::Lite->new( From => $from, To => $to, Subject => $subject, Type => 'multipart/mixed' # For messages with attachments # 用于带附件的消息 );
# Attach the text part # 附加文本部分 $msg->attach( Type => 'text/plain', Data => $text_body );
# Attach the file # 附加文件 $msg->attach( Type => 'text/plain', # Or application/octet-stream, etc. # 或 application/octet-stream 等 Path => $attachment_path, Filename => 'report_from_perl.txt', # Name for the attachment # 附件名称 Disposition => 'attachment' );
$msg->send; print "Email with attachment sent successfully via MIME::Lite!\n"; # 通过 MIME::Lite 成功发送带附件的电子邮件!}catch { warn "Failed to send email with attachment: $_\n"; # 发送带附件的电子邮件失败:$_\n}
unlink $attachment_path; # Clean up dummy file# 清理虚拟文件使用 SMTP 服务器与 MIME::Lite
Section titled “使用 SMTP 服务器与 MIME::Lite”如果你的机器未配置为直接发送邮件(例如,没有本地 sendmail),或者你需要使用特定的 SMTP 服务器(如 Gmail, SendGrid 等),你可以配置 MIME::Lite 通过 SMTP 发送。这通常需要安装 Net::SMTP。
#!/usr/bin/perluse strict;use warnings;use MIME::Lite;
my $to = 'recipient@example.com';my $from = 'sender@example.com'; # Often needs to be a valid address on the SMTP server# 通常需要在 SMTP 服务器上是有效的地址my $subject = 'SMTP Test from MIME::Lite';# 来自 MIME::Lite 的 SMTP 测试my $body = 'This email was sent via an external SMTP server.';# 这封电子邮件是通过外部 SMTP 服务器发送的。
my $smtp_server = 'smtp.example.com';my $smtp_user = 'your_username'; # Optional, if authentication is needed# 可选,如果需要认证my $smtp_pass = 'your_password'; # Optional# 可选
try { my $msg = MIME::Lite->new( From => $from, To => $to, Subject => $subject, Data => $body, Type => 'text/plain' );
# Option 1: Set global send method for MIME::Lite # 选项 1:设置 MIME::Lite 的全局发送方法 # MIME::Lite->send('smtp', $smtp_server, AuthUser => $smtp_user, AuthPass => $smtp_pass, Debug => 1); # $msg->send();
# Option 2: Use send_by_smtp (or send_via_smtp) on the message object # 选项 2:在消息对象上使用 send_by_smtp(或 send_via_smtp) # This requires Net::SMTP or similar to be available. # 这需要 Net::SMTP 或类似模块可用。 $msg->send_by_smtp($smtp_server, AuthUser => $smtp_user, AuthPass => $smtp_pass, Port => 587, # Common port for SMTP with STARTTLS # SMTP STARTTLS 的常用端口 Hello => 'my.hostname.com', # Optional HELO/EHLO domain # 可选的 HELO/EHLO 域名 # SSL => 'starttls', # For STARTTLS, often requires Net::SMTP::TLS::ButMaintained or IO::Socket::SSL # 对于 STARTTLS,通常需要 Net::SMTP::TLS::ButMaintained 或 IO::Socket::SSL # SSL => 1, # For SMTPS (SMTP over SSL directly on port 465) # 对于 SMTPS(端口 465 上直接使用 SSL 的 SMTP) Debug => 1 # Enable debugging output from Net::SMTP # 启用 Net::SMTP 的调试输出 ) or die "SMTP sending failed: " . MIME::Lite->errmsg; # SMTP 发送失败:... # MIME::Lite->errmsg
print "Email sent successfully via SMTP!\n"; # 通过 SMTP 成功发送电子邮件!}catch { warn "Failed to send email via SMTP: $_\n"; # 通过 SMTP 发送电子邮件失败:$_\n if (MIME::Lite->errmsg) { warn "MIME::Lite error: " . MIME::Lite->errmsg . "\n"; # MIME::Lite 错误:... # MIME::Lite->errmsg }};对于 SMTP,特别是涉及认证和 SSL/TLS 时,强烈推荐使用更现代的模块,例如 Email::Sender::Transport::SMTP::TLS(Email::Sender 生态系统的一部分),因为它们更健壮地处理这些复杂性。MIME::Lite 的直接 SMTP 支持在满足现代安全要求时可能很棘手。
现代替代方案:Email::Stuffer 或 Email::Sender
Section titled “现代替代方案:Email::Stuffer 或 Email::Sender”对于新的 Perl 项目,可以考虑以下更现代的模块:
Email::Stuffer:一个流行的选择,因其简单流畅的接口用于创建和发送电子邮件,包括 HTML、文本部分和附件。它底层通常使用Email::Sender。Email::Sender:一个灵活的电子邮件发送系统,支持各种传输方式(SMTP, sendmail 等),并良好支持现代 SMTP 功能,如 SSL/TLS 和认证。
使用 Email::Stuffer 的示例(概念性):
#!/usr/bin/perluse strict;use warnings;use Email::Stuffer;
# Conceptual example - details depend on your SMTP setup# 概念性示例 - 具体细节取决于你的 SMTP 设置my $email = Email::Stuffer->from('sender@example.com') ->to('recipient@example.com') ->subject('Modern Perl Email Test') # 现代 Perl 电子邮件测试 ->text_body('Hello from Email::Stuffer!') # 来自 Email::Stuffer 的问候! ->html_body('<h1>Hello from Email::Stuffer!</h1>') # <h1>来自 Email::Stuffer 的问候!</h1> ->attach_file('./report.pdf');
# To send via SMTP, you might need to configure transport or use Email::Sender directly# 要通过 SMTP 发送,你可能需要配置传输方式或直接使用 Email::Sender# $email->send; # Default send might use sendmail# 默认发送可能使用 sendmail
try { # Example of sending via Email::Sender with specific transport: # 使用 Email::Sender 通过特定传输方式发送的示例: use Email::Sender::Simple qw(sendmail); use Email::Sender::Transport::SMTP;
my $transport = Email::Sender::Transport::SMTP->new({ host => 'smtp.example.com', port => 587, # ssl => 'starttls', # or true for SMTPS on port 465 # 或 true 表示端口 465 上的 SMTPS # sasl_username => 'user', # sasl_password => 'pass', }); sendmail($email->as_email_mime, { transport => $transport }); print "Email sent with Email::Stuffer via SMTP!\n"; # 使用 Email::Stuffer 通过 SMTP 发送电子邮件!}catch { warn "Failed to send email with Email::Stuffer: $_\n"; # 使用 Email::Stuffer 发送电子邮件失败:$_\n};请务必查阅你选择的特定电子邮件模块的文档,因为 SMTP 服务器、认证和加密的配置可能有所不同。