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

CodeIgniter邮件发送错误处理:SMTP服务器重启时实现自动重连并重发邮件

解决CodeIgniter邮件发送中SMTP连接被强制关闭的重试问题

这个errno=10054错误太常见了——说白了就是SMTP服务器突然断开了连接(比如服务器重启、连接超时或者负载过高踢掉了你的连接)。你的原代码没处理这种突发情况,遇到错误就直接卡在当前邮件的失败分支了。咱们可以通过添加重试机制+每次重试时重新初始化邮件实例来解决,因为原来的邮件类实例已经持有失效的连接,必须重新创建新连接才行。

下面是修改后的健壮版代码,我会在后面拆解关键逻辑:

$config = array(
    'protocol' => 'smtp', 
    'smtp_host' => 'example.com', 
    'smtp_port' => 587, 
    'smtp_user' => '******', 
    'smtp_pass' => '***', 
    'priority' => 1, 
    'smtp_timeout' => '30', 
    'mailtype' => 'html', 
    'charset' => 'utf-8', 
    'wordwrap' => true
); 

// 自定义最大重试次数,根据你的需求调整
$maxRetries = 3;
$totalSent = 0;

foreach($res2 as $email) {
    $retryCount = 0;
    $sentSuccessfully = false;
    
    // 循环重试,直到发送成功或用完重试次数
    while ($retryCount < $maxRetries && !$sentSuccessfully) {
        try {
            // 关键1:每次重试都清空并重新初始化邮件类
            $this->email->clear(true); // 清空所有邮件数据+关闭旧连接
            $this->email->initialize($config); // 重新加载配置,创建新SMTP连接
            
            // 组装邮件内容
            $this->email->from($fromemail, $fromname); 
            $this->email->to($email); 
            $this->email->subject('Dummy Email'); 
            $body = $emailDesign2; 
            $this->email->message($body); 
            
            // 关键2:抑制fwrite的警告错误,避免脚本直接终止
            if (@$this->email->send()) { 
                echo "Mail Sent to {$email}<br/>"; 
                $totalSent++;
                $sentSuccessfully = true;
            } else {
                // 获取详细错误信息,方便排查问题
                $errorDetail = $this->email->print_debugger();
                echo "Attempt {$retryCount+1} failed for {$email}: {$errorDetail}<br/>";
                $retryCount++;
                // 重试前加短暂延迟,给服务器恢复时间
                sleep(2);
            }
        } catch (Exception $e) {
            // 捕获极端情况下的异常,让脚本更稳定
            echo "Exception on attempt {$retryCount+1} for {$email}: {$e->getMessage()}<br/>";
            $retryCount++;
            sleep(2);
        }
    }
    
    if (!$sentSuccessfully) {
        echo "All {$maxRetries} attempts failed for {$email}<br/>";
    }
}

echo "Total mails sent: {$totalSent}<br/>";

关键逻辑拆解

  1. $this->email->clear(true):这个方法不仅会清空邮件的收件人、内容等数据,还会关闭当前的SMTP连接(参数true的作用),确保下次初始化是全新的连接,不会复用已经失效的旧连接。
  2. 重新初始化邮件类:每次重试都调用initialize($config),相当于重新和SMTP服务器握手建立新连接,这是解决连接被强制关闭的核心。
  3. 重试循环+延迟:设置maxRetries避免无限重试,每次失败后sleep(2)给服务器一点恢复时间,也避免频繁请求被服务器拉黑。
  4. 错误抑制与日志:用@抑制fwrite的警告(不然可能直接终止脚本),同时通过print_debugger()获取详细错误日志,方便排查是连接问题还是邮件内容本身的问题。

额外小建议

  • 可以开启smtp_keepalive:如果你的邮件列表很长,开启这个能减少频繁建立连接的开销,但遇到服务器重启时还是需要重试机制兜底。
  • 生产环境别用echo输出:建议把日志写到文件里,用CodeIgniter自带的日志类($this->log->write_log())会更规范。
  • 批量发送加间隔:短时间发大量邮件容易被服务器判定为垃圾邮件,循环里可以加个1-2秒的延迟,降低风险。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.29 19:38:12