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) { |
|
|
|
|
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)) { |
|
|
|
|
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
|
|
|
|