封装发送邮件功能
使用的是PHPMailer包
//邮件发送
if (!function_exists('sendmail')) {
function sendmail($address, $title, $body)
{
$mail = new \PHPMailer\PHPMailer\PHPMailer(true);
try {
$mail->SMTPDebug = 0;
$mail->isSMTP();
$mail->CharSet = "UTF-8"; //utf-8;
$mail->Encoding = "base64";
$mail->Host = env('mail.host');
$mail->SMTPAuth = true;
$mail->Username = env('mail.username');
$mail->Password = env('mail.password');
$mail->SMTPSecure = env('mail.encryption');
$mail->Port = env('mail.port');
//Recipients
$mail->setFrom(env('mail.from_address'), env('mail.from_name'));
//接收人
$mail->addAddress($address);
//回复的时候回复给哪个邮箱 建议和发件人一致
$mail->addReplyTo(env('mail.from_address'), 'info');
//Content
$mail->isHTML(true);
//防止中文乱码
$mail->Subject = "=?UTF-8?B?" . base64_encode($title) . "?=";
$mail->Body = $body;
$mail->AltBody = '您的邮箱客户端不支持显示HTML内容';
$mail->send();
return true;
} catch (Exception $e) {
return $e;
}
}
}
2.使用
sendmail('xxx@xx.xx', '系统通知', '<h1>你好啊</h1>');
3.使用think-queue消息队列发送邮件
//前面的注册逻辑省略...
//缓存key(此处可以替换为redis等nosql缓存产品)
//参数说明
//参数1:缓存标志register_email_code_+用户注册入库时返回的主键id作为缓存key
//参数2:uuid当作缓存值进行缓存
//参数3:缓存过期时间(这里我从我的配置文件中读取,你可以直接设置值,单位:秒),24 * 60 * 60
cache("register_email_code_" . $user->id, $uuid, config('my.email_register.expire'));
//异步发送邮箱
//把需要的数据传递过去
Queue::push(RegEmailActiveJob::class, [
'user_id' => $user->id,
//昵称
'nickname' => $user->profile->nickname,
//uuid
'uuid' => $uuid,
//发给谁
'email' => $user->email
]);
生成RegEmailActiveJob异步任务
<?php
namespace app\job;
use think\queue\Job;
class RegEmailActiveJob
{
public function fire(Job $job, $data)
{
$user_id = $data['user_id'];
$nickname = $data['nickname'];
$uuid = $data['uuid'];
$email = $data['email'];
$link = env('app.host') . '/validate/email?user_id=' . $user_id . '&code=' . $uuid;
//smarty替换变量后返回html内容
$html = app('smarty')->fetch('index/email/regEmailActive.tpl', compact('nickname', 'link'));
//发送邮件
sendmail($email, config('my.email_register.title'), $html);
if ($job->attempts() > 3) {
//通过这个方法可以检查这个任务已经重试了几次了
// Log::info("超过三次");
}
//如果任务执行成功后 记得删除任务,不然这个任务会重复执行,直到达到最大重试次数后失败后,执行failed方法
$job->delete();
// 也可以重新发布这个任务
//$job->release(0); //$delay为延迟时间
}
public function failed($data)
{
// ...任务达到最大重试次数后,失败了
}
}
uuid生成方法
//生成uuid
if (!function_exists('uuid')) {
function uuid($prefix = '')
{
$chars = md5(uniqid(mt_rand(), true));
$uuid = substr($chars, 0, 8);
$uuid .= substr($chars, 8, 4);
$uuid .= substr($chars, 12, 4);
$uuid .= substr($chars, 16, 4);
$uuid .= substr($chars, 20, 12);
return $prefix . $uuid;
}
}
发送成功后用户点击连接的处理
验证成功后你可以直接登录,你也可以跳转回登录页,让用户登录
//邮箱注册链接回调
public function email(Request $request)
{
//接收参数
$user_id = $request->get('user_id');
$code = $request->get('code');
if ($user_id === null || $code === null) {
return $this->smarty->display('index/error/error.tpl', [
'msg' => '激活地址非法',
'code' => 500
]);
}
//判断缓存中取出来的是否和传递过来的是否相等
if (cache('register_email_code_' . $user_id) != $code) {
return $this->smarty->display('index/error/error.tpl', [
'msg' => '激活地址已失效',
'code' => 500
]);
}
//上面那一步过不来就等于是非法了,到这一步其实就已经可以直接更新状态了
$user = User::with(['profile'])->find($user_id);
$user->status = 1;
$user->save();
//让缓存失效
cache('register_email_code_' . $user_id, null);
//直接登录
session('index_user', $user);
return redirect((string)url('/'))->with('success', '登录成功');
}