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

PHP循环调用PHPMailer发邮件仅收到1封的问题排查

PHPMailer循环发送多封邮件仅收到第一封

问题描述

使用PHPMailer向不同收件人发送任务通知邮件,$actions数组包含2个带不同action_owner的子数组,循环遍历调用sendEmail()两次,输出显示收件人正确,但测试邮箱仅收到第一封邮件。

相关代码

调用部分代码

case 'action':
      $actions = $_POST['action']; 
      foreach($actions as $key=>$val){
        $emailParams = [
          'to'      => [$val['action_owner']],
          'bcc'     => ['bcc@email.com'],
          'subject' => _('Subject'),
          'nc_actions'   => $val['nc_actions']
        ];
        // dump($emailParams);
        $test = $mail->sendEmail('nc/action_email', $emailParams);
        // dump($test);
      }
      die;

PHPMailer封装代码

private function generateEmailBody(string $templateFile, array $params)
{
    // error_reporting(0);
    ob_start();
    require_once $_SERVER['DOCUMENT_ROOT'] . '/layouts/emails/header.php';
    require_once $_SERVER['DOCUMENT_ROOT'] . '/layouts/emails/' . $templateFile . '.php';
    require_once $_SERVER['DOCUMENT_ROOT'] . '/layouts/emails/footer.php';
    return ob_get_clean();
}

public function sendEmail(string $templateFile, array $emailParams)
{
    if (empty($emailParams['to']) || empty($emailParams['subject'])) {
        throw new Exception('Missing required parameters for sending email');
    }

    $this->Subject = $emailParams['subject'];
    $this->Body    = $this->generateEmailBody($templateFile, $emailParams);

    foreach ($emailParams['to'] as $to) {
        $this->addAddress($to);

        if (!empty($emailParams['bcc'])) {
            foreach ($emailParams['bcc'] as $bcc) {
                $this->AddBCC($bcc);
            }
        }

        $this->send();
        $this->ClearAllRecipients();
    }
    return true;
}

问题原因

第二次调用sendEmail()时,PHPMailer实例的状态未完全重置。虽然调用了ClearAllRecipients()清除收件人,但消息ID、发送标记等残留状态会导致第二次发送流程异常,最终邮件无法发出。

修复方案

方案1:重置PHPMailer实例状态

修改sendEmail()方法,在每次发送前重置实例的核心状态,避免前一次发送的残留影响:

public function sendEmail(string $templateFile, array $emailParams)
{
    if (empty($emailParams['to']) || empty($emailParams['subject'])) {
        throw new Exception('Missing required parameters for sending email');
    }

    // 重置实例核心状态
    $this->clearAddresses();
    $this->clearBCCs();
    $this->clearCCs();
    $this->clearReplyTos();
    $this->Subject = '';
    $this->Body = '';
    $this->AltBody = '';
    $this->message_id = '';
    $this->sent = false;

    $this->Subject = $emailParams['subject'];
    $this->Body    = $this->generateEmailBody($templateFile, $emailParams);

    foreach ($emailParams['to'] as $to) {
        $this->addAddress($to);

        if (!empty($emailParams['bcc'])) {
            foreach ($emailParams['bcc'] as $bcc) {
                $this->AddBCC($bcc);
            }
        }

        // 发送时捕获错误,便于排查
        if (!$this->send()) {
            error_log('邮件发送失败: ' . $this->ErrorInfo);
        }
        $this->ClearAllRecipients();
    }
    return true;
}

方案2:每次循环创建新的PHPMailer实例

在循环内每次初始化新的PHPMailer实例,彻底避免状态残留:

case 'action':
      $actions = $_POST['action']; 
      foreach($actions as $key=>$val){
        // 每次循环创建新实例并初始化SMTP配置
        $mail = new PHPMailer(true);
        $mail->isSMTP();
        $mail->Host = '你的SMTP服务器地址';
        $mail->SMTPAuth = true;
        $mail->Username = '邮箱账号';
        $mail->Password = '邮箱密码/授权码';
        $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
        $mail->Port = 587;

        $emailParams = [
          'to'      => [$val['action_owner']],
          'bcc'     => ['bcc@email.com'],
          'subject' => _('Subject'),
          'nc_actions'   => $val['nc_actions']
        ];
        $test = $mail->sendEmail('nc/action_email', $emailParams);
      }
      die;

额外建议

  • 始终在发送后记录错误信息,方便快速定位问题
  • 保持PHPMailer版本为最新,避免已知的版本bug

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 04:02:46