【发布时间】:2022-02-03 16:29:14
【问题描述】:
我刚刚升级到 Laravel 5.7,现在我正在使用内置的电子邮件验证。但是有两件事我无法弄清楚,主要问题是如何自定义发送给用户以验证他们的电子邮件的电子邮件?如果用户更改了他们的电子邮件,我也无法弄清楚如何开始发送该电子邮件,但我可以将其保存到另一个线程。
【问题讨论】:
标签: laravel-5 html-email
我刚刚升级到 Laravel 5.7,现在我正在使用内置的电子邮件验证。但是有两件事我无法弄清楚,主要问题是如何自定义发送给用户以验证他们的电子邮件的电子邮件?如果用户更改了他们的电子邮件,我也无法弄清楚如何开始发送该电子邮件,但我可以将其保存到另一个线程。
【问题讨论】:
标签: laravel-5 html-email
当您想在 Laravel 5.7 中添加电子邮件验证时,建议的方法是实现 Illuminate\Contracts\Auth\MustVerifyEmail 并在 App\User 模型上使用 Illuminate\Auth\MustVerifyEmail 特征。
要进行一些自定义行为,您可以覆盖方法sendEmailVerificationNotification,该方法通过调用方法notify 来通知创建的用户,并将Notifications\MustVerifyEmail 类的新实例作为参数传递。
您可以创建一个自定义通知,该通知将作为参数传递给您用户模型的 sendEmailVerificationNotification 方法中的$this->notify():
public function sendEmailVerificationNotification()
{
$this->notify(new App\Notifications\CustomVerifyEmail);
}
...然后在您的CustomVerifyEmail 通知中,您可以定义处理验证的方式。您可以通过发送包含自定义 verification.route 的电子邮件来通知创建的用户,该邮件将采用您想要的任何参数。
电子邮件验证通知流程
当新用户注册时,App\Http\Controllers\Auth\RegisterController 中会发出一个Illuminate\Auth\Events\Registered 事件,并且该Registered 事件有一个名为Illuminate\Auth\Listeners\SendEmailVerificationNotification 的侦听器,该侦听器注册在App\Providers\EventServiceProvider 中:
protected $listen = [
Registered::class => [
SendEmailVerificationNotification::class,
]
];
SendEmailVerificationNotification 监听器检查 $user(在 Laravel 默认身份验证 App\Http\Controllers\Auth\RegisterController 中作为参数传递给 new Registered($user = $this->create($request->all())))是否是 Illuminate\Contracts\Auth\MustVerifyEmail 的实例,这是 Laravel 建议的特征的名称当您要提供默认电子邮件验证并检查 $user 是否尚未验证时,在 App\User 模型中使用。如果所有这些都通过了,则对该用户调用 sendEmailVerificationNotification 方法:
if ($event->user instanceof MustVerifyEmail && !$event->user->hasVerifiedEmail()) {
$event->user->sendEmailVerificationNotification();
}
【讨论】:
我认为执行此操作的简单方法是使用此处的文档发出新通知:https://laravel.com/docs/5.7/notifications#creating-notifications
然后重写函数:
public function sendEmailVerificationNotification()
{
$this->notify(new App\Notifications\CustomEmailNotification);
}
在用户模型中。
或者你可以
php artisan vendor:publish --tag=laravel-notifications
这会将模板复制到 resources/views/vendor/notifications 目录,您可以在那里修改它们
【讨论】:
Illuminate\Auth\Notifications\VerifyEmail 并将其与 CustomEmailNotification 进行比较。查看laravel.com/docs/5.8/mail#customizing-the-components 和laravel.com/docs/5.8/notifications 也很有用。最后一件事,我不知道为什么 CSS 主题对我不起作用,我所做的只是将我需要的所有样式直接复制到 vendor/mail/html/layout.blade.php 文件中。
不幸的是,发出的这封电子邮件不是来自“视图”,而是实际上内联构建的Notification。这是当前需要发送时构建的位置:Illuminate\Auth\Notifications\VerifyEmail@toMail。这个特定的类有一个静态回调,可以设置它来构建这个电子邮件,而不是让它去做。
在boot 方法中的服务提供者中,您需要为此类分配回调:
“类似”的东西可能会起作用:
public function boot()
{
\Illuminate\Auth\Notifications\VerifyEmail::toMailUsing(function ($notifiable) {
// this is what is currently being done
// adjust for your needs
return (new \Illuminate\Notifications\Messages\MailMessage)
->subject(\Lang::getFromJson('Verify Email Address'))
->line(\Lang::getFromJson('Please click the button below to verify your email address.'))
->action(
\Lang::getFromJson('Verify Email Address'),
$this->verificationUrl($notifiable)
)
->line(\Lang::getFromJson('If you did not create an account, no further action is required.'));
});
}
由于这是一个通知,您应该有更多自定义选项。
如果您想使用自己的 Notification 类,您可以覆盖 User (Authenticatable) 模型上的 sendEmailVerificationNotification 方法(这是来自 MustVerifyEmail 特征)。
第二个问题:
您应该拥有的 VerificationController (App\Http\Controllers\Auth\VerificationController) 有一个名为 resend(来自 trait VerifiesEmails)的方法,该方法看起来很适合此目的。
您应该通过Auth::routes(['verify' => true]);为这些验证路由设置路由
注意:
验证系统使用 5.7 中 users 表 email_verified_at 上的一个字段来标记这一点。你会想确保你有这个字段。当用户更改电子邮件地址时,我想您可以创建此 null 然后将他们重定向到 resend 路由,以发送新的验证。这将使他们进入“未验证”状态,直到他们重新验证,如果这是你打算发生的。
更新:
看来我们走在了正确的轨道上。我发现这个 SO 答案涵盖了类似的事情:
Changing the default “subject” field for the verification email in laravel 5.7
【讨论】:
快速简便的方法:
php artisan vendor:publish --tag=laravel-notifications
它正在创建一个新文件:
\resources\views\vendor\notifications
这是 Laravel 的电子邮件模板。您可以更改和自定义它。
【讨论】:
我将向您展示如何在不使用任何供应商发布
的情况下从头开始使用自定义视图自定义用户验证电子邮件步骤:1
创建一个新通知UserVerifyNotification class。它应该从库 Illuminate\Auth\Notifications\VerifyEmail; 扩展 VerifyEmail class
代码:
use Illuminate\Auth\Notifications\VerifyEmail;
...
class UserVerifyNotification extends VerifyEmail implements ShouldQueue
{
use Queueable;
public $user; //you'll need this to address the user
/**
* Create a new notification instance.
*
* @return void
*/
public function __construct($user='')
{
$this->user = $user ?: Auth::user(); //if user is not supplied, get from session
}
/**
* Get the notification's delivery channels.
*
* @param mixed $notifiable
* @return array
*/
public function via($notifiable)
{
return ['mail'];
}
/**
* Get the mail representation of the notification.
*
* @param mixed $notifiable
* @return \Illuminate\Notifications\Messages\MailMessage
*/
public function toMail($notifiable)
{
$actionUrl = $this->verificationUrl($notifiable); //verificationUrl required for the verification link
$actionText = 'Click here to verify your email';
return (new MailMessage)->subject('Verify your account')->view(
'emails.user-verify',
[
'user'=> $this->user,
'actionText' => $actionText,
'actionUrl' => $actionUrl,
]);
}
/**
* Get the array representation of the notification.
*
* @param mixed $notifiable
* @return array
*/
public function toArray($notifiable)
{
return [
//
];
}
}
步骤:2
在resources\views\emails
<DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
</head>
<body>
<p>Dear {{$user->name}},</p>
<p>
Please click the button below to verify your email address.
</p>
<a href="{{ $actionUrl }}" class="button">{{$actionText}}</a>
<p>If you did not create an account, no further action is required.</p>
<p>
Best regards, <br>
{{ config('app.name')}}
</p>
<p>
<hr>
<span class="break-all">
<strong>If you’re having trouble clicking the link, copy and paste the URL below into your web browser:</strong><br/>
<em>{{$actionUrl}}</em>
</p>
</body>
</html>
步骤:3
在User model内添加如下方法
class User extends Authenticatable implements MustVerifyEmail
{
use HasFactory, Notifiable;
...
...
...
public function sendEmailVerificationNotification()
{
$this->notify(new \App\Notifications\UserVerifyNotification(Auth::user())); //pass the currently logged in user to the notification class
}
}
说明
Illuminate\Auth\Events) 会被调用。EventServiceProvider(App\Providers\EventServiceProvider))内部有一个监听器,监听Registered事件。 1、注册完成后,调用SendEmailVerificationNotification方法(Illuminate\Auth\Listeners\SendEmailVerificationNotification)。Illuminate\Auth\Listeners\SendEmailVerificationNotification 中的 sendEmailVerificationNotification() 方法
sendEmailVerificationNotification() 函数,并指出我们想使用我们之前在第 1 步中创建的通知类
Auth::routes([
'verify' => true,
'register' => true,
]);
【讨论】:
基于 Andrew Earls 的回答,您还可以使用以下命令发布应用程序使用的所有降价邮件组件:
php artisan vendor:publish --tag=laravel-mail
完成后,您将在 resources/views/vendor/mail 中修改一系列 html 和 markdown 文件。这将允许您修改整体电子邮件布局以及 CSS 的“主题”。我强烈建议好好阅读Mail docs - Customizing The Components。
作为一般电子邮件主题快速入门(Laravel 5.7),您可以:
php artisan vendor:publish --tag=laravel-mail 发布主题。resources/views/vendor/mail/html/themes/default.css 复制到您自己的文件中。例如resources/views/vendor/mail/html/themes/wayne.css
config/mail.php,在您看到'theme' => 'default' 的位置将其更改为'theme' => 'wayne'
wayne.css 以重新设置您的电子邮件样式。希望对某人有所帮助。
【讨论】:
要发送验证电子邮件,您只需使用下一个代码:
// send new verification email to user
$user->sendEmailVerificationNotification();
【讨论】:
在路由文件中
Auth::routes(['verify' => true]);
在 AppServiceProvider.php 文件中
namespace App\Providers;
use App\Mail\EmailVerification;
use Illuminate\Support\ServiceProvider;
use View;
use URL;
use Carbon\Carbon;
use Config;
use Illuminate\Auth\Notifications\VerifyEmail;
use Illuminate\Notifications\Messages\MailMessage;
class AppServiceProvider extends ServiceProvider
{
/**
* Register any application services.
*
* @return void
*/
public function register()
{
//
}
/**
* Bootstrap any application services.
*
* @return void
*/
public function boot()
{
// Override the email notification for verifying email
VerifyEmail::toMailUsing(function ($notifiable){
$verifyUrl = URL::temporarySignedRoute('verification.verify',
\Illuminate\Support\Carbon::now()->addMinutes(\Illuminate\Support\Facades
\Config::get('auth.verification.expire', 60)),
[
'id' => $notifiable->getKey(),
'hash' => sha1($notifiable->getEmailForVerification()),
]
);
return new EmailVerification($verifyUrl, $notifiable);
});
}
}
现在使用 Markdown 创建 EmailVerification
php artisan make:mail EmailVerification --markdown=emails.verify-email
根据需要编辑 EmailVerrification 和刀片文件
class EmailVerification extends Mailable
{
use Queueable, SerializesModels;
public $verifyUrl;
protected $user;
/**
* Create a new message instance.
*
* @return void
*/
public function __construct($url,$user)
{
$this->verifyUrl = $url;
$this->user = $user;
}
/**
* Build the message.
*
* @return $this
*/
public function build()
{
$address = 'mymail@gmail.com';
$name = 'Name';
$subject = 'verify Email';
return $this->to($this->user)->subject($subject)->from($address, $name)->
markdown('emails.verify',['url' => $this->verifyUrl,'user' => $this->user]);
}
}
在刀片文件中根据需要更改设计并使用 verifyUrl 显示验证链接并使用 $user 显示用户信息
谢谢,编码愉快:)
【讨论】:
导航到这些文件
vendor/laravel/framework/src/Illuminate/Auth/MustVerifyEmail.php
vendor/laravel/framework/src/Illuminate/Auth/Notifications/VerifyEmail.php
然后自定义它。 你甚至可以在 供应商/laravel/framework/src/Illuminate/Auth/Notifications/VerifyEmail.php 并通过 vendor/laravel/framework/src/Illuminate/Auth/MustVerifyEmail.php 传递值
【讨论】:
composer update 更新依赖项,这些文件就会被覆盖。
interface MustVerifyEmail 接口允许您覆盖那里指定的功能。这样您就不必编辑任何/vendor/ 文件。相反,将您喜欢的任何方法从该界面复制到用户模型中,然后复制您需要的供应商文件并将它们粘贴到用户模型中的该函数中...