Laravel + mailgun でメルマガを一気に全員へ送信する

こんにちは❗フリーランス・コンサルタント&エンジニアの 九保すこひ です。

さてさて、私は過去に(鳴かず飛ばず)の個人サイトを開発したことがあるのですが、その中で何度も「うーん、スペックが低いサーバーでそれやって大丈夫かな…」と思うことがありました。

それは・・・・・・・

メルマガの送信

です。

メルマガといえば、毎月「こんな機能を追加しましたよ」とか、「キャンペーンやってるよ👍」というような情報を(拒否されてなければ)登録ユーザー全員に送信することになります。

つまり、大量のメールを送信することになるわけですが、全く同じ文面というわけではなく「●● さんへ」というように名前を入れたい場合は、1件ずつ送信しないといけません。

そうなると、「サーバーの負荷的に大丈夫かな…」となっていたんですね。

そこで❗

今回はこの「メルマガ送信」をLaravelの公式ドキュメントでも紹介されているmailgunを使って一気に送信する方法をご紹介します。

ぜひ何かの参考になりましたら嬉しいです。😄✨


「姪っ子に『大きくなったね』
と言ったら、逆に(ビール腹が)
大きくなったねと言われました。
一緒に成長しよう…😂」

開発環境: Laravel 9.x

前提として

今回は登録ユーザーにメルマガを送信する機能ですので、Laravelにログイン機能がインストールされていることが前提です。

もしまだの方は以下を参考にしてインストールしておいてください。

📝 参考URL: Laravel Breezeで「シンプルな」ログイン機能をインストール

また、後で利用することになるメーリングリストには独自ドメインが必要(DNS設定とかもします)ですのでご注意ください。

では、今回も楽しくやっていきましょう❗

mailgun での作業

ユーザー登録をする

では、まず mailgun にユーザー登録します。
トップページ右上にあるGet Startedボタンをクリックしてください。

登録フォームが表示されるので、必要な項目を入力(チェック)し、「Create Account」ボタンをクリックします。

なお、入力内容の詳細は以下のとおりです。

  • Full Name: 姓名
  • Company: 会社名
  • Work Email: メールアドレス
  • Password: パスワード
  • Password Confirmation: パスワード(確認)
  • Add payment info now: クレジットカード情報(※1)
  • I’m not a bot: チェックを入れる

※1)私の場合、めんどうなのでチェックを外して登録しましたが、そうすると独自ドメインの登録ができないので、先にクレジット情報をいれておいた方がいいかもです。なお、クレジットカードの登録は「おまけ:クレジットカード情報の登録」をご覧ください。

すると、本人確認用の電話番号を聞かれるので入力し、「Send Verification Code」ボタンをクリック。

ページ移動すると同時にショートメッセージで認証コードを送信してくれるので、そのコードを入力して「Validate」ボタンをクリックしてください。

これで仮登録が完了します。

なお、入力したメールアドレスにも本人確認用のボタンがありますので、クリックしておきましょう。

これでアカウントの登録は完了です。

独自ドメインを登録する

初期状態で振り分けられることになるサブドメイン「sandbox********.mailgun.org」は事前に登録したメールアドレスにしか送信ができません。そして、その影響でメーリングリストが使えませんでした(認証メールを受信できないため)

そのため、独自ドメインを先に登録しておきます。

まず、画面左側メニューから「Sending > Domains」へ移動します。

ページ移動した先にある、ページ右側の「Add New Domain」をクリック。

フォームが表示されるので、ドメイン名(例: mailinglist.example.com)を入力し、「Add Domain」ボタンをクリックします。

すると、ドメインが登録されると同時に設定情報が表示されるので、その情報を元にDNS設定を行ってください。(送信のみの場合、TXTレコードのみでOKです)

※ 本当は複雑すぎるのでDNS設定は省略したかったのですが、どうしてもmailgunの仕様上必須となってしまいました。(ビギナーにはムズすぎですよね…😫 ギャー)

ちなみに私の場合は以下のような設定で登録しました。

mx mailinglist.******.*****. 10
a mailinglist (ここにIPアドレス)
txt mailinglist (ここに表示された値)
txt smtp._domainkey.mailinglist (ここに表示された値)

DNS設定が完了したら、ページ下部にある「Verify DNS settings」ボタンをクリックします。

もしページ移動し、「Sending > Domains」をチェックして以下のようにチェックマークがついていれば認証は完了しています。(完了メールも届きます)

では、認証できたら、.envにそのドメインを登録しておきましょう。

.env

MAILGUN_DOMAIN="************************"

# サンプル例
# MAILGUN_DOMAIN="mailinglist.example.com"

APIキーを取得する

続いて、APIアクセスに必要な情報を取得しておきましょう。
ページ右上にあるアカウント情報をクリックすると、ポップアップが表示されるので、その中から「API Keys」をクリックします。

すると、APIの情報が表示されます。

Private API key」が秘密鍵になりますのでLaravel.envへ登録しておきましょう。

.env

MAILGUN_SECRET="*****************************************"

メーリングリストをつくる

今回は大量のメールを一気に送信する必要があります。

もちろん、ユーザー数が少ないうちは1件ずつメール送信してもいいのでしょうが、数が多くなってくると、もしPHPが途中で止まってしまうとどこまで送信済みかわからなくなってしまいます。

そこで便利なのがmailgunが提供する「メーリングリスト」です。
つまり、送信先のメールアドレスをmailgun側へ事前登録しておくわけです。

こうすることで、1件ずつ送信しなくても一気に大量のメルマガを送信することができるというわけですね。

ということで、まずはmailgunで専用の「メーリングリスト」をつくります。
ページ左メニューから「Sending > Mailing lists」へ移動してください。

すると、今度はページ右上に「Create mailing list」というボタンがあるのでこれをクリックします。

メーリングリストの詳細を入力するフォームが表示されるので、以下のように適宜入力して「Add mailing list」ボタンをクリックしてください。(ご注意:ドメインは先ほど登録した独自ドメインにしてください。mailgunが用意してくれているサブドメインではうまくいきません)

すると、完了ページが表示されるのでここに表示されている「Alias address」を.envへ登録しておきます。

.env

MAILGUN_MAILINGLIST_ADDRESS="******************************"

なお、せっかく初期状態でconfig/services.phpmailgunの項目が用意されているので、そちらにも登録しておきましょう。

'mailgun' => [
    'domain' => env('MAILGUN_DOMAIN'),
    'secret' => env('MAILGUN_SECRET'),
    'endpoint' => env('MAILGUN_ENDPOINT', 'api.mailgun.net'),
    'mailinglist_address' => env('MAILGUN_MAILINGLIST_ADDRESS'), // 👈 ここを追加しました
],

メルマガのテンプレートをつくる

次に、送信するメルマガの中身をテンプレートでつくりましょう。

まず、テンプレートはドメインごとに登録することになるので、先ほど登録したドメインが選択されているか確認します。(ページ上部にあります)

mailgunのメニューから「Sending > Templates」へ移動してください。

すると、ページ右上に以下のボタンがありますので、これをクリックします。

メールテンプレートを選択するポップアップが表示されるので、好きなテンプレートを選択します。(今回はBlankにしました)

選択すると、詳細を入力するフォームが表示されるので以下のようにセットして、「Create and start coding」ボタンをクリックしてください。

ちなみに、本文の中身は以下のとおりです。

<b>%recipient_name%</b> さん、こんにちは。<br><br>

現在、ユーザー感謝祭をやっています。<br>
%recipient.name% さん専用ページは以下になります。<br><br>

クーポンコードは「<b>{{coupon_code}}</b>」です。<br><br>

<a href="https://exmaple.com/thanksgiving/user/%recipient.id%">感謝祭専用ページ</a><br><br>

ぜひお越しください!

この中には、「置き換えパターン」が2つありますが、その内容は以下のとおりです。

  • {{*****}} ・・・ 送信時にセットする値。例えばクーポンコードとかです。
  • %*****% ・・・ ユーザーごとの値。例えばユーザーIDなどで、これはメーリングリストからデータを取得することになります。

詳しいテンプレートの置き換えはこちらのページの「Template Variables」をご覧ください。

そして、登録が完了すると以下のようになります。

(長かったですが😅)これでmailgunでの設定は完了です❗

パッケージをインストールする

では、ここからLaravelを使っての作業になりますので、先にmailgunが提供しているPHPパッケージをインストールしておきましょう。

以下のコマンドを実行してください。

composer require mailgun/mailgun-php

これで、mailgunのライブラリが使えるようになりました。

メーリングリスト更新を自動化するためのイベントをつくる

では、先ほどつくったメーリングリストを自動更新するための機能をつくります。タイミングは以下の2つです。

  • ユーザー登録された: メーリングリストに登録
  • ユーザーが退会した: メーリングリストから削除

※ 本来はオプトイン・オプトアウト(メール送っていいよ or ダメ)したとき、またメールアドレスが変更された時にも同様にメーリングリスト操作をすべきですが、今回は省略します。オプトイン・オプトアウトについての詳細は以下のURLをご覧ください。

📝参考URL:【Laravel】オプトイン/オプトアウトのメール送信機能

では、以下のコマンドを実行してください。

php artisan make:event UserCreated
php artisan make:event UserDeleted

すると、イベント用のファイルが2つ作成されるので中身をそれぞれ以下のようにします。

app/Events/UserCreated.php

// 省略

use App\Models\User;
use Mailgun\Mailgun;

class UserCreated
{
    // 省略

    public function __construct(User $user)
    {
        $api_key = config('services.mailgun.secret');
        $mailing_list_address = config('services.mailgun.mailinglist_address');
        $client = Mailgun::create($api_key);

        $vars = $user->only('id', 'name'); // ユーザーの追加情報
        $client->mailingList()->member()->create(
            $mailing_list_address,
            $user->email,
            $user->name,
            $vars
        );
    }

    // 省略
}

app/Events/UserDeleted.php

// 省略

use App\Models\User;
use Mailgun\Mailgun;

class UserDeleted
{
    // 省略

    public function __construct(User $user)
    {
        $api_key = config('services.mailgun.secret');
        $mailing_list_address = config('services.mailgun.mailinglist_address');
        $client = Mailgun::create($api_key);

        $client->mailingList()->member()->delete(
            $mailing_list_address,
            $user->email,
        );
    }

    // 省略
}

では、この2つのイベントをUserモデルへ登録します。

app/Models/User.php

// 省略

use App\Events\UserCreated;
use App\Events\UserDeleted;

class User extends Authenticatable
{
    // 省略

    protected $dispatchesEvents = [
        'created' => UserCreated::class,
        'deleted' => UserDeleted::class,
    ];
}

これで、「ユーザー登録された」もしくは「ユーザーが削除された」時に自動でmailgunへアクセスしてメーリングリストの更新をしてくれます。

メルマガを一気に送信する部分をつくる

では、今回はひとつずつユーザー登録するのはめんどうですので、ユニットテストを使って送信テストできるようにしてみましょう。

以下のコマンドを実行してください。

php artisan make:test MailgunTest

すると、テスト実行用のファイルが作成されるので、中身を次のように変更します。

テストする内容は以下の3つです。

  • ユーザー登録したら、メーリングリストに登録されるかどうか
  • メルマガ送信が実行できるか
  • ユーザーを削除したら、メーリングリストからも削除されるかどうか

tests/Feature/MailgunTest.php

<?php

namespace Tests\Feature;

use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Foundation\Testing\WithFaker;
use Illuminate\Support\Facades\Hash;
use Mailgun\Exception\HttpClientException;
use Mailgun\Mailgun;
use Tests\TestCase;

class MailgunTest extends TestCase
{
    protected function setUp(): void
    {
        parent::setUp();

        $api_key = config('services.mailgun.secret');
        $this->client = Mailgun::create($api_key);

        // ご注意: 実際にメール送信されます!
        $this->test_users = [
            ['email' => 'taro.yamada@example.com', 'name' => '山田太郎'],
            ['email' => 'jiro.sato@example.com', 'name' => '佐藤二郎'],
            ['email' => 'saburo.tanaka@example.com', 'name' => '田中三郎'],
        ];
    }

    public function test_can_add_member()
    {
        foreach ($this->test_users as $test_user) {

            $email = $test_user['email'];
            $name = $test_user['name'];

            $user = new User();
            $user->email = $email;
            $user->name = $name;
            $user->password = Hash::make('password');
            $user->save();

            $member = $this->getMailingListMember($email);
            $member_email_address = $member->getMember()->getAddress();
            $this->assertEquals($email, $member_email_address);

        }
    }

    public function test_can_send_mail()
    {
        $mailing_list_address = config('services.mailgun.mailinglist_address');
        $template = 'newsletter_2022_05'; // テンプレート名
        $domain = config('services.mailgun.domain');
        $params = [
            'from' => 'from@example.com',
            'to' => $mailing_list_address,
            'subject' => 'メルマガ送信のテスト',
            'template' => $template,
            'h:X-Mailgun-Variables' => json_encode([ // 追加データ
                'coupon_code' => 'ABC-123',
            ])
        ];

        $result = $this->client->messages()->send($domain, $params);
        $id = $result->getId();

        $this->assertNotEmpty($id);
    }

    public function test_can_remove_member()
    {
        foreach ($this->test_users as $test_user) {

            $email = $test_user['email'];

            $user = User::where('email', $email)->first();
            $user->delete();

            $exists = true;

            try {

                $this->getMailingListMember($email); // メンバーが存在していない場合は例外が発生する

            } catch (HttpClientException $e) {

                $exists = false;

            }

            $this->assertFalse($exists);

        }
    }

    private function getMailingListMember($email)
    {
        $mailing_list_address = config('services.mailgun.mailinglist_address');

        return $this->client
            ->mailingList()
            ->member()
            ->show($mailing_list_address, $email);
    }
}

※ ご注意: mailgunの処理スピードの関係で、先にメーリングリストから削除された場合、待機中の送信は取り消しになります(つまり、メール送信されません)そのため、実際にはsleep()などで少し時間を待った方がいいかもしれません。

おまけ:クレジットカード情報の登録

記事の途中でも書きましたが、mailgunへの登録はクレジットカード情報がなくてもできます。ただ、その状態では独自ドメインが登録できない(結果として、メーリングリストを使って送信できない)状態になってしまいます。

そこで、ここではクレジットカード情報の登録方法をご紹介します。(すでに登録時に済ませている方は不要です)

まず、ダッシュボードへ移動するとページ上部に「Upgrade」というボタンがあるのでこれをクリックします。

そして、ページ移動した先で、「Upgrade」ボタンをクリック。

クレジットカードを登録するフォームが表示されるので、以下を参考にして入力し、「Upgrade」ボタンをクリックしてください。

  • Cardholder name: カードの持ち主(例: Taro Yamada)
  • Credit card details: カード番号や CVC(ウラ面に書かれている3〜4ケタ数字)
  • Billing address : カード会社に登録している住所

完了すると、独自ドメインが登録できるようになります。

なお、登録から3ヶ月は5000通までは無料です。(2022.5.10現在)

ちなみに:アカウントは放置しないように!

【追記:2022.8.9】

テスト後アカウントを放置していると、利用していなくても料金を請求されます。(私は、ちょうど本日mailgunから請求がありました😅)

不要な場合はアカウントを削除してしまうのが、確実かと思います。
ご注意ください。m(_ _)m

テストしてみる

では、実際にうまくメルマガが送信できるかチェックしてみましょう❗

では、ひとつずつ処理がうまくいっているかmailgun側でも確認したいので、ユニットテストのメソッドをひとつずつ実行していきます。

では、まずは以下のコマンドで「ユーザー登録時にメーリングリストへ登録されるか」のチェックです。

php artisan test --filter test_can_add_member

実行したら、まずはローカルのDBを見てみましょう。

はい❗うまく登録されています。

では、mailgunのメーリングリストの方はどうでしょうか??

こちらもうまく登録されていますね👍

では、続いて「メーリングリストに登録された人へ実際にメルマガが送信できるか」のチェックしてみます。

以下のコマンドを実行してください。

php artisan test --filter test_can_send_mail

では、登録されたメールアドレスをチェックしてみます。

メルマガは届いているでしょうか・・・・・・

はい❗うまく送信されてきました。
では、中身はどうでしょうか。

こちらも想定していた文章になっています。(名前とクーポンコードが置き換わっていることに注目してください)

では、念のためもう一つのメッセージも確認しておきましょう!

はい❗こちらも想定通りになりました。

では、最後に「メーリングリストに登録したユーザーが削除できるか」のチェックをしてみましょう。

以下のコマンドを実行してください。

php artisan test --filter test_can_remove_member

では、メーリングリストのページをリロードして確認してみます。

どうなるでしょうか・・・・・・

はい❗メンバーが削除されています。
では、DBの方も確認しておきましょう。

全て成功です😄👍✨

企業様へのご提案

mailgunを利用すると、メルマガの送信が一度に送信できるようになります。

しかも、名前やユーザーIDなどを個別に入れ替えた内容にできるため、「誕生日を利用した販促」や逆に「最近ログインしていないユーザーへのお伺い」のメッセージを送信し、より購入率や成約率を高めることに役立つでしょう。

また、クーポンコードに期限をつけて限定感を出し、ユーザーの購買意欲を高めるといったキャンペーンを開催することができます。

さらに、mailgunにはシンプルに「オプトイン/オプトアウト」の機能もついていますので、ルールに則った運営もしやすいです。

もしこういった機能をご希望でしたら、ぜひお問い合わせからご連絡ください。
お待ちしております。😄✨

おわりに

ということで、今回は「Laravel + mailgunでメルマガを一気に送信する」機能をつくってみました。

正直なところ、最初は「そこまで難しくないでしょー😉」ぐらい軽く考えていたのですが、サンドボックスのサブドメインを使うとメーリングリストが有効にできないなど、なかなか紆余曲折があり大変でした(笑)

しかも、今回は画像も多く使っているので、その作業も途中邪魔くさくなる瞬間もありました😫

例えて言うなら、「牛丼並」を食べるつもりが、実際は「特盛5杯 with 卵 + 味噌汁 + サラダ」がでてきた、みたいな印象です。ということで、いまのところmailgunはお腹いっぱいです。

でもすぐお腹減るので、その時はまた別の機能もつくってみようかな。
ぜひ皆さんもやってみてくださいね。

ではでは〜❗

「ユニットテストで、PASS
って表示されるの
快感ですよね??」

開発のご依頼お待ちしております 😊✨
開発のご依頼はこちらから: お問い合わせ
どうぞよろしくお願いいたします!
このエントリーをはてなブックマークに追加       follow us in feedly  

開発効率を上げるための機材・まとめ