0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

PHPMailer + SMTPリレー vs blastengine PHP SDK 徹底比較

Last updated at Posted at 2025-09-30

blastengineでは、SMTPリレー経由と公式PHP SDK経由の両方をサポートしています。
しかし、実際のところ「SMTPで送るのと、APIで送るのとで何が違うのか?」をコードレベルで検証した記事はあまり見かけません。本記事では 同じ blastengine を使う前提で、

  • PHPMailer + SMTPリレー
  • blastengine PHP SDK(API直叩き)

の2方式を並べて実装し、ログの内容・エラーハンドリング・Webhook連携・パフォーマンスの観点から比較しました。

単に「どちらが速いか」だけでなく、実装体験や運用性の差を具体的なスクリプトとログを交えて紹介していきます。

前提環境と比較条件

  • PHP 8.3.6 / Composer 2.7.1 を使用。composer.json では phpmailer/phpmailerblastengine/blastenginevlucas/phpdotenv を依存として追加。
  • プロジェクトルートに置いた .env で共通設定を管理。送信元 (FROM_ADDR)、送信先 (TO_ADDR)、blastengine のユーザーIDとAPIキー、SMTPリレーのホスト・認証情報を読み込み。
  • 検証は実運用アカウントを使わずテスト用宛先で実施。大量送信と誤認されないよう、SMTP/SDK それぞれ 3〜5 回程度の計測。

実装方法の違い

PHPMailer + blastengine SMTP リレー

scripts/send_with_phpmailer.php では PHPMailer を使い、blastengine の SMTP リレーへ TLS で接続して送信します。

<?php
declare(strict_types=1);
require __DIR__ . '/../src/bootstrap.php';

use PHPMailer\PHPMailer\Exception as PHPMailerException;
use PHPMailer\PHPMailer\PHPMailer;

$mail = new PHPMailer(true);
$mail->isSMTP();
$mail->Host       = env_optional('SMTP_HOST', 'smtp.engn.jp');
$mail->Port       = (int) env_optional('SMTP_PORT', '587');
$mail->SMTPAuth   = true;
$mail->Username   = env_optional('SMTP_USER', env_string('BE_ID'));
$mail->Password   = env_optional('SMTP_PASS', env_string('BE_PASS'));
$mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;

$mail->setFrom(env_string('FROM_ADDR'), 'SMTP Relay Example');
$mail->addAddress(env_string('TO_ADDR'));
$mail->Subject = 'PHPMailer + blastengine SMTP test';
$mail->isHTML(true);
$mail->Body    = '<p>こんにちは、blastengineのSMTPリレー経由で送信したテストメールです。</p>';
$mail->AltBody = 'こんにちは、blastengineのSMTPリレー経由で送信したテストメールです。';
$mail->send();
  • SMTP_DEBUG_LEVEL=2 を指定すると EHLO/STARTTLS/認証/データ送信の全ログを [SMTP][レベル] 形式でテキスト保存できます。
  • SMTPプロトコルの仕様上、接続確立から DATA 応答まで複数のラウンドトリップが発生し、delivery_id といったメタ情報はレスポンスに含まれません。

blastengine PHP SDK

scripts/send_with_sdk.php は blastengine のトランザクションAPIを直接呼び出します。

<?php
declare(strict_types=1);
require __DIR__ . '/../src/bootstrap.php';

use Blastengine\Client;
use Blastengine\Transaction;

Client::initialize(env_string('BE_ID'), env_string('BE_API_KEY'));

$transaction = (new Transaction())
    ->from(env_string('FROM_ADDR'), 'SDK Example')
    ->to(env_string('TO_ADDR'))
    ->subject('blastengine PHP SDK test')
    ->text_part('こんにちは。これはblastengine PHP SDKで送信したテストメールです。')
    ->html_part('<p>こんにちは。</p><p>これはAPI経由で送信したテストメールです。</p>');

if ($name = env_optional('PERSONAL_NAME')) {
    $transaction->insert_code('customer_name', $name);
}

$transaction->send();
  • 送信完了後は delivery_id を取得可能。SDK_FETCH_STATUS=1 を指定すると /deliveries/{delivery_id} を呼び、配信ステータスを JSON 形式でログに残せます。
  • Webhook 等の周辺機能はこの API レイヤーから設定・取得するため、SDK を使うと配信状況の自動取得が組み込みやすいです。

送信結果と挙動の比較

項目 PHPMailer + SMTP blastengine PHP SDK
ログに残る情報 SMTPのやり取りがそのまま表示され、EHLOSTARTTLSAUTHDATA といったコマンド応答のみ確認できる API呼び出し結果として delivery_id が返り、さらに {"status":"SENT", ...} のような配信ステータスを含むJSONレスポンスを直接確認できる
エラーハンドリング サーバーから返る「550」などのSMTPステータスコードをアプリ側で解釈し、どのエラーなのかを判断する必要がある SDKが例外を投げ、エラー内容がJSON形式で返却されるため「認証エラー」「宛先不明」などをコード上で判別しやすい
差し込み(パーソナライズ) メール本文に変数を埋め込む場合、自前でMIME本文を組み立てて文字列置換する必要がある insert_code メソッドでプレースホルダに値を渡すだけで差し込みが可能になり、個別宛先ごとのパーソナライズが簡単に実装できる

以下が実際に返却されるSMTPログです。

SMTPログ(抜粋)
[2025-09-26T19:31:52+00:00] Starting PHPMailer SMTP send
[2025-09-26T19:31:52+00:00] [SMTP][2] SERVER -> CLIENT: 220 smtp.engn.jp blastengine SMTP Server
[2025-09-26T19:31:52+00:00] [SMTP][1] CLIENT -> SERVER: EHLO level
[2025-09-26T19:31:52+00:00] [SMTP][2] SERVER -> CLIENT: 250-smtp.engn.jp Hello level 
...
[2025-09-26T19:31:52+00:00] [SMTP][2] SERVER -> CLIENT: 221 2.0.0 smtp.engn.jp Service closing transmission channel
[2025-09-26T19:31:52+00:00] PHPMailer send completed successfully

以下は実際に返されるSDKのログです。

SDKログ
[2025-09-26T19:31:57+00:00] Starting blastengine SDK transaction send
[2025-09-26T19:31:57+00:00] SDK send completed successfully with delivery_id=83
[2025-09-26T19:31:57+00:00] [SDK] Status fetched: {"delivery_type":"TRANSACTION","status":"SENT","sent_count":0,"open_count":0,"created_time":"2025-09-27T04:31:57+09:00","updated_time":"2025-09-27T04:31:57+09:00"}

SMTPは送信成功の可否しか分からないのに対し、SDKでは delivery_id や配信状況を即座に把握できる点が大きなメリットです。

Webhook連携の有無

  • PHPMailer + SMTPリレー: SMTP プロトコルには配信結果を返す仕組みがなく、Webhook 連携も不可。配信失敗の推測は受信サーバーからのバウンスメール頼り。

  • blastengine PHP SDK: 管理画面から Webhook URL を登録し、delivery_id をキーにリクエスト・レスポンス双方で配信結果を突き合わせられる。今回のサンプルでは差し込みコードのみだが、Webhook 受信スクリプトを追加すれば配信完了・bounce、エラーなどを自動で収集、モニタリングできる。

パフォーマンスの違い

両者を数回連続で送信し、オーバーヘッドの時間を記録するベンチマークスクリプトを作成しました。

スクリプト概要

PHPMailerとSDKのそれぞれの送信処理を関数化し、以下の計測ラッパーに入れて測定します。

計測ラッパー
$measure = static function (callable $fn): array {
    $start = microtime(true);
    try {
        $meta = $fn();
        $duration = (microtime(true) - $start) * 1000.0;
        return ['status' => 'success', 'duration_ms' => $duration, 'meta' => $meta];
    } catch (\Throwable $e) {
        return ['status' => 'error', 'duration_ms' => (microtime(true)-$start)*1000.0];
    }
};

以下のようにループさせ、複数回の平均値を取ります。

ループとログ出力
for ($i = 1; $i <= $iterations; $i++) {
    $phpResult = $measure(fn() => $sendWithPHPMailer($from, $to));
    $sdkResult = $measure(fn() => $sendWithSdk($from, $to));
    printf("Iter %d: SMTP %.2f ms / SDK %.2f ms\n",
        $i, $phpResult['duration_ms'], $sdkResult['duration_ms']);
}

送信処理部分は以下の通りです。

送信関数
/**
 * @return array<string, mixed>
 */
$sendWithPHPMailer = static function (string $from, string $to) {
    $mail = new PHPMailer(true);
    $mail->isSMTP();
    $mail->Host = env_optional('SMTP_HOST', 'smtp.engn.jp');
    $mail->Port = (int) env_optional('SMTP_PORT', '587');
    $mail->SMTPAuth = true;
    $mail->Username = env_optional('SMTP_USER', env_string('BE_ID'));
    $mail->Password = env_optional('SMTP_PASS', env_string('BE_PASS'));
    $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
    $mail->CharSet = 'UTF-8';

    $mail->setFrom($from, 'SMTP Relay Example');
    $mail->addAddress($to);

    $mail->Subject = 'PHPMailer benchmark test';
    $mail->isHTML(true);
    $mail->Body = '<p>Benchmark message from PHPMailer.</p>';
    $mail->AltBody = 'Benchmark message from PHPMailer.';

    $mail->send();
    return [];
};

/**
 * @return array<string, mixed>
 */
$sendWithSdk = static function (string $from, string $to) {
    $transaction = (new Transaction())
        ->from($from, 'SDK Example')
        ->to($to)
        ->subject('SDK benchmark test')
        ->text_part('Benchmark message from SDK.')
        ->html_part('<p>Benchmark message from SDK.</p>');

    $transaction->send();
    return ['delivery_id' => $transaction->delivery_id()];
};

計測結果

方式 平均時間 (ms) 最小 (ms) 最大 (ms)
PHPMailer + SMTP 475.67 451.19 499.59
blastengine PHP SDK 200.96 193.62 212.21
  • SMTP は接続確立・TLS 交渉・DATA コマンドまで複数ラウンドトリップが必要で、1通あたり約 0.48 秒のオーバーヘッドが発生しました。
  • SDK は HTTPS の単一リクエストに収まるため 0.2 秒前後で完了。delivery_id を返す API にステータス問い合わせを追加しても、同一セッション内で完結できます。
  • 大量配信時は SMTP 側でコネクション再利用を行っても帯域上限やセッション制限によりボトルネックになりやすいです。一方 SDK は並列リクエストや非同期処理を設計しやすいです。

運用上のメリット・デメリット

観点 PHPMailer + SMTP blastengine PHP SDK
導入コスト 既存の SMTP ライブラリを流用でき、環境変数だけでセットアップ可能 ComposerでSDK導入とAPIキー管理が必要
配信結果の可視化 送信ログのみ。配信失敗はバウンス解析が必須 delivery_id とステータスをAPI/Webhookで取得可能
スケール 1リクエスト=1セッション。大量配信はキューや接続再利用が課題 HTTPベースで並列化・リトライ制御が容易
既存資産との親和性 既存フォームの mail() 置き換えなど小規模用途に適合 周辺システム(CRM/MA)とのデータ連携に強み
メール内容の柔軟性 MIME組み立てが自由な反面メンテナンス負荷大 SDKに沿ったメソッドで差し込み・添付を扱える

まとめと推奨シナリオ

  • 小規模サイトや問い合わせフォーム程度で「とりあえず blastengine の SMTP を使いたい」場合は PHPMailer で十分です。既存コードをほぼ変えずに TLS/認証を設定できます。
  • 配信結果の追跡、Webhook連携、配信IDによるレポート連携が必要になった時点で SDK を導入すると、配送ステータスや差し込みコードを活用したパーソナライズがスムーズです。
  • 本検証では1通あたりの処理時間が SMTP ≒ 0.48 秒、SDK ≒ 0.20 秒と約 2.4 倍の差が出ました。大量配信やバッチ処理を想定するなら初期から SDK を中心に設計するのが望ましいでしょう。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?