// +---------------------------------------------------------------------- declare (strict_types=1); namespace app\api\service\passport; use think\facade\Log; use yiovo\cache\facade\Cache; use yiovo\captcha\facade\CaptchaApi; use app\api\validate\passport\EmailCaptcha as ValidateEmailCaptcha; use app\common\service\BaseService; use cores\exception\BaseException; use PHPMailer\PHPMailer\PHPMailer; use PHPMailer\PHPMailer\SMTP; use PHPMailer\PHPMailer\Exception; /** * 服务类:发送邮箱验证码 * Class MailCaptcha * @package app\api\service\passport */ class MailCaptcha extends BaseService { // 最大发送次数,默认10次 protected int $sendTimes = 10; // 发送限制间隔时间,默认24小时 protected int $safeTime = 86400; /** * 发送邮件验证码 * @param array $data * @return bool * @throws BaseException */ public function handle(array $data): bool { // 数据验证 $this->validate($data); // 执行发送短信 if (!$this->sendCaptcha($data['email'])) { return false; } return true; } /** * 执行发送邮箱验证码 * @param string $email * @return bool */ public function sendCaptcha(string $email): bool { // 缓存发送记录并判断次数 if (!$this->record($email)) { return false; } // 生成验证码 $smsCaptcha = CaptchaApi::createSMS($email); $mail = new PHPMailer(true); try { //Server settings $mail->SMTPDebug = SMTP::DEBUG_SERVER;//DEBUG_OFF //Enable verbose debug output $mail->isSMTP(); //Send using SMTP $mail->Host = 'smtp.163.com'; //Set the SMTP server to send through $mail->SMTPAuth = true; //Enable SMTP authentication $mail->Username = 'zhangdehua814@163.com'; //SMTP username $mail->Password = 'SGPMIQCKVKGIJUGQ'; //SMTP password $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption $mail->Port = 465; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS` //Recipients $mail->setFrom('zhangdehua814@163.com', 'Mailer'); $mail->addAddress($email, 'Gold'); //Add a recipient //$mail->addAddress('ellen@example.com'); //Name is optional //$mail->addReplyTo('info@example.com', 'Information'); //$mail->addCC('cc@example.com'); //$mail->addBCC('bcc@example.com'); //Attachments //$mail->addAttachment('/var/tmp/file.tar.gz'); //Add attachments //$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); //Optional name //Content //$mail->isHTML(true); //Set email format to HTML $mail->Subject = 'Captcha'; $mail->Body = 'Your captcha is ' . $smsCaptcha['code'] . '.Please use it in 15 minutes'; $mail->AltBody = 'This is the Your captcha for vapes'; $mail->send(); //echo 'Message has been sent'; } catch (Exception $e) { //echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}"; Log::error(__CLASS__ . ':' . __METHOD__ . $e->getMessage() . '---' . $mail->ErrorInfo); Log::error(__CLASS__ . ':' . __METHOD__, ['errMsg' => $e->getMessage(), 'mailError' => $mail->ErrorInfo]); return false; } return true; } /** * 发送营销文本邮件 * @param string $email * @param string $subject * @param string $body * @param string $altBody * @param bool $isHtml * @param string $name * @return bool */ public function sendText(string $email, string $subject = '', string $body = '', string $altBody = '', bool $isHtml = false, string $name = 'vip'): bool { $mail = new PHPMailer(true); try { //Server settings $mail->SMTPDebug = SMTP::DEBUG_SERVER; //Enable verbose debug output $mail->isSMTP(); //Send using SMTP $mail->Host = 'smtp.163.com'; //Set the SMTP server to send through $mail->SMTPAuth = true; //Enable SMTP authentication $mail->Username = 'zhangdehua814@163.com'; //SMTP username $mail->Password = 'SGPMIQCKVKGIJUGQ'; //SMTP password $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption $mail->Port = 465; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS` //Recipients $mail->setFrom('zhangdehua814@163.com', 'Mailer'); $mail->addAddress($email, $name); //Add a recipient //Content if ($isHtml) { $mail->isHTML(true); //Set email format to HTML } $mail->Subject = $subject; $mail->Body = $body; if (!empty($altBody)) { $mail->AltBody = 'This is the body in plain text for non-HTML mail clients'; } $mail->send(); echo 'Message has been sent'; } catch (Exception $e) { echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}"; Log::error(__CLASS__ . ':' . __METHOD__, ['errMsg' => $e->getMessage(), 'mailError' => $mail->ErrorInfo]); return false; } return true; } /** * 记录短信验证码发送记录并判断是否超出发送限制 * @param string $mobile * @return bool */ private function record(string $email): bool { // 获取发送记录缓存 $record = Cache::get("sendCaptchaEmail.$email"); // 写入缓存:记录剩余发送次数 if (empty($record)) { Cache::set("sendCaptchaEmail.$email", ['times' => $this->sendTimes - 1], $this->safeTime); return true; } // 判断发送次数是否合法 if ($record['times'] <= 0) { $this->error = '很抱歉,已超出今日最大发送次数限制'; return false; } // 发送次数递减 Cache::update("sendCaptchaEmail.$email", ['times' => $record['times'] - 1]); return true; } /** * 数据验证 * @param array $data * @throws BaseException */ public function validate(array $data) { // 数据验证 $validate = new ValidateEmailCaptcha; if (!$validate->check($data)) { throwError($validate->getError()); } // 验证图形验证码 // if (!CaptchaApi::check($data['captchaCode'], $data['captchaKey'])) { // throwError('很抱歉,图形验证码不正确'); // } } public function checkCaptcha($captchaCode = '', $email = '') { $localCode = Cache::get('captchaSMS.' . $email); if (empty($localCode) || empty($localCode['code']) || $localCode['code'] != $captchaCode) { throwError('Sorry,your captcha is invalid'); } //dd($localCode); } }