1 | <?php |
||
2 | /** |
||
3 | * 邮件 |
||
4 | * |
||
5 | * @author mybsdc <[email protected]> |
||
6 | * @date 2019/5/12 |
||
7 | * @time 16:38 |
||
8 | */ |
||
9 | |||
10 | namespace Luolongfei\Lib; |
||
11 | |||
12 | use Luolongfei\App\Exceptions\LlfException; |
||
13 | use PHPMailer\PHPMailer\PHPMailer; |
||
14 | use PHPMailer\PHPMailer\Exception as MailException; |
||
15 | |||
16 | class Mail |
||
17 | { |
||
18 | /** |
||
19 | * @var PHPMailer |
||
20 | */ |
||
21 | protected static $mail; |
||
22 | |||
23 | /** |
||
24 | * @return PHPMailer |
||
25 | * @throws MailException |
||
26 | * @throws \Exception |
||
27 | */ |
||
28 | public static function mail() |
||
29 | { |
||
30 | if (!self::$mail instanceof PHPMailer) { |
||
0 ignored issues
–
show
introduced
by
![]() |
|||
31 | self::$mail = new PHPMailer(true); |
||
32 | |||
33 | // 邮件服务配置 |
||
34 | $username = config('mail.username'); |
||
35 | $password = config('mail.password'); |
||
36 | if (stripos($username, '@gmail.com') !== false) { |
||
37 | $host = 'smtp.gmail.com'; |
||
38 | $secure = 'tls'; |
||
39 | $port = 587; |
||
40 | } else if (stripos($username, '@qq.com') !== false) { |
||
41 | $host = 'smtp.qq.com'; |
||
42 | $secure = 'tls'; |
||
43 | $port = 587; |
||
44 | } else if (stripos($username, '@163.com') !== false) { |
||
45 | $host = 'smtp.163.com'; |
||
46 | $secure = 'ssl'; |
||
47 | $port = 465; |
||
48 | } else if (stripos($username, '@vip.163.com') !== false) { |
||
49 | $host = 'smtp.vip.163.com'; |
||
50 | $secure = 'ssl'; |
||
51 | $port = 465; |
||
52 | } else if (stripos($username, '@outlook.com') !== false) { |
||
53 | $host = 'smtp.office365.com'; |
||
54 | $secure = 'starttls'; |
||
55 | $port = 587; |
||
56 | } else { |
||
57 | throw new \Exception('不受支持的邮箱。目前仅支持谷歌邮箱、QQ邮箱以及163邮箱,推荐使用谷歌邮箱。'); |
||
58 | } |
||
59 | |||
60 | self::$mail->SMTPDebug = config('debug') ? 2 : 0; // Debug 0:关闭 1:客户端信息 2:客户端和服务端信息 |
||
61 | self::$mail->isSMTP(); // 告诉PHPMailer使用SMTP |
||
62 | self::$mail->Host = $host; // SMTP服务器 |
||
63 | self::$mail->SMTPAuth = true; // 启用SMTP身份验证 |
||
64 | self::$mail->Username = $username; // 账号 |
||
65 | self::$mail->Password = $password; // 密码或授权码 |
||
66 | self::$mail->SMTPSecure = $secure; // 将加密系统设置为使用 - ssl(不建议使用)或tls |
||
67 | self::$mail->Port = $port; // 设置SMTP端口号 - tsl使用587端口,ssl使用465端口 |
||
68 | self::$mail->CharSet = 'UTF-8'; // 防止中文邮件乱码 |
||
69 | self::$mail->setLanguage('zh_cn', VENDOR_PATH . '/phpmailer/phpmailer/language/'); // 设置语言 |
||
70 | self::$mail->setFrom($username, 'im robot'); // 发件人 |
||
71 | } |
||
72 | |||
73 | return self::$mail; |
||
74 | } |
||
75 | |||
76 | /** |
||
77 | * 发送邮件 |
||
78 | * |
||
79 | * @param string $subject 标题 |
||
80 | * @param string | array $content 正文 |
||
81 | * @param string $to 收件人,选传 |
||
82 | * @param string $template 模板,选传 |
||
83 | * |
||
84 | * @return bool |
||
85 | * @throws \Exception |
||
86 | */ |
||
87 | public static function send($subject, $content, $to = '', $template = '') |
||
88 | { |
||
89 | if (config('mail.enable') === false) { |
||
90 | system_log('由于没有启用邮件功能,故本次不通过邮件送信。'); |
||
91 | |||
92 | return false; |
||
93 | } |
||
94 | |||
95 | $to = $to ?: config('mail.to'); |
||
96 | if (!$to) { |
||
97 | throw new LlfException(env('ON_GITHUB_ACTIONS') ? 34520011 : 34520012); |
||
98 | } |
||
99 | |||
100 | self::mail()->addAddress($to, config('mail.toName', '主人')); // 添加收件人,参数2选填 |
||
101 | self::mail()->addReplyTo(config('mail.replyTo', '[email protected]'), config('mail.replyToName', '作者')); // 备用回复地址,收到的回复的邮件将被发到此地址 |
||
102 | |||
103 | /** |
||
104 | * 抄送和密送都是添加收件人,抄送方式下,被抄送者知道除被密送者外的所有的收件人,密送方式下, |
||
105 | * 被密送者知道所有的被抄送者,但不知道其它的被密送者。 |
||
106 | * 抄送好比@,密送好比私信。 |
||
107 | */ |
||
108 | // self::mail()->addCC('[email protected]'); // 抄送 |
||
109 | // self::mail()->addBCC('[email protected]'); // 密送 |
||
110 | |||
111 | // 添加附件,参数2选填 |
||
112 | // self::mail()->addAttachment('README.md', '说明.txt'); |
||
113 | |||
114 | // 内容 |
||
115 | self::mail()->Subject = $subject; // 标题 |
||
116 | |||
117 | /** |
||
118 | * 正文 |
||
119 | * 使用html文件内容作为正文,其中的图片将被base64编码,另确保html样式为内联形式,且某些样式可能需要!important方能正常显示, |
||
120 | * msgHTML方法的第二个参数指定html内容中图片的路径,在转换时会拼接html中图片的相对路径得到完整的路径,最右侧无需“/”,PHPMailer |
||
121 | * 源码里有加。css中的背景图片不会被转换,这是PHPMailer已知问题,建议外链。 |
||
122 | * 此处也可替换为: |
||
123 | * self::mail()->isHTML(true); // 设为html格式 |
||
124 | * self::mail()->Body = '正文'; // 支持html |
||
125 | * self::mail()->AltBody = 'This is an HTML-only message. To view it, activate HTML in your email application.'; // 纯文本消息正文。不支持html预览的邮件客户端将显示此预览消息,其它情况将显示正常的body |
||
126 | */ |
||
127 | $template = file_get_contents(RESOURCES_PATH . '/mail/' . ($template ?: 'default') . '.html'); |
||
128 | if (is_array($content)) { |
||
129 | array_unshift($content, $template); |
||
130 | $message = call_user_func_array('sprintf', $content); |
||
131 | } else if (is_string($content)) { |
||
0 ignored issues
–
show
|
|||
132 | $message = $content; |
||
133 | } else { |
||
134 | throw new MailException('邮件内容格式错误,仅支持传入数组或字符串。'); |
||
135 | } |
||
136 | |||
137 | self::mail()->msgHTML($message, APP_PATH . '/mail'); |
||
138 | |||
139 | if (!self::mail()->send()) throw new MailException(self::mail()->ErrorInfo); |
||
140 | |||
141 | return true; |
||
142 | } |
||
143 | } |
||
144 |