Laravel 支援信件寄送功能,可以经由各种服务发送信件,框架也预设有使用者登入时就寄送验证信的功能,不过一开始并没有串接上寄信的服务,要先设定过後才能用。
寄信的环境变数设定在 config/mail.php
中。
首先看到 mailers
设定,用於定义寄送的信件要经由何种服务转送,包含 smtp ,AWS SES , Mailgun 等服务都可以设定。
'mailers' => [
'smtp' => [
'transport' => 'smtp',
//...
],
'ses' => [
'transport' => 'ses',
],
'mailgun' => [
'transport' => 'mailgun',
],
'postmark' => [
'transport' => 'postmark',
],
'sendmail' => [
'transport' => 'sendmail',
'path' => '/usr/sbin/sendmail -bs',
],
'log' => [
'transport' => 'log',
'channel' => env('MAIL_LOG_CHANNEL'),
],
'array' => [
'transport' => 'array',
],
'failover' => [
//...
],
],
回看到最上面的 default
,就是用於指定预设用哪个 mailer 寄送信件。
'default' => env('MAIL_MAILER', 'smtp'),
接着是 from
,就是预设的寄件者的信箱与名称,当寄信时若没另外指定寄件者就会取这里的值。
'from' => [
'address' => env('MAIL_FROM_ADDRESS', '[email protected]'),
'name' => env('MAIL_FROM_NAME', 'Example'),
],
最後是 markdown
,如果寄信的模板选用 markdown 编译,就会到 paths 底下的目录找对应的模板,应用预设的 theme ,也就是 css 格式。
'markdown' => [
'theme' => 'default',
'paths' => [
resource_path('views/vendor/mail'),
],
],
可以看到设定中很多是从 env
取值的,所以要先进行 .env 的设定
MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
[email protected]
MAIL_PASSWORD=password
MAIL_ENCRYPTION=null
[email protected]
MAIL_FROM_NAME="${APP_NAME}"
如果是用 sail 建立的专案,这边已经预设好 MAIL_HOST=mailhog
, mailhog 是个信件测试工具,将 mailhog 指定为寄件的 SMTP 的话 mailhog 就会拦截信件并呈现在网页介面上。
Sail 预设的 mailhog 开在 http://localhost:8025/
上,可以先打开看看,目前还没有任何信件。
因为这边是用 mailhog 进行测试,所以 .env 的设定只要有值就好,如果是正经的寄信
MAIL_USERNAME
跟 MAIL_PASSWORD
就要填对应服务的帐号密码。
[email protected]
MAIL_PASSWORD=password
想让使用者在注册时收到验证信,先到 User Model 进行设定
/app/Models/User.php
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\UserSetting;
use App\Models\Todo;
class User extends Authenticatable
{
//...
}
可以看到虽然已经引入了 MustVerifyEmail ,但 User 其实还没应用上。
就把 MustVerifyEmail 加上去吧。
@@ -11,7 +11,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
use App\Models\UserSetting;
use App\Models\Todo;
-class User extends Authenticatable
+class User extends Authenticatable implements MustVerifyEmail
{
use HasApiTokens, HasFactory, Notifiable;
use SoftDeletes;
接着就能新申请一个帐号,发现通知寄送验证信成功。
到 MailHog 看看
出现一笔纪录,点进去就能看到信件的内容,有个按钮可以验证信箱。
先来看看 Laravel 预设的验证信寄送流程。
当使用者注册、建立成功之後,发出 Registered
事件,关於事件的运作之後再详谈。
app/Http/Controllers/Auth/RegisteredUserController.php
public function store(Request $request)
{
$request->validate([
'name' => 'required|string|max:255',
'email' => 'required|string|email|max:255|unique:users',
'password' => ['required', 'confirmed', Rules\Password::defaults()],
]);
$user = User::create([
'name' => $request->name,
'email' => $request->email,
'password' => Hash::make($request->password),
]);
$user->setting()->create();
event(new Registered($user)); // 注册成功事件
Auth::login($user);
return redirect(RouteServiceProvider::HOME);
}
Registered
事件发出後会被 SendEmailVerificationNotification
处理。
app/Providers/EventServiceProvider.php
<?php
namespace App\Providers;
use Illuminate\Auth\Events\Registered;
use Illuminate\Auth\Listeners\SendEmailVerificationNotification;
use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider;
use Illuminate\Support\Facades\Event;
class EventServiceProvider extends ServiceProvider
{
protected $listen = [
Registered::class => [ //处理 Registered 事件
SendEmailVerificationNotification::class,
],
];
//...
}
找到 SendEmailVerificationNotification
,这里会用 User Model 中的 sendEmailVerificationNotification
执行寄信,而这个方法在哪呢?
vendor/laravel/framework/src/Illuminate/Auth/Listeners/SendEmailVerificationNotification.php
<?php
namespace Illuminate\Auth\Listeners;
use Illuminate\Auth\Events\Registered;
use Illuminate\Contracts\Auth\MustVerifyEmail;
class SendEmailVerificationNotification
{
public function handle(Registered $event)
{
if ($event->user instanceof MustVerifyEmail && ! $event->user->hasVerifiedEmail()) {
$event->user->sendEmailVerificationNotification();
}
}
}
就在我们刚刚应用的 MustVerifyEmail
底下
vendor/laravel/framework/src/Illuminate/Auth/MustVerifyEmail.php
<?php
namespace Illuminate\Auth;
use Illuminate\Auth\Notifications\VerifyEmail;
trait MustVerifyEmail
{
//...
public function sendEmailVerificationNotification()
{
$this->notify(new VerifyEmail);
}
}
这里的VerifyEmail
是用来产生信件的,包含信件的标题以及内容、寄件人等,所以我们要客制验证信的话,就在 User Model 底下覆盖 sendEmailVerificationNotification
方法,改成寄客制化的信件。
首先用指令产生用 Markdown 编写的信件
sail artisan make:mail CustomVerifyMail --markdown=mail.custom.verify
先看到刚刚产生的 Mailable ,信件的实例都是继承 Mailable ,并且要有 build 函式定义如何建立信件。
app/Mail/CustomVerifyMail.php
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
class CustomVerifyMail extends Mailable
{
use Queueable, SerializesModels;
public function __construct()
{
//
}
public function build()
{
return $this->markdown('mail.custom.verify');
}
}
这边我们选择用 markdown
格式编写信件内容
return $this->markdown('mail.custom.verify');
而 mail.custom.verify
会产生在 config/mail.php
中定义的 markdown path 底下,预设是 views/vendor/mail
。
resources/views/mail/custom/verify.blade.php
@component('mail::message')
# Introduction
The body of your message.
@component('mail::button', ['url' => ''])
Button Text
@endcomponent
Thanks,<br>
{{ config('app.name') }}
@endcomponent
现在就可以用 CustomVerifyMail
寄送信件了,在 User Model 底下编写覆盖 sendEmailVerificationNotification
的方法。
<?php
namespace App\Models;
//...
use App\Mail\CustomVerifyMail;
use Illuminate\Support\Facades\Mail;
class User extends Authenticatable implements MustVerifyEmail
{
use HasApiTokens, HasFactory, Notifiable;
use SoftDeletes;
//...
public function sendEmailVerificationNotification()
{
Mail::to($this)->send(new CustomVerifyMail);
}
}
不过现在寄信的话可以看到样式还是跟原本的信件一样。
这篇到这边有点长了,关於信件样式跟内容的改动就明天再写吧。
>>: Day27 [实作] 一对一视讯通话(7): 使用 Docker 封装
前言 今天要开始练习SQLite基本的语法 介绍内容有 SELECT 从资料库中选取特定资料 数值...
Recurrent Neural Network 循环精神网路 RNN是一种专门设计用以解决时间序列...
第12 届iT邦帮忙铁人赛系列文章 (Day30) 终於走到这一天了,每次都觉得铁人赛过程都生不如死...
我们知道写程序有个阶段就是一个输入、运算处理、输出 网页是由HTML、CSS、Javascript三...
今天到了 day3,上次有预告了这次会开始进行RISC-V 32平台的musl libc porti...