MailCaptcha.php 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. <?php
  2. // +----------------------------------------------------------------------
  3. // | 萤火商城系统 [ 致力于通过产品和服务,帮助商家高效化开拓市场 ]
  4. // +----------------------------------------------------------------------
  5. // | Copyright (c) 2017~2024 https://www.yiovo.com All rights reserved.
  6. // +----------------------------------------------------------------------
  7. // | Licensed 这不是一个自由软件,不允许对程序代码以任何形式任何目的的再发行
  8. // +----------------------------------------------------------------------
  9. // | Author: 萤火科技 <admin@yiovo.com>
  10. // +----------------------------------------------------------------------
  11. declare (strict_types=1);
  12. namespace app\api\service\passport;
  13. use think\facade\Log;
  14. use yiovo\cache\facade\Cache;
  15. use yiovo\captcha\facade\CaptchaApi;
  16. use app\api\validate\passport\EmailCaptcha as ValidateEmailCaptcha;
  17. use app\common\service\BaseService;
  18. use cores\exception\BaseException;
  19. use PHPMailer\PHPMailer\PHPMailer;
  20. use PHPMailer\PHPMailer\SMTP;
  21. use PHPMailer\PHPMailer\Exception;
  22. /**
  23. * 服务类:发送邮箱验证码
  24. * Class MailCaptcha
  25. * @package app\api\service\passport
  26. */
  27. class MailCaptcha extends BaseService
  28. {
  29. // 最大发送次数,默认10次
  30. protected int $sendTimes = 10;
  31. // 发送限制间隔时间,默认24小时
  32. protected int $safeTime = 86400;
  33. /**
  34. * 发送邮件验证码
  35. * @param array $data
  36. * @return bool
  37. * @throws BaseException
  38. */
  39. public function handle(array $data): bool
  40. {
  41. // 数据验证
  42. $this->validate($data);
  43. // 执行发送短信
  44. if (!$this->sendCaptcha($data['email'])) {
  45. return false;
  46. }
  47. return true;
  48. }
  49. /**
  50. * 执行发送邮箱验证码
  51. * @param string $email
  52. * @return bool
  53. */
  54. public function sendCaptcha(string $email): bool
  55. {
  56. // 缓存发送记录并判断次数
  57. if (!$this->record($email)) {
  58. return false;
  59. }
  60. // 生成验证码
  61. $smsCaptcha = CaptchaApi::createSMS($email);
  62. $mail = new PHPMailer(true);
  63. try {
  64. //Server settings
  65. $mail->SMTPDebug = SMTP::DEBUG_OFF;//DEBUG_SERVER //Enable verbose debug output
  66. $mail->isSMTP(); //Send using SMTP
  67. $mail->Host = 'smtp.163.com'; //Set the SMTP server to send through
  68. $mail->SMTPAuth = true; //Enable SMTP authentication
  69. $mail->Username = 'zhangdehua814@163.com'; //SMTP username
  70. $mail->Password = 'SGPMIQCKVKGIJUGQ'; //SMTP password
  71. $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption
  72. $mail->Port = 465; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`
  73. //Recipients
  74. $mail->setFrom('zhangdehua814@163.com', 'Mailer');
  75. $mail->addAddress($email, 'Gold'); //Add a recipient
  76. //$mail->addAddress('ellen@example.com'); //Name is optional
  77. //$mail->addReplyTo('info@example.com', 'Information');
  78. //$mail->addCC('cc@example.com');
  79. //$mail->addBCC('bcc@example.com');
  80. //Attachments
  81. //$mail->addAttachment('/var/tmp/file.tar.gz'); //Add attachments
  82. //$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); //Optional name
  83. //Content
  84. //$mail->isHTML(true); //Set email format to HTML
  85. $mail->Subject = 'Captcha';
  86. $mail->Body = 'Your captcha is ' . $smsCaptcha['code'] . '.Please use it in 15 minutes';
  87. $mail->AltBody = 'This is the Your captcha for vapes';
  88. $mail->send();
  89. //echo 'Message has been sent';
  90. } catch (Exception $e) {
  91. //echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
  92. Log::error(__CLASS__ . ':' . __METHOD__, ['errMsg' => $e->getMessage(), 'mailError' => $mail->ErrorInfo]);
  93. return false;
  94. }
  95. return true;
  96. }
  97. /**
  98. * 发送营销文本邮件
  99. * @param string $email
  100. * @param string $subject
  101. * @param string $body
  102. * @param string $altBody
  103. * @param bool $isHtml
  104. * @param string $name
  105. * @return bool
  106. */
  107. public function sendText(string $email, string $subject = '', string $body = '', string $altBody = '', bool $isHtml = false, string $name = 'vip'): bool
  108. {
  109. $mail = new PHPMailer(true);
  110. try {
  111. //Server settings
  112. $mail->SMTPDebug = SMTP::DEBUG_SERVER; //Enable verbose debug output
  113. $mail->isSMTP(); //Send using SMTP
  114. $mail->Host = 'smtp.163.com'; //Set the SMTP server to send through
  115. $mail->SMTPAuth = true; //Enable SMTP authentication
  116. $mail->Username = 'zhangdehua814@163.com'; //SMTP username
  117. $mail->Password = 'SGPMIQCKVKGIJUGQ'; //SMTP password
  118. $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption
  119. $mail->Port = 465; //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`
  120. //Recipients
  121. $mail->setFrom('zhangdehua814@163.com', 'Mailer');
  122. $mail->addAddress($email, $name); //Add a recipient
  123. //Content
  124. if ($isHtml) {
  125. $mail->isHTML(true); //Set email format to HTML
  126. }
  127. $mail->Subject = $subject;
  128. $mail->Body = $body;
  129. if (!empty($altBody)) {
  130. $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
  131. }
  132. $mail->send();
  133. echo 'Message has been sent';
  134. } catch (Exception $e) {
  135. echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
  136. Log::error(__CLASS__ . ':' . __METHOD__, ['errMsg' => $e->getMessage(), 'mailError' => $mail->ErrorInfo]);
  137. return false;
  138. }
  139. return true;
  140. }
  141. /**
  142. * 记录短信验证码发送记录并判断是否超出发送限制
  143. * @param string $mobile
  144. * @return bool
  145. */
  146. private function record(string $email): bool
  147. {
  148. // 获取发送记录缓存
  149. $record = Cache::get("sendCaptchaEmail.$email");
  150. // 写入缓存:记录剩余发送次数
  151. if (empty($record)) {
  152. Cache::set("sendCaptchaEmail.$email", ['times' => $this->sendTimes - 1], $this->safeTime);
  153. return true;
  154. }
  155. // 判断发送次数是否合法
  156. if ($record['times'] <= 0) {
  157. $this->error = '很抱歉,已超出今日最大发送次数限制';
  158. return false;
  159. }
  160. // 发送次数递减
  161. Cache::update("sendCaptchaEmail.$email", ['times' => $record['times'] - 1]);
  162. return true;
  163. }
  164. /**
  165. * 数据验证
  166. * @param array $data
  167. * @throws BaseException
  168. */
  169. public function validate(array $data)
  170. {
  171. // 数据验证
  172. $validate = new ValidateEmailCaptcha;
  173. if (!$validate->check($data)) {
  174. throwError($validate->getError());
  175. }
  176. // 验证图形验证码
  177. // if (!CaptchaApi::check($data['captchaCode'], $data['captchaKey'])) {
  178. // throwError('很抱歉,图形验证码不正确');
  179. // }
  180. }
  181. public function checkCaptcha( $captchaCode = '', $email = '')
  182. {
  183. $localCode = Cache::get('captchaSMS.'.$email);
  184. if (empty($localCode) || empty($localCode['code']) || $localCode['code'] != $captchaCode){
  185. throwError('Sorry,your captcha is invalid');
  186. }
  187. //dd($localCode);
  188. }
  189. }