PHPMailer 没有将所有电子邮件发送到最后一个电子邮件地址

PHPMailer not sending all emails to last email address

我正在使用 PHPMailer 发送电子邮件。我创建了一个功能,可以向 3 个不同的电子邮件地址发送 3 封电子邮件(总共发送 9 封电子邮件)。

为什么会这样?

这是我的代码:

use PHPMailer\PHPMailer\PHPMailer; 
use PHPMailer\PHPMailer\Exception;

require 'lib/phpmailer/vendor/autoload.php'; 

$mail = new PHPMailer(true);

$mail1 = phpmaileremail($reciever1, $usertype1, $file, $subject1, $body1);
$mail2 = phpmaileremail($reciever2, $usertype2, $file, $subject2, $body2);
$mail3 = phpmaileremail($reciever3, $usertype3, $file, $subject3, $body3);

function phpmaileremail($reciever,$usertype, $file, $subject, $body)
{
    global $mail;
    $mail->SMTPDebug = 0;                                        
    $mail->isSMTP();
    $mail->Host = 'smtp.gmail.com';
    $mail->SMTPAuth = true;
    $mail->Username = 'xxx@gmail.com';
    $mail->Password = 'xxx';
    $mail->SMTPSecure = 'tls';                               
    $mail->Port = 587;   

    $mail->setFrom('xxx', 'xxx');            
    $mail->addAddress($reciever); 
    $mail->addAddress($reciever, $usertype); 

    $mail->addAttachment($file);

    $mail->isHTML(true);                                   
    $mail->Subject = $subject; 
    $mail->Body = $body; 
    $mail->AltBody = 'NA'; 
    $mail->send();

    echo "Mail sent";
}

因为您将 $mail 对象重新用于 addAddress()send()。因此,您第一次致电 phpmaileremail() 时,第一个地址会收到电子邮件。然后,当您第二次调用它时,会添加第二个地址,第一个和第二个地址会收到电子邮件。等等。

一个简单的解决方案是在 phpmaileremail() 函数中创建 $mail 对象:

function phpmaileremail($reciever,$usertype, $file, $emailsubject, $email_body )
{

  $mail = new PHPMailer(true);

  $mail->SMTPDebug = 0;                                        
  $mail->isSMTP();                                             
  $mail->Host       = 'smtp.gmail.com;';                     
  $mail->SMTPAuth   = true;                              
  $mail->Username   = 'XXXXXXXX@gmail.com';                  
  $mail->Password   = 'XXXXXXXXXXXXXXXXXX';                         
  $mail->SMTPSecure = 'tls';                               
  $mail->Port       = 587;   

  $mail->setFrom('XXXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXX');            
  $mail->addAddress($reciever); 
  $mail->addAddress($reciever, $usertype); 
  // Attachments
  $mail->addAttachment($file);         // Add attachments

  $mail->isHTML(true);                                   
  $mail->Subject = $emailsubject; 
  $mail->Body    = $email_body; 
  $mail->AltBody = 'NA'; 
  $mail->send(); 

  echo "Mail sent"; 

}

PS:不重要,但是reciever写成receiver。我也犯过这个错误。

Kiko 的回答会奏效,但这不是最好的方法。顾名思义,addAddress 添加 一个地址,它不会绝对设置或替换您已经添加的现有收件人。

PHPMailer 有一个标准函数来清除您要结束的地址列表,称为 clearAddresses,因此正确的方法是在您发送每条消息后调用它,并在发送下一条消息之前添加新地址一,所以顺序大致是:

addAddress();
send();
clearAddresses();
addAddress();
send();

等等。这在 the mailing list example provided with PHPMailer 中得到了最清楚的证明,它在循环中发送,每次都调用 clearAddresses

您每次都可以使用一个新的 PHPMailer 实例来实现相同的目的(它具有清除地址的效果,但也清除其他所有内容),但重新使用该实例会更有效。如果您通过 SMTP(您是)发送,则尤其如此,因为它允许您使用 keepalive,这会显着减少建立 SMTP 连接的开销。如果您使用新实例,则每次都会断开并重新创建连接。您可以通过将 PHPMailer 实例设置为静态来在函数内部实现此目的:

function phpmaileremail($reciever, $usertype, $file, $emailsubject, $email_body)
{
    static $mail;

    if ($mail === null) {
        //Set everything that remains the same all the time in here
        $mail = new PHPMailer();
        $mail->SMTPDebug = 0;
        $mail->isSMTP();
        $mail->Host = 'smtp.gmail.com;';
        $mail->SMTPAuth = true;
        $mail->Username = 'XXXXXXXX@gmail.com';
        $mail->Password = 'XXXXXXXXXXXXXXXXXX';
        $mail->SMTPSecure = 'tls';
        $mail->Port = 587;
        $mail->SMTPKeepAlive = true;
        $mail->setFrom('XXXXXXXXXXXXXXXX', 'XXXXXXXXXXXXXX');
    }
    $mail->addAddress($reciever, $usertype);
    // Attachments
    $mail->addAttachment($file);         // Add attachments

    $mail->isHTML(true);
    $mail->Subject = $emailsubject;
    $mail->Body = $email_body;
    $mail->AltBody = 'NA';
    $mail->send();
    $mail->clearAddresses();
    $mail->clearAttachments();
    echo "Mail sent";
}

这具有不使用全局变量的额外好处。另请注意 clearAttachments 的使用,因为它的工作方式与地址相同。