![]() |
Xataface Email Module 0.2
Email/Mailmerge Module for Xataface
|
00001 <?php 00002 00003 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 00004 * * 00005 * XPertMailer is a PHP Mail Class that can send and read messages in MIME format. * 00006 * This file is part of the XPertMailer package (http://xpertmailer.sourceforge.net/) * 00007 * Copyright (C) 2007 Tanase Laurentiu Iulian * 00008 * * 00009 * This library is free software; you can redistribute it and/or modify it under the * 00010 * terms of the GNU Lesser General Public License as published by the Free Software * 00011 * Foundation; either version 2.1 of the License, or (at your option) any later version. * 00012 * * 00013 * This library is distributed in the hope that it will be useful, but WITHOUT ANY * 00014 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A * 00015 * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * 00016 * * 00017 * You should have received a copy of the GNU Lesser General Public License along with * 00018 * this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, * 00019 * Fifth Floor, Boston, MA 02110-1301, USA * 00020 * * 00021 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */ 00022 00023 if (!class_exists('MIME5')) require_once 'MIME5.php'; 00024 00025 $_RESULT = array(); 00026 00027 class SMTP5 { 00028 00029 const CRLF = "\r\n"; 00030 const PORT = 25; 00031 const TOUT = 30; 00032 const COUT = 5; 00033 const BLEN = 1024; 00034 00035 static private function _cres($conn = null, &$resp, $code1 = null, $code2 = null, $debug = null) { 00036 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00037 $err = array(); 00038 if (!is_resource($conn)) $err[] = 'invalid resource connection'; 00039 if (!(is_int($code1) && $code1 > 99 && $code1 < 1000)) $err[] = 'invalid 1 code value'; 00040 if ($code2 != null) { 00041 if (!(is_int($code2) && $code2 > 99 && $code2 < 1000)) $err[] = 'invalid 2 code value'; 00042 } 00043 if (count($err) > 0) return FUNC5::trace($debug, implode(', ', $err), 1); 00044 else { 00045 $ret = true; 00046 do { 00047 if ($result = fgets($conn, self::BLEN)) { 00048 $resp[] = $result; 00049 $rescode = substr($result, 0, 3); 00050 if (!($rescode == $code1 || $rescode == $code2)) { 00051 $ret = false; 00052 break; 00053 } 00054 } else { 00055 $resp[] = 'can not read'; 00056 $ret = false; 00057 break; 00058 } 00059 } while ($result[3] == '-'); 00060 return $ret; 00061 } 00062 } 00063 00064 static public function mxconnect($host = null, $port = null, $tout = null, $name = null, $context = null, $debug = null) { 00065 global $_RESULT; 00066 $_RESULT = array(); 00067 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00068 if (!is_string($host)) FUNC5::trace($debug, 'invalid host type'); 00069 else { 00070 $host = strtolower(trim($host)); 00071 if (!($host != '' && FUNC5::is_hostname($host, true, $debug))) FUNC5::trace($debug, 'invalid host value'); 00072 } 00073 $res = FUNC5::is_win() ? FUNC5::getmxrr_win($host, $arr, $debug) : getmxrr($host, $arr); 00074 $con = false; 00075 if ($res) { 00076 foreach ($arr as $mx) { 00077 if ($con = self::connect($mx, $port, null, null, null, $tout, $name, $context, null, $debug)) break; 00078 } 00079 } 00080 if (!$con) $con = self::connect($host, $port, null, null, null, $tout, $name, $context, null, $debug); 00081 return $con; 00082 } 00083 00084 static public function connect($host = null, $port = null, $user = null, $pass = null, $vssl = null, $tout = null, $name = null, $context = null, $login = null, $debug = null) { 00085 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00086 global $_RESULT; 00087 $_RESULT = $err = array(); 00088 if ($port == null) $port = self::PORT; 00089 if ($tout == null) $tout = self::TOUT; 00090 if (!is_string($host)) $err[] = 'invalid host type'; 00091 else { 00092 $host = strtolower(trim($host)); 00093 if (!($host != '' && ($host == 'localhost' || FUNC5::is_ipv4($host) || FUNC5::is_hostname($host, true, $debug)))) $err[] = 'invalid host value'; 00094 } 00095 if (!(is_int($port) && $port > 0)) $err[] = 'invalid port value'; 00096 if ($user != null) { 00097 if (!is_string($user)) $err[] = 'invalid username type'; 00098 else if (($user = FUNC5::str_clear($user)) == '') $err[] = 'invalid username value'; 00099 } 00100 if ($pass != null) { 00101 if (!is_string($pass)) $err[] = 'invalid password type'; 00102 else if (($pass = FUNC5::str_clear($pass)) == '') $err[] = 'invalid password value'; 00103 } 00104 if (($user != null && $pass == null) || ($user == null && $pass != null)) $err[] = 'invalid username/password combination'; 00105 if ($vssl != null) { 00106 if (!is_string($vssl)) $err[] = 'invalid ssl version type'; 00107 else { 00108 $vssl = strtolower($vssl); 00109 if (!($vssl == 'tls' || $vssl == 'ssl' || $vssl == 'sslv2' || $vssl == 'sslv3')) $err[] = 'invalid ssl version value'; 00110 } 00111 } 00112 if (!(is_int($tout) && $tout > 0)) $err[] = 'invalid timeout value'; 00113 if ($name != null) { 00114 if (!is_string($name)) $err[] = 'invalid name type'; 00115 else { 00116 $name = strtolower(trim($name)); 00117 if (!($name != '' && ($name == 'localhost' || FUNC5::is_ipv4($name) || FUNC5::is_hostname($name, true, $debug)))) $err[] = 'invalid name value'; 00118 } 00119 } else $name = '127.0.0.1'; 00120 if ($context != null && !is_resource($context)) $err[] = 'invalid context type'; 00121 if ($login != null) { 00122 $login = strtolower(trim($login)); 00123 if (!($login == 'login' || $login == 'plain' || $login == 'cram-md5')) $err[] = 'invalid authentication type value'; 00124 } 00125 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err)); 00126 else { 00127 $ret = false; 00128 $prt = ($vssl == null) ? 'tcp' : $vssl; 00129 $conn = ($context == null) ? stream_socket_client($prt.'://'.$host.':'.$port, $errno, $errstr, $tout) : stream_socket_client($prt.'://'.$host.':'.$port, $errno, $errstr, $tout, STREAM_CLIENT_CONNECT, $context); 00130 if (!$conn) $_RESULT[101] = $errstr; 00131 else if (!stream_set_timeout($conn, self::COUT)) $_RESULT[102] = 'could not set stream timeout'; 00132 else if (!self::_cres($conn, $resp, 220, null, $debug)) $_RESULT[103] = $resp; 00133 else { 00134 $continue = true; 00135 if (!self::ehlo($conn, $name, $debug)) $continue = self::helo($conn, $name, $debug); 00136 if ($continue) { 00137 if ($user == null) $ret = true; 00138 else if ($login != null) $ret = self::auth($conn, $user, $pass, $login, $debug); 00139 else { 00140 list($code, $arr) = each($_RESULT); 00141 $auth['default'] = $auth['login'] = $auth['plain'] = $auth['cram-md5'] = false; 00142 foreach ($arr as $line) { 00143 if (substr($line, 0, strlen('250-AUTH ')) == '250-AUTH ') { 00144 foreach (explode(' ', substr($line, strlen('250-AUTH '))) as $type) { 00145 $type = strtolower(trim($type)); 00146 if ($type == 'login' || $type == 'plain' || $type == 'cram-md5') $auth[$type] = true; 00147 } 00148 } else if (substr($line, 0, strlen('250 AUTH=')) == '250 AUTH=') { 00149 $expl = explode(' ', strtolower(trim(substr($line, strlen('250 AUTH=')))), 2); 00150 if ($expl[0] == 'login' || $expl[0] == 'plain' || $expl[0] == 'cram-md5') $auth['default'] = $expl[0]; 00151 } 00152 } 00153 if ($auth['default']) $ret = self::auth($conn, $user, $pass, $auth['default'], $debug); 00154 if (!$ret && $auth['login'] && $auth['default'] != 'login') $ret = self::auth($conn, $user, $pass, 'login', $debug); 00155 if (!$ret && $auth['plain'] && $auth['default'] != 'plain') $ret = self::auth($conn, $user, $pass, 'plain', $debug); 00156 if (!$ret && $auth['cram-md5'] && $auth['default'] != 'cram-md5') $ret = self::auth($conn, $user, $pass, 'cram-md5', $debug); 00157 if (!$ret && !$auth['login'] && $auth['default'] != 'login') $ret = self::auth($conn, $user, $pass, 'login', $debug); 00158 if (!$ret && !$auth['plain'] && $auth['default'] != 'plain') $ret = self::auth($conn, $user, $pass, 'plain', $debug); 00159 if (!$ret && !$auth['cram-md5'] && $auth['default'] != 'cram-md5') $ret = self::auth($conn, $user, $pass, 'cram-md5', $debug); 00160 } 00161 } 00162 } 00163 if (!$ret) { 00164 if (is_resource($conn)) self::disconnect($conn, $debug); 00165 $conn = false; 00166 } 00167 return $conn; 00168 } 00169 } 00170 00171 static public function send($conn = null, $addrs = null, $mess = null, $from = null, $debug = null) { 00172 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00173 global $_RESULT; 00174 $_RESULT = $err = array(); 00175 if (!is_resource($conn)) $err[] = 'invalid resource connection'; 00176 if (!is_array($addrs)) $err[] = 'invalid to address type'; 00177 else { 00178 $aver = true; 00179 if (count($addrs) > 0) { 00180 foreach ($addrs as $addr) { 00181 if (!FUNC5::is_mail($addr)) { 00182 $aver = false; 00183 break; 00184 } 00185 } 00186 } else $aver = false; 00187 if (!$aver) $err[] = 'invalid to address value'; 00188 } 00189 if (!is_string($mess)) $err[] = 'invalid message value'; 00190 if ($from == null) { 00191 $from = @ini_get('sendmail_from'); 00192 if ($from == '' || !FUNC5::is_mail($from)) $from = (isset($_SERVER['SERVER_ADMIN']) && FUNC5::is_mail($_SERVER['SERVER_ADMIN'])) ? $_SERVER['SERVER_ADMIN'] : 'postmaster@localhost'; 00193 } else { 00194 if (!is_string($from)) $err[] = 'invalid from address type'; 00195 else if (!($from != '' && FUNC5::is_mail($from))) $err[] = 'invalid from address value'; 00196 } 00197 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err)); 00198 else { 00199 $ret = false; 00200 if (self::from($conn, $from, $debug)) { 00201 $continue = true; 00202 foreach ($addrs as $dest) { 00203 if (!self::to($conn, $dest, $debug)) { 00204 $continue = false; 00205 break; 00206 } 00207 } 00208 if ($continue) { 00209 if (self::data($conn, $mess, $debug)) $ret = self::rset($conn, $debug); 00210 } 00211 } 00212 return $ret; 00213 } 00214 } 00215 00216 static public function disconnect($conn = null, $debug = null) { 00217 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00218 global $_RESULT; 00219 $_RESULT = array(); 00220 if (!is_resource($conn)) return FUNC5::trace($debug, 'invalid resource connection', 1); 00221 else { 00222 if (!fwrite($conn, 'QUIT'.self::CRLF)) $_RESULT[300] = 'can not write'; 00223 else $_RESULT[301] = 'Send QUIT'; 00224 return @fclose($conn); 00225 } 00226 } 00227 00228 static public function quit($conn = null, $debug = null) { 00229 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00230 global $_RESULT; 00231 $_RESULT = array(); 00232 $ret = false; 00233 if (!is_resource($conn)) FUNC5::trace($debug, 'invalid resource connection'); 00234 else if (!fwrite($conn, 'QUIT'.self::CRLF)) $_RESULT[302] = 'can not write'; 00235 else { 00236 $_RESULT[303] = ($vget = @fgets($conn, self::BLEN)) ? $vget : 'can not read'; 00237 $ret = true; 00238 } 00239 return $ret; 00240 } 00241 00242 static public function helo($conn = null, $host = null, $debug = null) { 00243 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00244 global $_RESULT; 00245 $_RESULT = $err = array(); 00246 if (!is_resource($conn)) $err[] = 'invalid resource connection'; 00247 if (!is_string($host)) $err[] = 'invalid host type'; 00248 else { 00249 $host = strtolower(trim($host)); 00250 if (!($host != '' && ($host == 'localhost' || FUNC5::is_ipv4($host) || FUNC5::is_hostname($host, true, $debug)))) $err[] = 'invalid host value'; 00251 } 00252 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err)); 00253 else { 00254 $ret = false; 00255 if (!fwrite($conn, 'HELO '.$host.self::CRLF)) $_RESULT[304] = 'can not write'; 00256 else if (!self::_cres($conn, $resp, 250, null, $debug)) $_RESULT[305] = $resp; 00257 else { 00258 $_RESULT[306] = $resp; 00259 $ret = true; 00260 } 00261 return $ret; 00262 } 00263 } 00264 00265 static public function ehlo($conn = null, $host = null, $debug = null) { 00266 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00267 global $_RESULT; 00268 $_RESULT = $err = array(); 00269 if (!is_resource($conn)) $err[] = 'invalid resource connection'; 00270 if (!is_string($host)) $err[] = 'invalid host type'; 00271 else { 00272 $host = strtolower(trim($host)); 00273 if (!($host != '' && ($host == 'localhost' || FUNC5::is_ipv4($host) || FUNC5::is_hostname($host, true, $debug)))) $err[] = 'invalid host value'; 00274 } 00275 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err)); 00276 else { 00277 $ret = false; 00278 if (!fwrite($conn, 'EHLO '.$host.self::CRLF)) $_RESULT[307] = 'can not write'; 00279 else if (!self::_cres($conn, $resp, 250, null, $debug)) $_RESULT[308] = $resp; 00280 else { 00281 $_RESULT[309] = $resp; 00282 $ret = true; 00283 } 00284 return $ret; 00285 } 00286 } 00287 00288 static public function auth($conn = null, $user = null, $pass = null, $type = null, $debug = null) { 00289 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00290 global $_RESULT; 00291 $_RESULT = $err = array(); 00292 if (!is_resource($conn)) $err[] = 'invalid resource connection'; 00293 if (!is_string($user)) $err[] = 'invalid username type'; 00294 else if (($user = FUNC5::str_clear($user)) == '') $err[] = 'invalid username value'; 00295 if (!is_string($pass)) $err[] = 'invalid password type'; 00296 else if (($pass = FUNC5::str_clear($pass)) == '') $err[] = 'invalid password value'; 00297 if ($type == null) $type = 'login'; 00298 if (!is_string($type)) $err[] = 'invalid authentication type'; 00299 else { 00300 $type = strtolower(trim($type)); 00301 if (!($type == 'login' || $type == 'plain' || $type == 'cram-md5')) $err[] = 'invalid authentication type value'; 00302 } 00303 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err)); 00304 else { 00305 $ret = false; 00306 if ($type == 'login') { 00307 if (!fwrite($conn, 'AUTH LOGIN'.self::CRLF)) $_RESULT[310] = 'can not write'; 00308 else if (!self::_cres($conn, $resp, 334, null, $debug)) $_RESULT[311] = $resp; 00309 else if (!fwrite($conn, base64_encode($user).self::CRLF)) $_RESULT[312] = 'can not write'; 00310 else if (!self::_cres($conn, $resp, 334, null, $debug)) $_RESULT[313] = $resp; 00311 else if (!fwrite($conn, base64_encode($pass).self::CRLF)) $_RESULT[314] = 'can not write'; 00312 else if (!self::_cres($conn, $resp, 235, null, $debug)) $_RESULT[315] = $resp; 00313 else { 00314 $_RESULT[316] = $resp; 00315 $ret = true; 00316 } 00317 } else if ($type == 'plain') { 00318 if (!fwrite($conn, 'AUTH PLAIN '.base64_encode($user.chr(0).$user.chr(0).$pass).self::CRLF)) $_RESULT[317] = 'can not write'; 00319 else if (!self::_cres($conn, $resp, 235, null, $debug)) $_RESULT[318] = $resp; 00320 else { 00321 $_RESULT[319] = $resp; 00322 $ret = true; 00323 } 00324 } else if ($type == 'cram-md5') { 00325 if (!fwrite($conn, 'AUTH CRAM-MD5'.self::CRLF)) $_RESULT[200] = 'can not write'; 00326 else if (!self::_cres($conn, $resp, 334, null, $debug)) $_RESULT[201] = $resp; 00327 else { 00328 if (strlen($pass) > 64) $pass = pack('H32', md5($pass)); 00329 if (strlen($pass) < 64) $pass = str_pad($pass, 64, chr(0)); 00330 $pad1 = substr($pass, 0, 64) ^ str_repeat(chr(0x36), 64); 00331 $pad2 = substr($pass, 0, 64) ^ str_repeat(chr(0x5C), 64); 00332 $chal = substr($resp[count($resp)-1], 4); 00333 $innr = pack('H32', md5($pad1.base64_decode($chal))); 00334 if (!fwrite($conn, base64_encode($user.' '.md5($pad2.$innr)).self::CRLF)) $_RESULT[202] = 'can not write'; 00335 else if (!self::_cres($conn, $resp, 235, null, $debug)) $_RESULT[203] = $resp; 00336 else { 00337 $_RESULT[204] = $resp; 00338 $ret = true; 00339 } 00340 } 00341 } 00342 return $ret; 00343 } 00344 } 00345 00346 static public function from($conn = null, $addr = null, $debug = null) { 00347 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00348 global $_RESULT; 00349 $_RESULT = $err = array(); 00350 if (!is_resource($conn)) $err[] = 'invalid resource connection'; 00351 if (!is_string($addr)) $err[] = 'invalid from address type'; 00352 else if (!($addr != '' && FUNC5::is_mail($addr))) $err[] = 'invalid from address value'; 00353 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err)); 00354 else { 00355 $ret = false; 00356 if (!fwrite($conn, 'MAIL FROM:<'.$addr.'>'.self::CRLF)) $_RESULT[320] = 'can not write'; 00357 else if (!self::_cres($conn, $resp, 250, null, $debug)) $_RESULT[321] = $resp; 00358 else { 00359 $_RESULT[322] = $resp; 00360 $ret = true; 00361 } 00362 return $ret; 00363 } 00364 } 00365 00366 static public function to($conn = null, $addr = null, $debug = null) { 00367 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00368 global $_RESULT; 00369 $_RESULT = $err = array(); 00370 if (!is_resource($conn)) $err[] = 'invalid resource connection'; 00371 if (!is_string($addr)) $err[] = 'invalid to address type'; 00372 else if (!($addr != '' && FUNC5::is_mail($addr))) $err[] = 'invalid to address value'; 00373 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err)); 00374 else { 00375 $ret = false; 00376 if (!fwrite($conn, 'RCPT TO:<'.$addr.'>'.self::CRLF)) $_RESULT[323] = 'can not write'; 00377 else if (!self::_cres($conn, $resp, 250, 251, $debug)) $_RESULT[324] = $resp; 00378 else { 00379 $_RESULT[325] = $resp; 00380 $ret = true; 00381 } 00382 return $ret; 00383 } 00384 } 00385 00386 static public function data($conn = null, $mess = null, $debug = null) { 00387 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00388 global $_RESULT; 00389 $_RESULT = $err = array(); 00390 if (!is_resource($conn)) $err[] = 'invalid resource connection'; 00391 if (!(is_string($mess) && $mess != '')) $err[] = 'invalid message value'; 00392 if (count($err) > 0) FUNC5::trace($debug, implode(', ', $err)); 00393 else { 00394 $ret = false; 00395 if (!fwrite($conn, 'DATA'.self::CRLF)) $_RESULT[326] = 'can not write'; 00396 else if (!self::_cres($conn, $resp, 354, null, $debug)) $_RESULT[327] = $resp; 00397 else { 00398 $continue = true; 00399 foreach (explode(self::CRLF, $mess) as $line) { 00400 if ($line != '' && $line[0] == '.') $line = '.'.$line; 00401 if (!fwrite($conn, $line.self::CRLF)) { 00402 $_RESULT[328] = 'can not write'; 00403 $continue = false; 00404 break; 00405 } 00406 } 00407 if ($continue) { 00408 if (!fwrite($conn, '.'.self::CRLF)) $_RESULT[329] = 'can not write'; 00409 else if (!self::_cres($conn, $resp, 250, null, $debug)) $_RESULT[330] = $resp; 00410 else { 00411 $_RESULT[331] = $resp; 00412 $ret = true; 00413 } 00414 } 00415 } 00416 return $ret; 00417 } 00418 } 00419 00420 static public function rset($conn = null, $debug = null) { 00421 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00422 global $_RESULT; 00423 $_RESULT = array(); 00424 $ret = false; 00425 if (!is_resource($conn)) FUNC5::trace($debug, 'invalid resource connection'); 00426 else if (!fwrite($conn, 'RSET'.self::CRLF)) $_RESULT[332] = 'can not write'; 00427 else if (!self::_cres($conn, $resp, 250, null, $debug)) $_RESULT[333] = $resp; 00428 else { 00429 $_RESULT[334] = $resp; 00430 $ret = true; 00431 } 00432 return $ret; 00433 } 00434 00435 static public function recv($conn = null, $code1 = null, $code2 = null, $debug = null) { 00436 if (!FUNC5::is_debug($debug)) $debug = debug_backtrace(); 00437 global $_RESULT; 00438 $_RESULT = array(); 00439 $ret = false; 00440 if (!self::_cres($conn, $resp, $code1, $code2, $debug)) $_RESULT[335] = $resp; 00441 else { 00442 $_RESULT[336] = $resp; 00443 $ret = true; 00444 } 00445 return $ret; 00446 } 00447 00448 } 00449 00450 ?>