前回 のメール編!
Laravelで困るのって、書類発行とメール送信だと思う。
(JobやWebSocketから目をそらして)
1. メール設定
Laravel は標準でメール送信に対応している。
まず、基本設定についてまとめる。
設定中の動作確認は「2. メールの送り方」を参照のこと。
.env 設定値
設定は config/mail.php
と .env
の MAIL_
で始まるキーで定義されている。
MAIL_MAILER=log
MAIL_HOST=127.0.0.1
MAIL_PORT=2525
MAIL_USERNAME=null
MAIL_PASSWORD=null
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS="hello@example.com"
MAIL_FROM_NAME="${APP_NAME}"
MAIL_MAILER
config/mail.php
の mailers
で定義されているドライバ情報を記入する。
基本的には smtp
で良い。
Amazon SES を使うのであれば ses
。
log
にすると、Laravel のログに出力されるので便利。
MAIL_HOST
MAIL_PORT
MAIL_USERNAME
MAIL_PASSWORD
MAIL_ENCRYPTION
接続先の情報。
メール送信に使用するサーバーやサービスの情報を記載する。
sail 環境であれば、mailpit
コンテナを使用する。
MAIL_ENCRYPTION
は tls
ssl
null
の値を取る。
困ったら tls
で動くはず。
適切に設定しないと、エラーで弾かれることが多い。
MAIL_FROM_ADDRESS
MAIL_FROM_NAME
送信元の情報。
基本的には送信に利用するアドレス情報を指定すればよい。
一括して support@xxx
みたいなアドレスを使用したい場合、こちらに記載する。
※ドメインが異なる場合、セキュリティの都合で弾かれることが多い。
ちゃんと存在するアドレスを指定しよう。
一般的なメールサーバーの場合
基本的には、メーラーに設定するSMTP情報を使うことで、メール送信が可能になる。
「Xserver Business」の場合、こちらに記載があった。
使用するアドレスのアカウント情報と合わせて、設定値を作成する。
MAIL_MAILER=smtp
MAIL_HOST="sv***.xbiz.ne.jp"
MAIL_PORT=587
MAIL_USERNAME="xxxxxx@example.com"
MAIL_PASSWORD="xxxxxxxx"
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="xxxxxx@example.com"
MAIL_FROM_NAME="${APP_NAME}"
Gmail の場合 (アプリパスワード)
以前であれば、「一般的なメールサーバーの場合」と同様に設定できたのだが、セキュリティ強化の影響で使用できなくなるみたい...。
https://support.google.com/a/answer/14114704?hl=ja
2024 年秋:
すべての Google アカウントで、安全性の低いアプリへのアクセスが無効になります。
CalDAV、CardDAV、IMAP、SMTP、POP で従来のパスワード(基本認証)を使用できなくなります。(アプリパスワードは例外です)
でもアプリパスワードは使えるみたい!
セキュリティ的には脆弱になるので、安全性を高めるには下の OAuth 認証方式を使おう。
https://myaccount.google.com/security
まず使いたいアカウントの管理画面にアクセスして、「セキュリティ」「二段階認証プロセス」を選択する。
※あらかじめ二段階認証を有効にする必要があります。
ページ下部の「アプリパスワード」を選択する。
任意の名称を付けると、パスワードが生成される。
二度と閲覧できないので記録しよう。
これらの値より、設定値を作成する。
SMTP情報はこちら。
MAIL_MAILER=smtp
MAIL_HOST=smtp.gmail.com
MAIL_PORT=587
MAIL_USERNAME="xxxxxx@gmail.com"
MAIL_PASSWORD="xxxxxxxx"
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="xxxxxx@gmail.com"
MAIL_FROM_NAME="${APP_NAME}"
MAIL_PASSWORD
に先ほど取得したアプリパスワードを記入する。
Gmail の場合 (OAuth)
他の人にお任せする!
この方が分かりやすいかと。
これ!っていうライブラリが無いから紹介しにくい...。
Amazon SES の場合
AWS にて SES のアカウント設定が必要。(割愛)
$ composer require aws/aws-sdk-php
設定値はこんな感じ。
MAIL 設定のほかに AWS の IAM 設定が必要になる。
意外とシンプルに扱える。
AWS_ACCESS_KEY_ID="xxxxxxxx"
AWS_SECRET_ACCESS_KEY="xxxxxxxx"
AWS_DEFAULT_REGION="ap-northeast-1"
MAIL_MAILER=ses
MAIL_FROM_ADDRESS="xxxxxx@example.com"
MAIL_FROM_NAME="${APP_NAME}"
あとは他の人にお任せする!
この方が分かりやすいかと。
2. メールの送り方
一般的にSMTP送信時に行うことは何でもできる。
メールは動作確認が大事なので、送信テスト用コマンドを作っておくと良い。
シンプルにメールを送る
実はドキュメントに乗っていない方法。
というか Model と Blade を使う方法しか載ってない。
ただ送るだけの時に作るの面倒なので、こちらを用意。
use Illuminate\Console\Command;
use Illuminate\Mail\Mailables\Attachment;
use Illuminate\Mail\Message;
use Illuminate\Support\Facades\Mail;
use Symfony\Component\Mime\Address;
Mail::raw('本文です。', function (Message $message) {
$message
->to([
new Address('test@example.com', 'Lara'),
new Address('sub@example.com', 'Vel'),
])
->subject('タイトル')
->attach(
Attachment::fromStorage('red.png')
->as('赤い画像.png')
->withMime('image/png')
);
});
生成されるメール本文はこちら。
From: Laravel <xxxxxxxx@gmail.com>
To: Lara <test@example.com>, Vel <sub@example.com>
Subject: =?utf-8?Q?=E3=82=BF=E3=82=A4=E3=83=88=E3=83=AB?=
MIME-Version: 1.0
Date: Mon, 16 Sep 2024 03:29:33 +0000
Message-ID: <dfca79409fde9d1630bd1fbe206b1925@gmail.com>
Content-Type: multipart/mixed; boundary=tOuA3Ufv
--tOuA3Ufv
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable
本文です。
--tOuA3Ufv
Content-Type: image/png;
name="=?utf-8?Q?=E8=B5=A4=E3=81=84=E7=94=BB=E5=83=8F=2Epng?="
Content-Transfer-Encoding: base64
Content-Disposition: attachment;
name*=utf-8''%E8%B5%A4%E3%81%84%E7%94%BB%E5%83%8F.png;
filename*=utf-8''%E8%B5%A4%E3%81%84%E7%94%BB%E5%83%8F.png
iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACx
jwv8YQUAAAAJcEhZcwAADsEAAA7BAbiRa+0AAAANSURBVBhXY3gro/IfAAVUAi3GPZKdAAAAAElF
TkSuQmCC
--tOuA3Ufv--
詳しい関数はソースを見たほうが早い。
to
cc
bcc
to($address, $name = null, $override = false)
宛先情報の追加。
送信先を Address で作って、配列で指定する。
複数実行した場合、過去の値はそのままに追加される。
文字列指定もできるが、挙動が若干複雑なのでこっちをおすすめ。
Address は Symfony のほうを使う。
(多分 raw の使用は考慮されてない)
※ Address の代わりに User モデルを指定することも可能!
from
(sender
)
from($address, $name = null)
サンプルでは指定していないが、送信元も指定できる。
未指定の場合は .env
で指定した値が使用される。
sender()
は意識する機会あるのかな?
subject
subject($subject)
メールのタイトル。
ちなみに本文は raw()
の第一引数なので注意。
attachment
attach($file, array $options = [])
添付ファイル。
Attachment を使ってファイルを添付することができる。
添付元は fromStorage()
fromStorageDisk()
fromData()
fromPath()
と、必要そうなものは大体用意されている。
ちゃんと設定すれば s3
から直接添付もできるんじゃないかな。
ファイル名未指定時は、元のファイル名がそのまま使われる。
Mime未指定時は、拡張子から勝手に推測されるみたい。(未検証)
いくつか付与したい場合は、何回も呼び出そう。
また zip にしたい場合は、別途 zip ライブラリを使って先に固める必要がある。
Mailable + Blade を使ってメールを送る
メール送信用のテンプレートを作って、それを呼び出す一般的な使い方。
個人的には準備するものが多くなるので、インラインでも良くないか?と思っている。
テンプレートはコマンドで生成可能。
$ php artisan make:mail TestMail
$ php artisan make:view mail/testMailView
<div>
<p>こんにちは! {{ $name }} さん</p>
</div>
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Mail\Mailables\Attachment;
use Illuminate\Mail\Mailables\Content;
use Illuminate\Mail\Mailables\Envelope;
use Illuminate\Queue\SerializesModels;
class TestMail extends Mailable
{
use Queueable, SerializesModels;
public function __construct(protected string $name)
{
//
}
public function envelope(): Envelope
{
return new Envelope(
subject: 'テストメール',
);
}
public function content(): Content
{
return new Content(
view: 'mail.testMailView',
);
}
public function attachments(): array
{
return [
Attachment::fromStorage('red.png')
->as('赤い画像.png')
->withMime('image/png')
];
}
}
使い方。
$res = Mail::to([
new Address('test@example.com', 'Lara'),
new Address('sub@example.com', 'Vel'),
])
->send(new TestMail('たなかさん'));
to などの仕様は Mail::raw()
と同等。
envelope
宛名情報を記録する場所。
基本は subject
のメール件名を記載する場所。
他にも from
や tags
metadata
などが指定可能。
content
本文を記載する場所。
view
モードと markdown
モードに対応している。
text
を指定しておくと、平文メールの際の描画を決められる。
with
に配列を指定することで、bladeファイルに値を渡すことができる。
このテンプレート内部で使用する値は、コンストラクタの引数に渡しておこう。
attachments
添付ファイルを指定するところ。
これは先の説明と同じ。
送信履歴について
送信履歴、送信トレイに、送信メールが保管されるかはメールサーバー次第。
基本的には履歴は残らないと思った方が良い。
送信時の戻り値をDBなどに格納しておこう。
送信失敗時はちゃんと例外で処理される。