Skip to content

修改邮箱

在修改邮箱之前,我们需要一些提前准备工作。我们将使用邮箱服务发送验证码来验证邮箱的正确性。首先需要配置邮箱服务,我们选择使用 QQ 邮箱服务。使用 QQ 邮箱服务,需要获取授权码,按照下面的步骤来配置 QQ 邮箱服务。

获取 QQ 邮箱授权码

Laravel入门教程-修改邮箱

  • 找到“POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV 服务”部分。

Laravel入门教程-修改邮箱

  • 开启“POP3/SMTP 服务”或“IMAP/SMTP 服务”。
  • 根据提示完成验证(通常需要发送短信),然后会生成一个授权码,记下来。

Laravel 入门教程-修改邮箱

配置邮箱服务

获取授权码之后,配置 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>

页面效果如下 laravel 入门教程-用户修改邮箱页面

点击发送邮箱,会收到如下邮件 laravel 入门教程-用户资料-邮箱验证

验证邮箱

验证邮箱的话,我们需要在 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,但这毕竟是入门教程,不想引入太多的依赖,以实现熟悉为主)