主题
修改邮箱
在修改邮箱之前,我们需要一些提前准备工作。我们将使用邮箱服务发送验证码来验证邮箱的正确性。首先需要配置邮箱服务,我们选择使用 QQ 邮箱服务
。使用 QQ 邮箱服务,需要获取授权码,按照下面的步骤来配置 QQ 邮箱服务。
获取 QQ 邮箱授权码
- 登录 QQ 邮箱网页版。
- 点击顶部“设置” > “账户”。
- 找到“POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV 服务”部分。
- 开启“POP3/SMTP 服务”或“IMAP/SMTP 服务”。
- 根据提示完成验证(通常需要发送短信),然后会生成一个授权码,记下来。
配置邮箱服务
获取授权码之后,配置 Mail 邮箱服务
php
MAIL_MAILER=smtp
MAIL_HOST=smtp.qq.com
MAIL_PORT=587
MAIL_USERNAME="你的@qq.com"
MAIL_PASSWORD="上面配置后的授权码"
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS="你的@qq.com"
MAIL_FROM_NAME="${APP_NAME}"
创建邮件类
使用下面的命令生成邮件类
shell
php artisan make:mail SendEmailCode
这会在 app/Mail
目录下生成一个 SendEmailCode.php
文件。在创建一个 email
模板
shell
php artisan make:view emails/sendCode
找到 resources/views/emails/sendCode.blade.php
邮件模板,然后作如下修改,这里就简单一点
php
<!DOCTYPE html>
<html>
<head>
<title>邮箱更改</title>
</head>
<body>
<h1>Hello !</h1>
<p>这是一封来自 {{ config('app.name')}} 的邮箱更改邮件,验证码 : {{ $code }}</p>
</body>
</html>
再回到 UserController
控制器,添加下面两个方法
php
// 邮箱更改方法
public function email(Request $request)
{
// 等后面添加
return view('user.email');
}
// 发送邮箱更改验证码
public function sendEmailCode(Request $request)
{
$request->validate([
'email' => 'required|email|unique:users,email,' . Auth::id(),
]);
$newEmail = $request->get('email');
if ($newEmail != $request->user()->email) {
$code = Str::random(4);
// 使用 缓存 保存 code,以便后面校验使用
Cache::set(Auth::id() . '_email_code', $code, 600);
Mail::to($request->get('email'))->send(new SendEmailCode(Str::random(4)));
// 发送邮件成功,这里使用 json 返回,前端使用 ajax 请求
return \response()->json(['message' => '发送邮件成功']);
}
return \response()->json(['message' => '邮箱没有改变,无需发送邮件']);
}
添加邮箱验证路由
这里就不赘述了,还是到 routes/web.php
进行
php
Route::controller(\App\Http\Controllers\UserController::class)->prefix('user')->group(function () {
# 邮件
Route::match(['get', 'post'],'/email', 'email')->name('email');
Route::post('sendEmailCode', 'sendEmailCode')->name('sendEmailCode');
});
创建修改邮箱页面
shell
php artisan make:view user/email
然后找到 resources/views/user/email.blade.php
模板,添加如下代码
html
<div>
<x-layout>
<x-slot:header>个人资料</x-slot:header>
<div class="text-xl">修改邮箱</div>
<div class="w-full lg:w-1/2">
<form class="mt-10 space-y-6" action="{{ route('email')}}" method="POST">
@if (session('success'))
<div class="alert alert-success">{{ session('success') }}</div>
@endif
<label class="input input-bordered flex items-center gap-2 @error('email') input-error @enderror">
<input type="text" class="email" placeholder="邮箱" name="email" value="{{ auth()->user()->email }}" />
</label>
@error('email')
<div class="text-white alert alert-error">{{ $message }}</div>
@enderror
<label class="input input-bordered flex items-center gap-2 @error('code') input-error @enderror">
<input type="text" class="grow" placeholder="验证码" name="code" value="" />
<span onclick="sendEmailCode()">发送</span>
</label>
@error('code')
<div class="text-white alert alert-error">{{ $message }}</div>
@enderror
<div>
<button
type="submit"
class="flex justify-center px-3 py-1.5 w-full font-semibold text-white bg-indigo-600 rounded-md shadow-sm text-sm/6 hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
更 新
</button>
</div>
@csrf
</form>
</div>
</x-layout>
<!-- The best way to take care of the future is to take care of the present moment. - Thich Nhat Hanh -->
</div>
<script>
// 发送邮箱验证码,使用自带的 fetch 方法进行 ajax 请求
const sendEmailCode = () => {
fetch("{{route('sendEmailCode')}}", {
method: 'POST',
body: JSON.stringify({ email: document.querySelector('input[name="email"]').value, _token: '{{ csrf_token() }}' }),
headers: { 'Content-Type': 'application/json' }
}).then((r) => {
if (r.ok) {
r.json().then((r) => alert(r.message))
}
})
}
</script>
页面效果如下
点击发送邮箱,会收到如下邮件
验证邮箱
验证邮箱的话,我们需要在 UserController
控制器中的 email
方法中添加验证逻辑
php
public function email(Request $request)
{
if ($request->isMethod('POST')) {
$request->validate([
'email' =>'required|email|unique:users,email,'. Auth::id(),
'code' => ['required',
// 自定义验证规则
function (string $attribute, mixed $value, \Closure $fail) {
// 从缓存中获取验证码,进行验证
// 这里使用了 Laravel 的缓存,你也可以使用 Redis 等其他缓存工具
if ($value !== Cache::get(Auth::id() . '_email_code')) {
$fail('验证码错误');
}
}],
], [
'email.required' => '请输入邮箱',
'email.unique' => '该邮箱已经存在',
'email.email' => '请输入正确的邮箱格式',
'code.required' => '请输入验证码',
]);
// 验证成功,更新邮箱
$user = $request->user();
$user->email = $request->get('email');
// 保存成功后,删除验证码缓存
if ($user->save()) {
Cache::forget(Auth::id() . '_email_code');
}
return to_route('email')->with(['success' => '更新邮箱成功']);
}
return view('user.email');
}
发送验证码更换邮箱的逻辑就完成了。我们在总结以下这节内容,主要涉及到的知识点有
- 邮箱服务配置
- 发送邮件
- 验证邮箱
- 缓存, 这里主要使用的是 Laravel 的缓存,使用文件作为缓存驱动,实际业务一般都是使用
redis
作为缓存驱动 - 自定义验证规则,可以看文档闭包验证
- 前端 ajax 请求(一般不会使用 fetch,前端一般使用 axios,但这毕竟是入门教程,不想引入太多的依赖,以实现熟悉为主)