MailCaptcha.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  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\index\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. protected int $expireTime = 300;
  35. //可重复使用次数
  36. protected int $checkTimes = 5;
  37. /**
  38. * 发送邮件验证码
  39. * @param array $data
  40. * @return bool
  41. * @throws BaseException
  42. */
  43. public function handle(array $data): bool
  44. {
  45. // 数据验证
  46. $this->validate($data);
  47. // 执行发送短信
  48. if (!$this->sendCaptcha($data['mobile'])) {
  49. return false;
  50. }
  51. return true;
  52. }
  53. /**
  54. * 执行发送邮箱验证码
  55. * @param string $email
  56. * @return bool
  57. */
  58. public function sendCaptcha(string $email): bool
  59. {
  60. // 缓存发送记录并判断次数
  61. if (!$this->record($email)) {
  62. return false;
  63. }
  64. // 生成验证码
  65. //$smsCaptcha = CaptchaApi::createSMS($email);
  66. $smsCaptcha = (string)mt_rand(100000, 999999);
  67. Cache::set("captchaSMS.{$email}", ['code' => $smsCaptcha, 'times' => $this->checkTimes], $this->expireTime);
  68. $mail = new PHPMailer(true);
  69. //dd(config('smtp'));
  70. try {
  71. //Server settings
  72. $mail->SMTPDebug = SMTP::DEBUG_SERVER;//DEBUG_OFF,DEBUG_SERVER //Enable verbose debug output
  73. $mail->SMTPOptions = array(
  74. 'ssl' => array(
  75. 'verify_peer' => false,
  76. 'verify_peer_name' => false,
  77. 'allow_self_signed' => true
  78. )
  79. );
  80. /* $mail->isSMTP(); //Send using SMTP
  81. $mail->Host = config('smtp.host'); //Set the SMTP server to send through
  82. $mail->SMTPAuth = true; //Enable SMTP authentication
  83. $mail->Username = config('smtp.username'); //SMTP username
  84. $mail->Password = config('smtp.password'); //SMTP password
  85. $mail->SMTPSecure = PHPMailer::ENCRYPTION_SMTPS; //Enable implicit TLS encryption
  86. $mail->Port = config('smtp.port'); */ //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`
  87. //Recipients
  88. //$mail->setFrom(config('smtp.from_address'), config('smtp.from_name'));
  89. $mail->isSMTP(); //Send using SMTP
  90. $mail->Host = 'tls://smtp.office365.com';//config('smtp.host'); //Set the SMTP server to send through
  91. $mail->SMTPAuth = true; //Enable SMTP authentication
  92. $mail->Username = 'register@freeshippingvapes.com';//config('smtp.username'); //SMTP username
  93. $mail->Password = 'Iloveyou1@#';//config('smtp.password'); //SMTP password
  94. $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; //Enable implicit TLS encryption
  95. $mail->Port = 587;//;config('smtp.port');
  96. $mail->setFrom('register@freeshippingvapes.com', 'Free Shipping Vps');
  97. $mail->addAddress($email, 'FSV'); //Add a recipient
  98. //$mail->addAddress('ellen@example.com'); //Name is optional
  99. //$mail->addReplyTo('info@example.com', 'Information');
  100. //$mail->addCC('cc@example.com');
  101. //$mail->addBCC('bcc@example.com');
  102. //Attachments
  103. //$mail->addAttachment('/var/tmp/file.tar.gz'); //Add attachments
  104. //$mail->addAttachment('/tmp/image.jpg', 'new.jpg'); //Optional name
  105. //Content
  106. //$mail->isHTML(true); //Set email format to HTML
  107. $mail->Subject = 'Password';
  108. $mail->Body = 'Your code is ' . $smsCaptcha . '.Please use it in 15 minutes';
  109. $mail->AltBody = 'This is the Your Code for FreeShippingV';
  110. $mail->send();
  111. //echo 'Message has been sent';
  112. } catch (Exception $e) {
  113. //echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
  114. Log::error(__CLASS__ . ':' . __METHOD__ . $e->getMessage() . '---' . $mail->ErrorInfo);
  115. Log::error(__CLASS__ . ':' . __METHOD__ . ',error:' . $e->getMessage() . ',mailError:' . $mail->ErrorInfo);
  116. return false;
  117. }
  118. return true;
  119. }
  120. /**
  121. * 发送营销文本邮件
  122. * @param string $email
  123. * @param string $subject
  124. * @param string $body
  125. * @param string $altBody
  126. * @param bool $isHtml
  127. * @param string $name
  128. * @return bool
  129. */
  130. public function sendText(string $email, string $subject = '', string $body = '', string $altBody = '', bool $isHtml = false, string $name = 'vip'): bool
  131. {
  132. $mail = new PHPMailer(true);
  133. try {
  134. //Server settings
  135. $mail->SMTPDebug = SMTP::DEBUG_OFF; //Enable verbose debug output
  136. $mail->SMTPOptions = array(
  137. 'ssl' => array(
  138. 'verify_peer' => false,
  139. 'verify_peer_name' => false,
  140. 'allow_self_signed' => true
  141. )
  142. );
  143. $mail->isSMTP(); //Send using SMTP //SMTP password
  144. $mail->Host = config('smtp.host'); //Set the SMTP server to send through
  145. $mail->SMTPAuth = true; //Enable SMTP authentication
  146. $mail->Username = config('smtp.username'); //SMTP username
  147. $mail->Password = config('smtp.password');
  148. $mail->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS; //Enable implicit TLS encryption
  149. $mail->Port = config('smtp.port'); //TCP port to connect to; use 587 if you have set `SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS`
  150. //Recipients
  151. $mail->setFrom(config('smtp.from_address'), config('smtp.from_name'));
  152. $mail->addAddress($email, $name); //Add a recipient
  153. //Content
  154. if ($isHtml) {
  155. $mail->isHTML(true); //Set email format to HTML
  156. }
  157. $mail->Subject = $subject;
  158. $mail->Body = $body;
  159. if (!empty($altBody)) {
  160. $mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
  161. }
  162. $mail->send();
  163. //echo 'Message has been sent';
  164. } catch (Exception $e) {
  165. //echo "Message could not be sent. Mailer Error: {$mail->ErrorInfo}";
  166. Log::error(__CLASS__ . ':' . __METHOD__ . ',error:' . $e->getMessage() . ',mailError:' . $mail->ErrorInfo);
  167. return false;
  168. }
  169. return true;
  170. }
  171. /**
  172. * 记录短信验证码发送记录并判断是否超出发送限制
  173. * @param string $mobile
  174. * @return bool
  175. */
  176. private function record(string $email): bool
  177. {
  178. // 获取发送记录缓存
  179. $record = Cache::get("sendCaptchaEmail.$email");
  180. // 写入缓存:记录剩余发送次数
  181. if (empty($record)) {
  182. Cache::set("sendCaptchaEmail.$email", ['times' => $this->sendTimes - 1], $this->safeTime);
  183. return true;
  184. }
  185. // 判断发送次数是否合法
  186. if ($record['times'] <= 0) {
  187. $this->error = 'Sorry,up to the limit today.';
  188. return false;
  189. }
  190. // 发送次数递减
  191. Cache::update("sendCaptchaEmail.$email", ['times' => $record['times'] - 1]);
  192. return true;
  193. }
  194. /**
  195. * 数据验证
  196. * @param array $data
  197. * @throws BaseException
  198. */
  199. public function validate(array $data)
  200. {
  201. // 数据验证
  202. $validate = new ValidateEmailCaptcha;
  203. if (!$validate->check($data)) {
  204. throwError($validate->getError());
  205. }
  206. // 验证图形验证码
  207. // if (!CaptchaApi::check($data['captchaCode'], $data['captchaKey'])) {
  208. // throwError('很抱歉,图形验证码不正确');
  209. // }
  210. }
  211. public function checkCaptcha($captchaCode = '', $email = '')
  212. {
  213. log_record('captchaCode:' . $captchaCode.',email:' . $email,'info');
  214. //todo
  215. if (config('smtp.app_debug') && $captchaCode == '888888') {
  216. return true;
  217. }
  218. $localCode = Cache::get('captchaSMS.' . $email);
  219. if (empty($localCode) || empty($localCode['code']) || $localCode['code'] != $captchaCode) {
  220. throwError('Sorry, the code is invalid!');
  221. }
  222. return true;
  223. }
  224. }