GmailのSMTPサーバーを利用してLaravel 8でメールを送信する

October 13, 2021
執筆者
Funke Olasupo
寄稿者
Twilio の寄稿者によって表明された意見は彼ら自身のものです
レビュー担当者

GmailのSMTPサーバーを利用してLaravel 8でメールを送信する

この記事はFunke Olasupoこちらで公開した記事(英語)を日本語化したものです。

メール送信は、現代のWebアプリケーションに欠かせない要素になりました。たとえばユーザー登録時、登録の確認時、パスワードのリセット時など、ユーザーとのコミュニケーションに最適な方法です。

そこで、このチュートリアルでは、GmailのSMTPサーバーを利用してLaravelでメールを送信する方法をご紹介します。

必要条件

このチュートリアルを最後まで進めるには、以下の項目が必要です。

概要

状況により、PHPのデフォルトメソッドであるmail()を使用しても、ローカルサーバーでメールが送信されないか、送信することが非常に困難な場合があります。このような状況では、SymfonyのMailerコンポーネントのような専用のメールライブラリを使用することが、現実的な代替手段となります。

また、Laravelが対応しているMailgun、Amazon SES、Postmark、そしてTwilioSendGridなど、メールドライバーのいずれかを利用することも可能です。様々な方法がありますが、このチュートリアルでは、LaravelでGmailのSMTPサーバーを利用してメールを送信する方法を説明します。

以下では、ニュースレターを登録するためのAPIを作成します。ユーザーは、ニュースレターへの登録にあたり、メールアドレスを送信します。すると、そのメールアドレスがデータベースに保存され、「Thank you for subscribing」(ご登録ありがとうございます)というメールが送られます。

GmailのSMTPサーバーを使用するメリット

  • GmailのSMTPサーバーを使用することで、受信者のスパムフォルダにメールが保存されないよう設定できます。
  • GmailのSMTPサーバーは、安定性と信頼できるパフォーマンスから、多くのユーザーがメール通信に使用している有力な選択肢です。

ただし、Googleは無料アカウントにいくつかの制限を課しています。たとえば、1日に送信できるメールの数は最大100通であることなどを認識しておくことが重要です。

Laravelアプリケーションを作成する

Composerか、Composerのグローバル依存関係としてLaravelインストーラーをダウンロードして新規にLaravelアプリケーションを作成できます。このチュートリアルでは、ターミナルで以下のコマンドを実行して、Laravelインストーラーを使用します。

laravel new mail_article

上記のコマンドで、mail_articleという名前の新規ディレクトリに、新しいLaravelアプリケーションが作成されます。次に、新しいプロジェクトディレクトリに移動し、以下のコマンドを実行して、アプリケーションを起動します。

cd mail_article
php artisan serve

デフォルトでは、プロジェクトはlocalhostのポート8000で実行されます。ブラウザでhttp://localhost:8000を入力してアクセスできます。

以下の画像のようなページが表示され、プロジェクトが実行されていることが確認できます。このページが表示されたら、Ctrl + Cで、アプリケーションを停止します。

Laravelのデフォルトのホームページ

GmailのSMTPサーバーの設定を追加する

Laravelではメールの設定をconfig/mail.phpに保存しています。デフォルトではSMTPを使用するように設定されています。ただし、環境変数を格納する.envで必要な情報を提供できるので、config/mail.phpを編集する必要はありません。config/mail.phpは、そこから必要な詳細を取得します。

.envを開き、以下の変数を更新します。

MAIL_DRIVER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=465
MAIL_USERNAME=<あなたのGmailアドレス>
MAIL_PASSWORD=<あなたのGmailパスワード>
MAIL_ENCRYPTION=ssl
MAIL_FROM_NAME=Newsletter

引用符(“や’)またはスペースは、使用しないでください。

Googleアカウントを設定する

これでメールの設定が更新されました。

次にGmailアカウントのセキュリティ設定をします。Gmailにログインし、[Less secure apps](安全性の低いアプリ)ページの[Allow less secure apps:OFF](安全性の低いアプリを許可する:OFF)の右側にあるオプションをオンに切り替えます。

 

これは、デフォルトでは、Gmailが「安全性の低い」アプリにGmailアカウントを使用するためのアクセス権を与えないためです。

重要なのは、この用語の意味を理解することです。「安全性が低い」とは、OAuthのような認証システムを使用して認証情報にアクセスするよりも、基本的に安全性が低いサードパーティ製アプリケーションのクラスを指します。OAuthは、サードパーティのアプリケーションに対し認証情報へのアクセス権を与えるのではなく、特定のサービスに対する権限のみを提供します。

モデルや移行のセットアップ

これで必要な設定変更ができました。次にユーザーをニュースレターに登録するコードを追加します。

まず、以下のコマンドを実行して、モデルとデータベース移行を同時に作成します。

php artisan make:model Subscriber -m

これにより、app/ModelsディレクトリにSubscriber.phpというモデルファイルが作成され、database/migrationsディレクトリに、create_subscriber_table.phpという移行ファイルが作成されます。

以下のコードをファイルの先頭に追加してSubscriber.phpを更新し、モデルの大量アサインを有効にします。

protected $guarded = [];

次に、移行ファイルのup()メソッドを更新し、emailフィールドを以下の例のようにします。

Schema::create('subscribers', function (Blueprint $table) {
    $table->id();
    $table->string('email');
    $table->timestamps();
});

データベース接続を確立する

アプリケーションのデータベースを設定するには、.envで、以下の例と一致するようにプレースホルダーを自分のデータベースの情報に置き換えて、データベース設定を更新します。

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=<データベース名>
DB_USERNAME=<データベースのユーザーネーム>
DB_PASSWORD=<データベースのパスワード>

キャッシュをクリアする必要があるかもしれませんが、必須ではありません。これを行うには、ターミナルで次のコマンドを実行します。

php artisan config:cache

次に、以下のコマンドを実行して、データベースの移行を実行します。

php artisan migrate

Mailableを生成する

Laravelには、Mailableのクラスを利用してメール送信をサポートするさまざまな方法があり、Markdownとプレーンテキストの両方のメールに対応しています。このチュートリアルでは、Markdown Mailableを使用します。

Markdown Mailableには、MarkdownとBladeのテンプレートが一緒に含まれており、あらかじめ組み込まれたUI要素を使い、Laravelからメールメッセージを組み立てることができます。

Mailable(app/Mail/Subscribe.php)とそれに対応する表示テンプレート(resources/views/emails/subscribers.blade.php)を作成するために、以下のArtisanコマンドを実行します。

php artisan make:mail Subscribe --markdown=emails.subscribers

コントローラーを設定する

次に、メールアドレスの保存と、送信されたメールアドレスへの確認メールの送信を管理するロジックを格納するコントローラーを作成する必要があります。コントローラーを作成するには、次のArtisanコマンドを実行します。

php artisan make:controller SubscriberController

このコマンドを実行すると、app/Http/ControllersディレクトリにSubscriberController.phpという新しいファイルが作成されます。この作成されたファイルに、以下のインポートステートメントを追加して、コントローラーが使用するクラスをインポートします。

use App\Mail\Subscribe;
use App\Models\Subscriber;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Mail;
use Illuminate\Support\Facades\Validator;

次に、ビジネスロジックを保持するsubscribe()メソッドを、以下をコピーしてクラス内に定義します。このメソッドは$requestを介してユーザーの入力を受け取ります。

public function subscribe(Request $request) 
{
    $validator = Validator::make($request->all(), [
          'email' => 'required|email|unique:subscribers'
    ]);

    if ($validator->fails()) {
        return new JsonResponse(['success' => false, 'message' => $validator->errors()], 422);
    }  

    $email = $request->all()['email'];
        $subscriber = Subscriber::create([
            'email' => $email
        ]
    ); 

    if ($subscriber) {
        Mail::to($email)->send(new Subscribe($email));
        return new JsonResponse(
            [
                'success' => true, 
                'message' => "Thank you for subscribing to our email, please check your inbox"
            ], 
            200
        );
    }
}

subscribe()メソッドは最初に検証を行います。空のフィールドやランダムなテキストではなく、有効なメールアドレスが送信されていることを検証します。また、そのユーザーがすでに登録していないか、つまりデータベースの登録者のテーブルにそのユーザーがいないかもチェックします。

検証ルールのいずれかに失敗した場合、失敗したルールのエラーメッセージを含むJSONレスポンスが返されます。検証ルールに合格した場合は、データベースに保存されている、提供されたメールアドレスにメールを送信します。

次に、Subscriberモデルのインスタンスを作成し、提供されたメールをcreate()メソッドに渡して、登録者の新規レコードを作成します。

メールアドレスを$email変数でMailableに渡すことで、送信されるメールメッセージ内で返されていることを確認できるようにしています。To()メソッドが受信者のメールアドレスのみを受け取る一方、MailableのSubscribe()ではメールに組み込む必要のあるデータプロパティをすべて受け取ります。

Mailableの作成

Mailableのクラスが、私たちに代わりメールを構築してくれます。その中のbuildメソッドでは、fromviewmarkdownsubject など、他のメソッドを呼び出し、Mailableのさまざまなプロパティを設定できます。

app/Mail/Subscriber.phpを開き、__construct()メソッドを以下のように更新します。

public $email;
  
public function __construct($email)
{
    $this->email = $email;
}

メールに渡すデータがない場合は、__construct()メソッドはそのままにしておきます。

次にbuild()メソッドですが、以下のようにsubject()を呼び出して、メールメッセージに件名を付けます。

public function build()
{
    return $this
        ->subject('Thank you for subscribing to our newsletter')
        ->markdown('emails.subscribers');
}

このメソッドはデフォルトでmarkdown()メソッドを備えており、メールの構成要素を書き込むことができるBladeファイルを指定します。

Markdownメッセージを書く

メッセージのすべてのコンポーネントを含むBladeファイルであるresources/views/emails/subscribers.blade.phpを開き、以下のコードと一致するように更新してください。

注記: これは、Mailableクラスのbuild()メソッド内のmarkdown()メソッドでターゲットとされているBladeファイルです。

@component('mail::message')
# Welcome to the first Newsletter

Dear {{$email}},

We look forward to communicating more with you. For more information visit our blog.

@component('mail::button', ['url' => 'enter your desired url'])
Blog
@endcomponent

Thanks,<br>
{{ config('app.name') }}
@endcomponent


ここではMarkdownとBladeの両方がサポートされています。ただしMarkdownでは、過度のインデントはコードブロックになる可能性があるため、避けてください。ここで作成したいメッセージを構成し、ボタンや表などの各種プロパティを利用できます。Markdown Mailableの詳細については Laravelドキュメントを参照してください。

ルートを設定する

今回構築しているのはAPIのため、routes/api.phpに新しいルートを追加します。定義する必要があるルートは1つのみです。使用するエンドポイントは、ユーザーがメールを送信するために使う/api/subscribe 1つだけだからです。

ルートを定義するには、次のコードをroutes/api.phpに追加します。

Route::post('/subscribe', [SubscriberController::class, 'subscribe']);

次に、インポートステートメントをファイルの先頭に追加します。

use App\Http\Controllers\SubscriberController;

アプリケーションのテスト

いよいよAPIをテストして、すべてが正しく機能していることを確認します。これには、Postmanや、これから使うcURLなど、さまざまな方法があります。

まず、以下のコマンドを実行して、アプリケーションを起動します。

php artisan serve

プロジェクトのルートディレクトリで、<登録者のメールアドレス>を登録するメールアドレスに置き換えて、以下のコマンドを実行します。

curl -X POST -F "email=<登録者のメールアドレス>" http://localhost:8000/api/subscribe 

すべてが想定通りに動けば、以下の例のような出力が表示されます。

{
    "success":true,
    "message":"Thank you for subscribing to our mail, please check your inbox"
}

受信ボックスをチェックすると、メッセージ、送信者情報、メールの件名などが、Laravel UIできれいにフォーマットされたメールが表示されているはずです。

受信したお礼メール

もし、メールアドレスがすでに登録されていることが原因でリクエストが失敗した場合は、以下のような出力が表示されます。

{
    "success":false,
    "message":{
        "email":[
            "The email has already been taken."
        ]
    }
}

まとめ

このチュートリアルでは、LaravelでGmailのSMTPサーバーを使用してメールを送信する方法を紹介しました。Laravelのメールはそれ自体で幅広い内容にわたる概念ですが、このチュートリアルは入門書としてご利用いただけます。さらに詳しい情報は Laravel公式ドキュメントを参照してください。このプロジェクトのコードはオープンソースのため、GitHub上で公開されています。

GmailのSMTPサーバーの統合を体験された方は、LaravelでSMTPリレーとしてSendGridを使用もお試しください。

コーディングを楽しみましょう!

Funkeはテクノロジーが好きで、特にティーンエイジャーや若者の間で持続可能な技術コミュニティを構築し、発展させることに強い関心を寄せています。バックエンドの開発者として、コミュニティの成長に情熱を持ち、個人ブログも含め、数多くのブログで記事を公開しています。

コードを書いたり、技術的なコンテンツを作成したりしていないときは、地元のコミュニティで社会的な問題を解決するための福祉サービスに貢献しています。Funkeへのご連絡には、TwitterGitHubをご利用ください。