Menu

BLOG ベアメールブログ

PHPMailerでメールを送信する方法

このシリーズでは、色々なプログラムでメールを送る方法を紹介していきます。 今回はPHPでメールを送る方法として、PHPMailerの使い方を紹介します。

環境情報

本記事では、メールサーバとは別のサーバでプログラムを実行します。
メールサーバに接続可能でプログラムが実行できる環境であれば、クライアントPCやメールサーバと同一環境でも問題ありません。

プログラムを実行可能なサーバやクライアントPC

実行環境のOSは「AlmaLinux 8.10」を使用しています。

# cat /etc/redhat-release
AlmaLinux release 8.10 (Cerulean Leopard)

メールサーバ

OSは「AlmaLinux 8.9」、SMTPサーバとして「postfix 3.5.8」を使用しています。

# cat /etc/redhat-release
AlmaLinux release 8.9 (Midnight Oncilla)

# postconf | grep mail_version
mail_version = 3.5.8
milter_macro_v = $mail_name $mail_version

プログラムの実行環境とメールサーバ間は587ポートで接続し、SMTP AUTHで認証します。

シンプルですが今回の構成を図にするとこんな感じです。

今回の構成図。クライアントPCから、587番ポートでメールサーバに接続する

PHPでメールを送信する場合の選択肢

PHPはHypertext Preprocessorの略で、主にWeb開発に用いられるサーバーサイドスクリプト言語です。HTMLの中に埋め込んで記述することもでき、動的なWEBページを作成することができる強力なツールです。

PHPは、組み込みの関数や外部ライブラリを使用することで、簡単にメールを送信する機能を実装できます。シンプルなスクリプトから本格的なメール配信システムまで、幅広い用途に対応可能です。 PHPでメールを送信する方法としては、以下のような選択肢が考えられます。

mail()関数

PHPに標準で用意されているmail()関数を使って、簡単なメール送信が可能です。

メリット

  • PHPに組み込まれているため、追加のライブラリが不要
  • 基本的なメール送信であれば簡単に実装できる

デメリット

  • サーバー環境(特にsendmailの設定)に依存するため、共有ホスティングでは利用制限がある場合がある
  • SMTP認証や添付ファイルなどの高度な機能に対応していない
  • メールの信頼性やスパムフィルターにかかるリスクが高い

PHPMailerライブラリ

PHPMailerは、PHPでメールを送信するための非常に人気のあるライブラリで、SMTPの設定や認証、添付ファイルの送信など、豊富な機能を提供しています。

メリット

  • SMTP認証や暗号化に対応
  • 添付ファイル、HTMLメール、マルチパートメールなどが簡単に実装可能
  • 高い信頼性と柔軟性

デメリット

  • mail()関数に比べてセットアップが少し複雑

SwiftMailerライブラリ

SwiftMailerもPHPでのメール送信に広く使われているライブラリです。PHPMailerと似た機能を提供し、高度なメール送信が可能です。

メリット

  • 柔軟で高機能な設計
  • 高度なエラーハンドリング
  • 拡張性

デメリット

  • 2021年で開発が終了している

PHPでメールを送信したい場合、組み込みのmail()関数を直接利用するのが最も手軽です。しかし、mail()関数は設定がシステムに依存するため、柔軟性や信頼性の面で課題がある場合もあります。そのため、細かな設定やエラーハンドリングが必要な場合には、SMTPサーバーの利用を前提とした外部ライブラリを利用するのが一般的です。

PHPMailerでメールを送ってみる

今回は複雑なメール送信処理を必要としないため、SMTP認証機能に対応でき、設定もシンプルで分かりやすいPHPMailerを使用したいと思います。

PHPでメールを送るプログラムを作ります。必要なものは下記の3つとなるので、環境に合わせて導入してください。

  • PHP本体
  • composer(ライブラリ管理ツール)
  • PHPMailer(メール送信用ライブラリ)

今回使用するPHPのバージョンは「7.2.24」です。

# php -v
PHP 7.2.24 (cli) (built: Oct 22 2019 08:28:36) ( NTS )

他のバージョンでは実行できない可能性がありますのでご了承下さい。

SMTP設定ファイルの作成

まずはSMTPの接続情報とエンベロープFROM、ヘッダFROMを記載するための設定ファイルを作成します。
値は実際の送信環境に合わせて下さい。

# vi smtp_config.php

※ここから
-------
 'SERVER_HOST_NAME',       // SMTPサーバのホスト名
    'username' => 'USERNAME@DOMAIN',  // SMTPユーザ名
    'password' => 'YOUR_PASSWORD',      // SMTPパスワード
    'port' => 587,                          // SMTPポート番号
    'use_tls' => false,                        // TLS使用有無設定。使用する場合はtrue
    'from_email' => ' HEADER_FROM_ADD ',   // ヘッダーFROMメールアドレス
    'from_name' => 'YOUR_NAME',            // ヘッダーFROM表示名
    'envelope_from' => 'ENVELOPE_FROM_ADD’,    // エンベロープFromメールアドレス
];
?>
-------
※ここまで

PHPのプログラムを作成

続いてPHPのプログラムを作成します。
本記事では「send_mail.php」という名前で作成しますが、お好きな名前で作成してOKです。

# # vi send_mail.php

※ここから
-------
  \n";
    exit(1);
}

$to = $argv[1];
$subject = $argv[2];
$message = $argv[3];

$mail = new PHPMailer(true);

try {
    // デバッグ出力を有効化
    $mail->SMTPDebug = 0;
    $mail->isSMTP();
    $mail->Host       = $config['host'];
    $mail->SMTPAuth   = true;
    $mail->Username   = $config['username'];
    $mail->Password   = $config['password'];

    // TLSの使用判定
    if ($config['use_tls']) {
        $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
    } else {
        $mail->SMTPSecure = '';
    }
    $mail->Port       = $config['port'];

    $mail->setFrom($config['from_email'], $config['from_name']);
    $mail->Sender = $config['envelope_from'];
    $mail->addAddress($to);
                              
    $mail->isHTML(false); 
    $mail->Subject = $subject;
    $mail->Body    = $message;

    $mail->XMailer = ' ';
    $mail->send();
    echo "Message has been sent to $to\n";
} catch (Exception $e) {
    echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}\n";
}
?>
-------
※ここまで


実行

PHPでも引数として「Toアドレス」、「件名」、「メール本文」を末尾に追加するようにしています。 実行例は下記のとおりです。

php send_mail.sh "xxxxxxx@xxx.xxx" "Test Mail From PHP" "PHP"

送信に成功すると、下記のようなメッセージが出力されます。

Message has been sent to xxxxxxx@xxx.xxx

送ったメールを確認すると届いていることが分かります。
こちらも指定したヘッダFromで届いていますね。

テストメールのメールヘッダのスクリーンショット

デバッグモードで実行

送信に失敗してしまった場合、設定ファイルが間違っている可能性があるため「smtp_config.php」の内容を見直して下さい。

また、「send_mail.php」の「$mail->SMTPDebug = 0;」を「$mail->SMTPDebug = 2;」とすることでデバッグモードを有効にできます。

デバッグモードにすることで、出力される内容からどこで失敗しているか分かりやすくなるため、必要に応じて使用してみてください。

正常に実行された場合、デバッグモードだと下記のように出力されます。

# php send_mail.php  "xxxxxxx@xxx.xxx" "Test Mail From PHP" "PHP"
yyyy-mm-dd hh:mm:ss     SERVER -> CLIENT: 220 MAIL_HOST ESMTP Postfix (AlmaLinux)
yyyy-mm-dd hh:mm:ss     SERVER -> CLIENT: 220 MAIL_HOST ESMTP Postfix (AlmaLinux)
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: EHLO YOUR_HOST
yyyy-mm-dd hh:mm:ss     SERVER -> CLIENT: 250-MAIL_HOST
                                          250-PIPELINING
                                          250-SIZE 10240000
                                          250-ETRN
                                          250-AUTH PLAIN LOGIN
                                          250-ENHANCEDSTATUSCODES
                                          250-8BITMIME
                                          250-DSN
                                          250 SMTPUTF8
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: AUTH LOGIN
yyyy-mm-dd hh:mm:ss     SERVER -> CLIENT: 334 VXNlcm5hbWU6
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: [credentials hidden]
yyyy-mm-dd hh:mm:ss     SERVER -> CLIENT: 334 UGFzc3dvcmQ6
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: [credentials hidden]
yyyy-mm-dd hh:mm:ss     SERVER -> CLIENT: 235 2.7.0 Authentication successful
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: MAIL FROM:
yyyy-mm-dd hh:mm:ss     SERVER -> CLIENT: 250 2.1.0 Ok
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: RCPT TO:
yyyy-mm-dd hh:mm:ss     SERVER -> CLIENT: 250 2.1.5 Ok
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: DATA
yyyy-mm-dd hh:mm:ss     SERVER -> CLIENT: 354 End data with .
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: Date: Wed, 21 Aug 2024 07:54:44 +0000
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: To: TO_ADD
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: From: headerfrom Name 
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: Subject: Test Mail from PHP
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: Message-ID: 
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: MIME-Version: 1.0
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: Content-Type: text/plain; charset=iso-8859-1
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER:
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: PHP
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER:
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: .
yyyy-mm-dd hh:mm:ss     SERVER -> CLIENT: 250 2.0.0 Ok: queued as 231078522F62
yyyy-mm-dd hh:mm:ss     CLIENT -> SERVER: QUIT
yyyy-mm-dd hh:mm:ss     SERVER -> CLIENT: 221 2.0.0 Bye


注意事項

今回作成したプログラムではSMTP接続に失敗した場合でもリトライされません。

また、エラー処理も最低限となっておりますので、実際に業務やサービスとして使用される場合は、SMTP接続に失敗した場合のリトライ処理、プログラムの再実行処理、エラー処理やログの生成などのカスタマイズが必要になります。

具体的な利用例

今回はプログラム単体で実行しましたが、PHPはWebサーバーと一緒に使用することで真価を発揮するプログラミング言語です。WEBページから入力情報を受取り、PHPのプログラムに渡すことで問い合わせフォームとして使う、一定の条件で通知メールを送る、といった用途に応用することが出来ます。

PHPMailerは、シンプルなメール送信から、HTMLメール、添付ファイル、SMTP認証などを必要とする高度なメール送信まで幅広く対応できるため、さまざまな場面で利用されています。

以下に、

$mail->isHTML(true)
$mail->Subject =
$mail->Body =

の3つを編集することで使用できる簡単なサンプルを用意しました。
smtp_config.phpで定義した配信情報を使い回す形としているので、別のサーバーやメールアドレスに変更したい場合はsmtp_config.phpを編集する必要があることに注意して下さい。

1. ユーザー登録時の確認メール送信

Webアプリケーションでユーザー登録を行う際に、確認メールを送信してアカウントの有効化を求めることが一般的です。この場合、PHPMailerを使って以下の機能を実現できます。

  • 確認リンク付きのメール:登録時に生成された一意のトークンを含むURLを送信し、ユーザーがリンクをクリックすることでアカウントを有効化。
  • HTMLメールの送信:デザイン性の高いメールテンプレートを利用して、ブランドイメージに沿った確認メールを送信。
<?php
require 'vendor/autoload.php';

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

$config = require 'smtp_config.php';

$to = $argv[1];
$mail = new PHPMailer(true);

try {
    $mail->SMTPDebug = 0;
    $mail->isSMTP();
    $mail->Host       = $config['host'];
    $mail->SMTPAuth   = true;
    $mail->Username   = $config['username'];
    $mail->Password   = $config['password'];

    if ($config['use_tls']) {
        $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
    } else {
        $mail->SMTPSecure = '';
    }
    $mail->Port       = $config['port'];

    $mail->setFrom($config['from_email'], $config['from_name']);
    $mail->Sender = $config['envelope_from'];
    $mail->addAddress($to);

    // ここから下を編集することで様々なメールに対応できます。
    // --------------------------------------------------------

    // HTMLメールを送る場合はtrue
    $mail->isHTML(true);
    
    // 目的に応じたメールタイトルを設定
    $mail->Subject = 'Confirm your registration';

   // bodyにHTMLを記述
    $mail->Body = '
    <html>
        <head>
            <style>
                table {
                    border-collapse: collapse;
                    width: 100%;
                }
                td, th {
                    border: 1px solid #ddd;
                    padding: 8px;
                    text-align: left;
                }
                tr:nth-child(even) {
                    background-color: #f2f2f2;
                }
            </style>
        </head>
        <body>
            <table>
                <tr>
                    <td>こんにちは!</td>
                </tr>
                <tr>
                    <td>ご登録ありがとうございます。</td>
                </tr>
                <tr>
                    <td>下記のリンクをクリックして、ご登録を完了してください。</td>
                </tr>
                <tr>
                    <td>
                        <a href="https://yourwebsite.com/confirm.php?token=' . htmlspecialchars($token, ENT_QUOTES, 'UTF-8') . '">アカウントを有効化する</a>
                    </td>
                </tr>
            </table>
        </body>
    </html>
    ';
// ---------------------------------------------------------------

    $mail->XMailer = ' ';
    $mail->send();
    echo "Message has been sent to $to\n";
} catch (Exception $e) {
    echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}\n";
}
?>
================================


2. パスワードリセットメールの送信

ユーザーがパスワードを忘れた場合、PHPMailerを利用してパスワードリセットのリンクを送信することができます。この場合、セキュリティ上の理由から、リンクには短時間で失効するトークンが含まれます。

  • 一時リンクの送信:リセット用の一時リンクをユーザーに送信し、クリック後に新しいパスワードを設定できるようにする。
  • メール送信の自動化:フォーム入力をもとにして自動でメールが送られるため、運用コストを削減できる。

    // テキストメールとして送信
    $mail->isHTML(false); 
    $mail->Subject = 'Password Reset Request';
    $mail->Body = "Hello,\n\nWe received a request to reset your password. Please use the following link to reset it:\n\n" .
                  "https://yourwebsite.com/reset.php?token=" . urlencode($resetToken) . "\n\n" .
                  "If you did not request this, please ignore this email.\n\nBest regards,\nYour Website Team";
    

まとめ

今回は、PHPのメール送信ライブラリであるPHPMailerを使って、シンプルなメール送信プログラムを作成しました。PHPMailerは、入門者でも比較的容易に扱えるため、メール送信機能を実装したいと考えている方にお勧めです。

今回紹介したプログラムは必要最低限の機能しか持たせていませんが、実際の開発現場では、エラー処理、添付ファイルの対応など、より高度な機能が必要となる場合があります。

SwiftMailer は開発が終了してしまっていますが、PHPMailerの他にもSymfonyなど、様々なメール送信ライブラリやフレームワークが存在しますので、開発規模や要件に合わせて、最適なライブラリを選ぶことが重要です。本記事が参考になれば幸いです。