You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Perl CGI脚本发邮件后出现500错误及输出提前结束问题求助

解决Perl CGI脚本发送邮件后出现500 Internal Server Error的问题

问题现象

邮件可正常发送,但脚本执行后返回500 Internal Server Error,服务器日志提示:

[Tue Jan 17 16:00:23.475272 2023] [cgi:error] [pid 230679] [client 69.90.223.10:35014] End of script output before headers: test3.cgi

已确认CGI文件权限为755,脚本可执行到发送邮件的子程序,但仍触发错误。

核心原因

CGI规范强制要求脚本必须先向Web服务器输出HTTP响应头(至少包含Content-Type字段),再输出响应内容。当前脚本仅执行邮件发送逻辑后直接exit,未输出任何HTTP头,服务器无法识别有效响应,因此返回500错误。

另外,脚本中使用的die语句如果触发(比如SMTP连接失败),会直接输出错误信息到标准输出,但同样没有前置HTTP头,也会导致相同的错误。

解决方案

修改后的完整代码

#!/usr/bin/perl -Tw
use warnings; # 取消注释,便于排查潜在问题
use strict;
use Net::SMTP;

# 先输出HTTP响应头,这是CGI脚本的强制要求
print "Content-Type: text/plain\n\n";

eval {
    send_mail(
        'mail.xxxxxxx.com',        # Host
        'order@xxxxxxxxx.com',     # From
        'yyyyyyy@gmail.com',       # To
        'Just a test, from mail.xxxxxx.com please ignore',  # Message body
        "Testing mail server email.\n" # Subject
    );
    print "邮件发送成功\n";
};
if ($@) {
    print "邮件发送失败: $@";
}
exit;

sub send_mail {
    my ($SMTP_HOST, $from, $to_addr, $body, $subject, $msg) = @_;

    $msg = "MIME-Version: 1.0\n"
        . "From: $from\n"
        . "To: " . ( ref($to_addr) ? join(';', @$to_addr) : $to_addr ) . "\n"
        . "Subject: $subject\n\n"  # 双换行分隔邮件头和正文
        . $body;

    my $smtp = Net::SMTP->new( $SMTP_HOST,
        Debug => 0,       # 改为1可开启SMTP调试信息
        Port => 587,
    );

    die("SMTP ERROR: Unable to open smtp session.\n")
        if(!defined($smtp) || !($smtp));

    die("Failed to set FROM address\n")
        if (! ($smtp->mail( $from ) ) );

    die("Failed to set recipient\n") # 修正拼写错误receipient -> recipient
        if (! ($smtp->recipient( ( ref($to_addr) ? @$to_addr : $to_addr ) ) ) );

    $smtp->data( $msg );
    $smtp->quit;
}

关键修改说明

  1. 添加HTTP响应头:脚本开头先输出Content-Type: text/plain\n\n,满足CGI规范要求
  2. 异常捕获:用eval包裹邮件发送逻辑,捕获die抛出的异常,统一输出带HTTP头的错误信息
  3. 启用警告:取消use warnings;的注释,便于发现脚本中的语法或逻辑隐患
  4. 拼写修正:修复send_mail子程序中的拼写错误receipient改为recipient

额外排查方向

  • 命令行直接执行脚本:./test3.cgi,查看输出是否包含HTTP头和预期内容,排查脚本本身的执行错误
  • 验证模块依赖:执行perl -MNet::SMTP -e 1,无报错则表示Net::SMTP模块已正确安装
  • 查看系统日志:检查/var/log/messages等系统日志,确认是否有Perl执行相关的权限或路径错误

内容的提问来源于stack exchange,提问作者Michael

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 19:55:15