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
相关产品推荐
相关产品推荐

