PHPのメール送信ライブラリ「PHPMailer」を使っていて、先日ハマったところがあったので記事にまとめておく。

PHPMailerで送信先のアドレスを指定する場合、以下のようにaddAddressメソッドを使用する。(27行目)

<?php
require __DIR__.'/vendor/autoload.php';
require __DIR__.'/conf.php';
use PHPMailer\PHPMailer\PHPMailer; 
use PHPMailer\PHPMailer\Exception;

$Mail = new PHPMailer(true); 

// 基本情報の設定(定数はconf.phpにて定義)
try { 
  $Mail->isSMTP(); 
  $Mail->CharSet = MAIL_CHARSET; 
  $Mail->Host = MAIL_HOST; 
  $Mail->SMTPAuth = true; 
  $Mail->Username = MAIL_USER; 
  $Mail->Password = MAIL_PASSWORD; 
  $Mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; 
  $Mail->Port = SMTP_PORT; 
   
  $Mail->setFrom(MAIL_ADMIN_ADDRESS, MAIL_ADMIN_NAME); 
  $Mail->addReplyTo(MAIL_ADMIN_ADDRESS, MAIL_ADMIN_NAME); 
} catch (Exception $e) { 
  echo $Mail->ErrorInfo; 
}

// 送信先アドレスの指定
$Mail->addAddress('customer@example.com');

$Mail->Subject = '件名'; 
$Mail->Body = '本文'; 
$Mail->send(); 

一つのプログラム内で1度のメール送信しかおこなわないのであれば何の問題もないのだが、例えばユーザー宛、管理者宛に異なるメールを送る場合に不都合が生じる。

以下のように共通の$Mailオブジェクトを使って、一つのプログラム内で複数のメールを送るケースを見てみる。

// ユーザー宛に送信
$Mail->addAddress($customerEmail); 
$Mail->Subject = $subject1; 
$Mail->Body = $body1; 
$Mail->send();

// 管理者宛に送信 
$Mail->addAddress($adminEmail); 
$Mail->Subject = $subject2;  
$Mail->Body = $body2;  
$Mail->send();

この例の場合、2通目の管理者宛に送るべきメールが、先に指定したユーザーのメールアドレスにも届いてしまうのだ。

なぜこのようなことが起きるかというと、addAddressメソッドは送信先アドレスを追加するメソッドなので、前に指定したアドレスが残ったまま送信先アドレスがどんどん追加されていってしまうためだ。

同じオブジェクトを使って複数のメールを送信する場合は、以下のclearAllRecipientsメソッドを使ってクリアしてやる必要がある。

clearAllRecipientsメソッドで送信先情報をクリアする

clearAllRecipientsメソッドは、TO、CC、BCCに割り当てた全ての情報をクリアするメソッドで、先ほどのコードを以下のとおり修正することで、一つのプログラム内で複数のメールを安全に送信することができるようになる。

// ユーザー宛に送信
$Mail->addAddress($customerEmail); 
$Mail->Subject = $subject1; 
$Mail->Body = $body1; 
$Mail->send();

// 送信先情報をクリア
$Mail->clearAllRecipients();

// 管理者宛に送信 
$Mail->addAddress($adminEmail); 
$Mail->Subject = $subject2;  
$Mail->Body = $body2;  
$Mail->send();