-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathSMTP.php
More file actions
233 lines (214 loc) · 7.94 KB
/
Copy pathSMTP.php
File metadata and controls
233 lines (214 loc) · 7.94 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
<?php
/**
* 超简洁SMTP类,支持附件,支持验证
* @author chenall
* @link http://chenall.net/post/cs_smtp/
* @since
* 2017-01-24 <路漫漫 [email protected]>
* 重写为单例模式
* 用SMTP::Ins()获取实例
* 2017-01-23 <路漫漫 [email protected]>
* 简化调用操作,只需new SMTP()就完事。(注意填写配置文件)
* 支持中文附件名。
* 另外注意SSL的一定要加'host' => 'ssl://smtp.qq.com'
* 2012-12-08
* 添加AddURL函数,可以直接从某个网址上下载文件并作为附件发送。
* 修正由于发送人和接收人邮件地址没有使用"<>"126邮箱SMTP无法使用的问题。
* 2012-12-06
* 添加reset函数,重置连接,这样可以发送多个邮件。
* 2012-12-05
* 发送附件的代码整合到send函数中,减少变量的使用,快速输出,节省内存占用;
* 2012-12-04
* 第一个版本
*
* @example
* 1. 初始化:连接到服务器
* $mail = SMTP::Ins()
* if ($mail->errstr) //如果连接出错
* die($mail->errstr);
* $mail->AddFile($file,$name) //服务器上的文件,可以指定文件名;
* 2. 发送邮件
* $mail->send($to,$subject,$body)
* $to 收件人,多个使用','分隔
* $subject 邮件主题,可选。
* $body 邮件主体内容,可选
*
*/
namespace Base\Tool;
class SMTP {
private $CRLF = "\r\n";
private $from;
private $smtp = null;
private static $obj = null;
//附件
private $attach = array();
public $debug = false;
public $errstr = '';
private function __construct() {
$cfg = Config('smtp');
if (empty($cfg['host']))
die('SMTP服务器未指定!');
$this->smtp = fsockopen($cfg['host'],$cfg['port'],$errno,$errstr,5);
if (empty($this->smtp))
{
$this->errstr = '错误'.$errno.':'.$errstr;
return;
}
$this->smtp_log(fread($this->smtp, 515));
if (intval($this->smtp_cmd('EHLO '.$cfg['host'])) != 250 && intval($this->smtp_cmd('HELO '.$cfg['host'])))
return $this->errstr = '服务器不支持!';
$this->errstr = '';
if (!$this->login($cfg['user'],$cfg['pass']))
die($this->errstr);
}
//关闭clone
private function __clone() {}
public static function Ins(){
if (self::$obj===null){
self::$obj = new self();
}
return self::$obj;
}
private function AttachURL($url,$name)
{
$info = parse_url($url);
isset($info['port']) || $info['port'] = 80;
isset($info['path']) || $info['path'] = '/';
isset($info['query']) || $info['query'] = '';
$down = fsockopen($info['host'],$info['port'],$errno,$errstr,5);
if (!$down)
return false;
$out = "GET ".$info['path'].'?'.$info['query']." HTTP/1.1\r\n";
$out .="Host: ".$info['host']."\r\n";
$out .= "Connection: Close\r\n\r\n";
fwrite($down, $out);
$filesize = 0;
while (!feof($down)) {
$a = fgets($down,515);
if ($a == "\r\n")
break;
$a = explode(':',$a);
if (strcasecmp($a[0],'Content-Length') == 0)
$filesize = intval($a[1]);
}
$sendsize = 0;
echo "TotalSize: ".$filesize."\r\n";
$i = 0;
while (!feof($down)) {
$data = fread($down,0x2000);
$sendsize += strlen($data);
if ($filesize)
{
echo "$i Send:".$sendsize."\r";
ob_flush();
flush();
}
++$i;
fwrite($this->smtp,chunk_split(base64_encode($data)));
}
echo "\r\n";
fclose($down);
return ($filesize>0)?$filesize==$sendsize:true;
}
function __destruct() {
if ($this->smtp)
$this->smtp_cmd('QUIT');//发送退出命令
}
//即时输出调试使用
private function smtp_log($msg) {
if ($this->debug == false)
return;
echo $msg."\r\n";
ob_flush();
flush();
}
function reset() {
$this->attach = null;
$this->smtp_cmd('RSET');
}
//SMTP命令发送和收收
function smtp_cmd($msg) {
fputs($this->smtp,$msg.$this->CRLF);
$this->smtp_log('SEND:'. substr($msg,0,80));
$res = fread($this->smtp, 515);
$this->smtp_log($res);
$this->errstr = $res;
return $res;
}
function AddURL($url,$name) {
$this->attach[$name] = $url;
}
//添加文件附件
function AddFile($file,$name = '') {
if (file_exists($file)) {
if (!empty($name))
return $this->attach[$name] = $file;
$fn = pathinfo($file);
return $this->attach[$fn['basename']] = $file;
}
return false;
}
function send($to,$subject='',$body = '') {
$this->smtp_cmd("MAIL FROM: <".$this->from.'>');
$mailto = explode(',',$to);
foreach($mailto as $email_to)
$this->smtp_cmd("RCPT TO: <".$email_to.">");
if (intval($this->smtp_cmd("DATA")) != 354)//正确的返回必须是354
return false;
fwrite($this->smtp,"To:$to\nFrom: ".$this->from."\nSubject: $subject\n");
$boundary = uniqid("--BY_路漫漫_",true);
$headers = "MIME-Version: 1.0".$this->CRLF;
$headers .= "From: <".$this->from.">".$this->CRLF;
$headers .= "Content-type: multipart/mixed; boundary= $boundary\n\n".$this->CRLF;//headers结束要至少两个换行
fwrite($this->smtp,$headers);
// $msg = "--$boundary\nContent-Type: text/html;charset=\"ISO-8859-1\"\nContent-Transfer-Encoding: base64\n\n";
$msg = "--$boundary\nContent-Type: text/html;charset=\"UTF-8\"\nContent-Transfer-Encoding: base64\n\n";
$msg .= chunk_split(base64_encode($body));
fwrite($this->smtp,$msg);
$files = '';
$errinfo = '';
foreach($this->attach as $name=>$file)
{
$files .= $name;
$msg = "--$boundary\n--$boundary\n";
$msg .= "Content-Type: application/octet-stream; name=\"".iconv("UTF-8", "GB2312",$name)."\"\n";
$msg .= "Content-Disposition: attachment; filename=\"".iconv("UTF-8", "GB2312",$name)."\"\n";
$msg .= "Content-transfer-encoding: base64\n\n";
fwrite($this->smtp,$msg);
//URL like http:///file://
if (substr($file,4,1) == ':') {
if (!$this->AttachURL($file,$name))
$errinfo .= '文件下载错误:'.$name.",文件可能是错误的\r\n$file";
}else{
//使用BASE64编码,再用chunk_split大卸八块(每行76个字符)
fwrite($this->smtp,chunk_split(base64_encode(file_get_contents($file))));
}
}
if (!empty($errinfo))
{
$msg = "--$boundary\n--$boundary\n";
$msg .= "Content-Type: application/octet-stream; name=Error.log\n";
$msg .= "Content-Disposition: attachment; filename=Error.log\n";
$msg .= "Content-transfer-encoding: base64\n\n";
fwrite($this->smtp,$msg);
fwrite($this->smtp,chunk_split(base64_encode($errinfo)));
}
//结束DATA发送,服务器会返回执行结果,如果代码不是250则出错。
return intval($this->smtp_cmd("--$boundary--\n\r\n.")) == 250;
}
function login($su,$sp) {
if (empty($this->smtp))
return false;
$res = $this->smtp_cmd("AUTH LOGIN");
if (intval($res)>400)
return !$this->errstr = $res;
$res = $this->smtp_cmd(base64_encode($su));
if (intval($res)>400)
return !$this->errstr = $res;
$res = $this->smtp_cmd(base64_encode($sp));
if (intval($res)>400)
return !$this->errstr = $res;
$this->from = $su;
return true;
}
}