Xataface Email Module  0.3.2
Email/Mailmerge Module for Xataface
 All Data Structures Files Functions Variables Pages
SMTP4.php
Go to the documentation of this file.
1 <?php
2 
3 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4  * *
5  * XPertMailer is a PHP Mail Class that can send and read messages in MIME format. *
6  * This file is part of the XPertMailer package (http://xpertmailer.sourceforge.net/) *
7  * Copyright (C) 2007 Tanase Laurentiu Iulian *
8  * *
9  * This library is free software; you can redistribute it and/or modify it under the *
10  * terms of the GNU Lesser General Public License as published by the Free Software *
11  * Foundation; either version 2.1 of the License, or (at your option) any later version. *
12  * *
13  * This library is distributed in the hope that it will be useful, but WITHOUT ANY *
14  * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A *
15  * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. *
16  * *
17  * You should have received a copy of the GNU Lesser General Public License along with *
18  * this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, *
19  * Fifth Floor, Boston, MA 02110-1301, USA *
20  * *
21  * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
22 
23 if (!class_exists('MIME4')) require_once 'MIME4.php';
24 
25 $_RESULT = array();
26 
27 class SMTP4 {
28 
29  var $CRLF = "\r\n";
30  var $PORT = 25;
31  var $TOUT = 30;
32  var $COUT = 5;
33  var $BLEN = 1024;
34 
35  function _cres($conn = null, &$resp, $code1 = null, $code2 = null, $debug = null) {
36  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
37  $err = array();
38  if (!is_resource($conn)) $err[] = 'invalid resource connection';
39  if (!(is_int($code1) && $code1 > 99 && $code1 < 1000)) $err[] = 'invalid 1 code value';
40  if ($code2 != null) {
41  if (!(is_int($code2) && $code2 > 99 && $code2 < 1000)) $err[] = 'invalid 2 code value';
42  }
43  if (count($err) > 0) return FUNC4::trace($debug, implode(', ', $err), 1);
44  else {
45  $_smtp = new SMTP4;
46  $ret = true;
47  do {
48  if ($result = fgets($conn, $_smtp->BLEN)) {
49  $resp[] = $result;
50  $rescode = substr($result, 0, 3);
51  if (!($rescode == $code1 || $rescode == $code2)) {
52  $ret = false;
53  break;
54  }
55  } else {
56  $resp[] = 'can not read';
57  $ret = false;
58  break;
59  }
60  } while ($result[3] == '-');
61  return $ret;
62  }
63  }
64 
65  function mxconnect($host = null, $port = null, $tout = null, $name = null, $context = null, $debug = null) {
66  global $_RESULT;
67  $_RESULT = array();
68  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
69  if (!is_string($host)) FUNC4::trace($debug, 'invalid host type');
70  else {
71  $host = strtolower(trim($host));
72  if (!($host != '' && FUNC4::is_hostname($host, true, $debug))) FUNC4::trace($debug, 'invalid host value');
73  }
74  $res = FUNC4::is_win() ? FUNC4::getmxrr_win($host, $arr, $debug) : getmxrr($host, $arr);
75  $con = false;
76  if ($res) {
77  foreach ($arr as $mx) {
78  if ($con = SMTP4::connect($mx, $port, null, null, null, $tout, $name, $context, null, $debug)) break;
79  }
80  }
81  if (!$con) $con = SMTP4::connect($host, $port, null, null, null, $tout, $name, $context, null, $debug);
82  return $con;
83  }
84 
85  function connect($host = null, $port = null, $user = null, $pass = null, $vssl = null, $tout = null, $name = null, $context = null, $login = null, $debug = null) {
86  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
87  global $_RESULT;
88  $_RESULT = $err = array();
89  $_smtp = new SMTP4;
90  if ($port == null) $port = $_smtp->PORT;
91  if ($tout == null) $tout = $_smtp->TOUT;
92  if (!is_string($host)) $err[] = 'invalid host type';
93  else {
94  $host = strtolower(trim($host));
95  if (!($host != '' && ($host == 'localhost' || FUNC4::is_ipv4($host) || FUNC4::is_hostname($host, true, $debug)))) $err[] = 'invalid host value';
96  }
97  if (!(is_int($port) && $port > 0)) $err[] = 'invalid port value';
98  if ($user != null) {
99  if (!is_string($user)) $err[] = 'invalid username type';
100  else if (($user = FUNC4::str_clear($user)) == '') $err[] = 'invalid username value';
101  }
102  if ($pass != null) {
103  if (!is_string($pass)) $err[] = 'invalid password type';
104  else if (($pass = FUNC4::str_clear($pass)) == '') $err[] = 'invalid password value';
105  }
106  if (($user != null && $pass == null) || ($user == null && $pass != null)) $err[] = 'invalid username/password combination';
107  if ($vssl != null) {
108  if (!is_string($vssl)) $err[] = 'invalid ssl version type';
109  else {
110  $vssl = strtolower($vssl);
111  if (!($vssl == 'tls' || $vssl == 'ssl' || $vssl == 'sslv2' || $vssl == 'sslv3')) $err[] = 'invalid ssl version value';
112  }
113  }
114  if (!(is_int($tout) && $tout > 0)) $err[] = 'invalid timeout value';
115  if ($name != null) {
116  if (!is_string($name)) $err[] = 'invalid name type';
117  else {
118  $name = strtolower(trim($name));
119  if (!($name != '' && ($name == 'localhost' || FUNC4::is_ipv4($name) || FUNC4::is_hostname($name, true, $debug)))) $err[] = 'invalid name value';
120  }
121  } else $name = '127.0.0.1';
122  if ($context != null && !is_resource($context)) $err[] = 'invalid context type';
123  if ($login != null) {
124  $login = strtolower(trim($login));
125  if (!($login == 'login' || $login == 'plain' || $login == 'cram-md5')) $err[] = 'invalid authentication type value';
126  }
127  if (count($err) > 0) FUNC4::trace($debug, implode(', ', $err));
128  else {
129  $ret = false;
130  $prt = ($vssl == null) ? 'tcp' : $vssl;
131  $conn = ($context == null) ? fsockopen($prt.'://'.$host, $port, $errno, $errstr, $tout) : fsockopen($prt.'://'.$host, $port, $errno, $errstr, $tout, $context);
132  if (!$conn) $_RESULT[101] = $errstr;
133  else if (!socket_set_timeout($conn, $_smtp->COUT)) $_RESULT[102] = 'could not set socket timeout';
134  else if (!SMTP4::_cres($conn, $resp, 220, null, $debug)) $_RESULT[103] = $resp;
135  else {
136  $continue = true;
137  if (!SMTP4::ehlo($conn, $name, $debug)) $continue = SMTP4::helo($conn, $name, $debug);
138  if ($continue) {
139  if ($user == null) $ret = true;
140  else if ($login != null) $ret = SMTP4::auth($conn, $user, $pass, $login, $debug);
141  else {
142  list($code, $arr) = each($_RESULT);
143  $auth['default'] = $auth['login'] = $auth['plain'] = $auth['cram-md5'] = false;
144  foreach ($arr as $line) {
145  if (substr($line, 0, strlen('250-AUTH ')) == '250-AUTH ') {
146  foreach (explode(' ', substr($line, strlen('250-AUTH '))) as $type) {
147  $type = strtolower(trim($type));
148  if ($type == 'login' || $type == 'plain' || $type == 'cram-md5') $auth[$type] = true;
149  }
150  } else if (substr($line, 0, strlen('250 AUTH=')) == '250 AUTH=') {
151  $expl = explode(' ', strtolower(trim(substr($line, strlen('250 AUTH=')))), 2);
152  if ($expl[0] == 'login' || $expl[0] == 'plain' || $expl[0] == 'cram-md5') $auth['default'] = $expl[0];
153  }
154  }
155  if ($auth['default']) $ret = SMTP4::auth($conn, $user, $pass, $auth['default'], $debug);
156  if (!$ret && $auth['login'] && $auth['default'] != 'login') $ret = SMTP4::auth($conn, $user, $pass, 'login', $debug);
157  if (!$ret && $auth['plain'] && $auth['default'] != 'plain') $ret = SMTP4::auth($conn, $user, $pass, 'plain', $debug);
158  if (!$ret && $auth['cram-md5'] && $auth['default'] != 'cram-md5') $ret = SMTP4::auth($conn, $user, $pass, 'cram-md5', $debug);
159  if (!$ret && !$auth['login'] && $auth['default'] != 'login') $ret = SMTP4::auth($conn, $user, $pass, 'login', $debug);
160  if (!$ret && !$auth['plain'] && $auth['default'] != 'plain') $ret = SMTP4::auth($conn, $user, $pass, 'plain', $debug);
161  if (!$ret && !$auth['cram-md5'] && $auth['default'] != 'cram-md5') $ret = SMTP4::auth($conn, $user, $pass, 'cram-md5', $debug);
162  }
163  }
164  }
165  if (!$ret) {
166  if (is_resource($conn)) SMTP4::disconnect($conn, $debug);
167  $conn = false;
168  }
169  return $conn;
170  }
171  }
172 
173  function send($conn = null, $addrs = null, $mess = null, $from = null, $debug = null) {
174  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
175  global $_RESULT;
176  $_RESULT = $err = array();
177  if (!is_resource($conn)) $err[] = 'invalid resource connection';
178  if (!is_array($addrs)) $err[] = 'invalid to address type';
179  else {
180  $aver = true;
181  if (count($addrs) > 0) {
182  foreach ($addrs as $addr) {
183  if (!FUNC4::is_mail($addr)) {
184  $aver = false;
185  break;
186  }
187  }
188  } else $aver = false;
189  if (!$aver) $err[] = 'invalid to address value';
190  }
191  if (!is_string($mess)) $err[] = 'invalid message value';
192  if ($from == null) {
193  $from = @ini_get('sendmail_from');
194  if ($from == '' || !FUNC4::is_mail($from)) $from = (isset($_SERVER['SERVER_ADMIN']) && FUNC4::is_mail($_SERVER['SERVER_ADMIN'])) ? $_SERVER['SERVER_ADMIN'] : 'postmaster@localhost';
195  } else {
196  if (!is_string($from)) $err[] = 'invalid from address type';
197  else if (!($from != '' && FUNC4::is_mail($from))) $err[] = 'invalid from address value';
198  }
199  if (count($err) > 0) FUNC4::trace($debug, implode(', ', $err));
200  else {
201  $ret = false;
202  if (SMTP4::from($conn, $from, $debug)) {
203  $continue = true;
204  foreach ($addrs as $dest) {
205  if (!SMTP4::to($conn, $dest, $debug)) {
206  $continue = false;
207  break;
208  }
209  }
210  if ($continue) {
211  if (SMTP4::data($conn, $mess, $debug)) $ret = SMTP4::rset($conn, $debug);
212  }
213  }
214  return $ret;
215  }
216  }
217 
218  function disconnect($conn = null, $debug = null) {
219  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
220  global $_RESULT;
221  $_RESULT = array();
222  if (!is_resource($conn)) return FUNC4::trace($debug, 'invalid resource connection', 1);
223  else {
224  $_smtp = new SMTP4;
225  if (!fwrite($conn, 'QUIT'.$_smtp->CRLF)) $_RESULT[300] = 'can not write';
226  else $_RESULT[301] = 'Send QUIT';
227  return @fclose($conn);
228  }
229  }
230 
231  function quit($conn = null, $debug = null) {
232  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
233  global $_RESULT;
234  $_RESULT = array();
235  $ret = false;
236  $_smtp = new SMTP4;
237  if (!is_resource($conn)) FUNC4::trace($debug, 'invalid resource connection');
238  else if (!fwrite($conn, 'QUIT'.$_smtp->CRLF)) $_RESULT[302] = 'can not write';
239  else {
240  $_RESULT[303] = ($vget = @fgets($conn, $_smtp->BLEN)) ? $vget : 'can not read';
241  $ret = true;
242  }
243  return $ret;
244  }
245 
246  function helo($conn = null, $host = null, $debug = null) {
247  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
248  global $_RESULT;
249  $_RESULT = $err = array();
250  if (!is_resource($conn)) $err[] = 'invalid resource connection';
251  if (!is_string($host)) $err[] = 'invalid host type';
252  else {
253  $host = strtolower(trim($host));
254  if (!($host != '' && ($host == 'localhost' || FUNC4::is_ipv4($host) || FUNC4::is_hostname($host, true, $debug)))) $err[] = 'invalid host value';
255  }
256  if (count($err) > 0) FUNC4::trace($debug, implode(', ', $err));
257  else {
258  $ret = false;
259  $_smtp = new SMTP4;
260  if (!fwrite($conn, 'HELO '.$host.$_smtp->CRLF)) $_RESULT[304] = 'can not write';
261  else if (!SMTP4::_cres($conn, $resp, 250, null, $debug)) $_RESULT[305] = $resp;
262  else {
263  $_RESULT[306] = $resp;
264  $ret = true;
265  }
266  return $ret;
267  }
268  }
269 
270  function ehlo($conn = null, $host = null, $debug = null) {
271  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
272  global $_RESULT;
273  $_RESULT = $err = array();
274  if (!is_resource($conn)) $err[] = 'invalid resource connection';
275  if (!is_string($host)) $err[] = 'invalid host type';
276  else {
277  $host = strtolower(trim($host));
278  if (!($host != '' && ($host == 'localhost' || FUNC4::is_ipv4($host) || FUNC4::is_hostname($host, true, $debug)))) $err[] = 'invalid host value';
279  }
280  if (count($err) > 0) FUNC4::trace($debug, implode(', ', $err));
281  else {
282  $ret = false;
283  $_smtp = new SMTP4;
284  if (!fwrite($conn, 'EHLO '.$host.$_smtp->CRLF)) $_RESULT[307] = 'can not write';
285  else if (!SMTP4::_cres($conn, $resp, 250, null, $debug)) $_RESULT[308] = $resp;
286  else {
287  $_RESULT[309] = $resp;
288  $ret = true;
289  }
290  return $ret;
291  }
292  }
293 
294  function auth($conn = null, $user = null, $pass = null, $type = null, $debug = null) {
295  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
296  global $_RESULT;
297  $_RESULT = $err = array();
298  if (!is_resource($conn)) $err[] = 'invalid resource connection';
299  if (!is_string($user)) $err[] = 'invalid username type';
300  else if (($user = FUNC4::str_clear($user)) == '') $err[] = 'invalid username value';
301  if (!is_string($pass)) $err[] = 'invalid password type';
302  else if (($pass = FUNC4::str_clear($pass)) == '') $err[] = 'invalid password value';
303  if ($type == null) $type = 'login';
304  if (!is_string($type)) $err[] = 'invalid authentication type';
305  else {
306  $type = strtolower(trim($type));
307  if (!($type == 'login' || $type == 'plain' || $type == 'cram-md5')) $err[] = 'invalid authentication type value';
308  }
309  if (count($err) > 0) FUNC4::trace($debug, implode(', ', $err));
310  else {
311  $ret = false;
312  $_smtp = new SMTP4;
313  if ($type == 'login') {
314  if (!fwrite($conn, 'AUTH LOGIN'.$_smtp->CRLF)) $_RESULT[310] = 'can not write';
315  else if (!SMTP4::_cres($conn, $resp, 334, null, $debug)) $_RESULT[311] = $resp;
316  else if (!fwrite($conn, base64_encode($user).$_smtp->CRLF)) $_RESULT[312] = 'can not write';
317  else if (!SMTP4::_cres($conn, $resp, 334, null, $debug)) $_RESULT[313] = $resp;
318  else if (!fwrite($conn, base64_encode($pass).$_smtp->CRLF)) $_RESULT[314] = 'can not write';
319  else if (!SMTP4::_cres($conn, $resp, 235, null, $debug)) $_RESULT[315] = $resp;
320  else {
321  $_RESULT[316] = $resp;
322  $ret = true;
323  }
324  } else if ($type == 'plain') {
325  if (!fwrite($conn, 'AUTH PLAIN '.base64_encode($user.chr(0).$user.chr(0).$pass).$_smtp->CRLF)) $_RESULT[317] = 'can not write';
326  else if (!SMTP4::_cres($conn, $resp, 235, null, $debug)) $_RESULT[318] = $resp;
327  else {
328  $_RESULT[319] = $resp;
329  $ret = true;
330  }
331  } else if ($type == 'cram-md5') {
332  if (!fwrite($conn, 'AUTH CRAM-MD5'.$_smtp->CRLF)) $_RESULT[200] = 'can not write';
333  else if (!SMTP4::_cres($conn, $resp, 334, null, $debug)) $_RESULT[201] = $resp;
334  else {
335  if (strlen($pass) > 64) $pass = pack('H32', md5($pass));
336  if (strlen($pass) < 64) $pass = str_pad($pass, 64, chr(0));
337  $pad1 = substr($pass, 0, 64) ^ str_repeat(chr(0x36), 64);
338  $pad2 = substr($pass, 0, 64) ^ str_repeat(chr(0x5C), 64);
339  $chal = substr($resp[count($resp)-1], 4);
340  $innr = pack('H32', md5($pad1.base64_decode($chal)));
341  if (!fwrite($conn, base64_encode($user.' '.md5($pad2.$innr)).$_smtp->CRLF)) $_RESULT[202] = 'can not write';
342  else if (!SMTP4::_cres($conn, $resp, 235, null, $debug)) $_RESULT[203] = $resp;
343  else {
344  $_RESULT[204] = $resp;
345  $ret = true;
346  }
347  }
348  }
349  return $ret;
350  }
351  }
352 
353  function from($conn = null, $addr = null, $debug = null) {
354  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
355  global $_RESULT;
356  $_RESULT = $err = array();
357  if (!is_resource($conn)) $err[] = 'invalid resource connection';
358  if (!is_string($addr)) $err[] = 'invalid from address type';
359  else if (!($addr != '' && FUNC4::is_mail($addr))) $err[] = 'invalid from address value';
360  if (count($err) > 0) FUNC4::trace($debug, implode(', ', $err));
361  else {
362  $ret = false;
363  $_smtp = new SMTP4;
364  if (!fwrite($conn, 'MAIL FROM:<'.$addr.'>'.$_smtp->CRLF)) $_RESULT[320] = 'can not write';
365  else if (!SMTP4::_cres($conn, $resp, 250, null, $debug)) $_RESULT[321] = $resp;
366  else {
367  $_RESULT[322] = $resp;
368  $ret = true;
369  }
370  return $ret;
371  }
372  }
373 
374  function to($conn = null, $addr = null, $debug = null) {
375  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
376  global $_RESULT;
377  $_RESULT = $err = array();
378  if (!is_resource($conn)) $err[] = 'invalid resource connection';
379  if (!is_string($addr)) $err[] = 'invalid to address type';
380  else if (!($addr != '' && FUNC4::is_mail($addr))) $err[] = 'invalid to address value';
381  if (count($err) > 0) FUNC4::trace($debug, implode(', ', $err));
382  else {
383  $ret = false;
384  $_smtp = new SMTP4;
385  if (!fwrite($conn, 'RCPT TO:<'.$addr.'>'.$_smtp->CRLF)) $_RESULT[323] = 'can not write';
386  else if (!SMTP4::_cres($conn, $resp, 250, 251, $debug)) $_RESULT[324] = $resp;
387  else {
388  $_RESULT[325] = $resp;
389  $ret = true;
390  }
391  return $ret;
392  }
393  }
394 
395  function data($conn = null, $mess = null, $debug = null) {
396  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
397  global $_RESULT;
398  $_RESULT = $err = array();
399  if (!is_resource($conn)) $err[] = 'invalid resource connection';
400  if (!(is_string($mess) && $mess != '')) $err[] = 'invalid message value';
401  if (count($err) > 0) FUNC4::trace($debug, implode(', ', $err));
402  else {
403  $ret = false;
404  $_smtp = new SMTP4;
405  if (!fwrite($conn, 'DATA'.$_smtp->CRLF)) $_RESULT[326] = 'can not write';
406  else if (!SMTP4::_cres($conn, $resp, 354, null, $debug)) $_RESULT[327] = $resp;
407  else {
408  $continue = true;
409  foreach (explode($_smtp->CRLF, $mess) as $line) {
410  if ($line != '' && $line[0] == '.') $line = '.'.$line;
411  if (!fwrite($conn, $line.$_smtp->CRLF)) {
412  $_RESULT[328] = 'can not write';
413  $continue = false;
414  break;
415  }
416  }
417  if ($continue) {
418  if (!fwrite($conn, '.'.$_smtp->CRLF)) $_RESULT[329] = 'can not write';
419  else if (!SMTP4::_cres($conn, $resp, 250, null, $debug)) $_RESULT[330] = $resp;
420  else {
421  $_RESULT[331] = $resp;
422  $ret = true;
423  }
424  }
425  }
426  return $ret;
427  }
428  }
429 
430  function rset($conn = null, $debug = null) {
431  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
432  global $_RESULT;
433  $_RESULT = array();
434  $ret = false;
435  $_smtp = new SMTP4;
436  if (!is_resource($conn)) FUNC4::trace($debug, 'invalid resource connection');
437  else if (!fwrite($conn, 'RSET'.$_smtp->CRLF)) $_RESULT[332] = 'can not write';
438  else if (!SMTP4::_cres($conn, $resp, 250, null, $debug)) $_RESULT[333] = $resp;
439  else {
440  $_RESULT[334] = $resp;
441  $ret = true;
442  }
443  return $ret;
444  }
445 
446  function recv($conn = null, $code1 = null, $code2 = null, $debug = null) {
447  if (!FUNC4::is_debug($debug)) $debug = debug_backtrace();
448  global $_RESULT;
449  $_RESULT = array();
450  $ret = false;
451  if (!SMTP4::_cres($conn, $resp, $code1, $code2, $debug)) $_RESULT[335] = $resp;
452  else {
453  $_RESULT[336] = $resp;
454  $ret = true;
455  }
456  return $ret;
457  }
458 
459 }
460 
461 ?>