A hint: This file contains one or more very long lines, so maybe it is better readable using the pure text view mode that shows the contents as wrapped lines within the browser window.
1 <?php 2 3 /*********************************************** 4 * File : utils.php 5 * Project : Z-Push 6 * Descr : 7 * 8 * Created : 03.04.2008 9 * 10 * Zarafa Deutschland GmbH, www.zarafaserver.de 11 * This file is distributed under GPL v2. 12 * Consult LICENSE file for details 13 ************************************************/ 14 15 // saves information about folder data for a specific device 16 function _saveFolderData($devid, $folders) { 17 if (!is_array($folders) || empty ($folders)) 18 return false; 19 20 $unique_folders = array (); 21 22 foreach ($folders as $folder) { 23 if (!isset($folder->type)) 24 continue; 25 26 // don't save folder-ids for emails 27 if ($folder->type == SYNC_FOLDER_TYPE_INBOX) 28 continue; 29 30 // no folder from that type or the default folder 31 if (!array_key_exists($folder->type, $unique_folders) || $folder->parentid == 0) { 32 $unique_folders[$folder->type] = $folder->serverid; 33 } 34 } 35 36 // Treo does initial sync for calendar and contacts too, so we need to fake 37 // these folders if they are not supported by the backend 38 if (!array_key_exists(SYNC_FOLDER_TYPE_APPOINTMENT, $unique_folders)) 39 $unique_folders[SYNC_FOLDER_TYPE_APPOINTMENT] = SYNC_FOLDER_TYPE_DUMMY; 40 if (!array_key_exists(SYNC_FOLDER_TYPE_CONTACT, $unique_folders)) 41 $unique_folders[SYNC_FOLDER_TYPE_CONTACT] = SYNC_FOLDER_TYPE_DUMMY; 42 43 if (!file_put_contents(STATE_PATH."/".$devid."/compat-$devid", serialize($unique_folders))) { 44 debugLog("_saveFolderData: Data could not be saved!"); 45 } 46 } 47 48 // returns information about folder data for a specific device 49 function _getFolderID($devid, $class) { 50 $filename = STATE_PATH."/".$devid."/compat-$devid"; 51 52 if (file_exists($filename)) { 53 $arr = unserialize(file_get_contents($filename)); 54 55 if ($class == "Calendar") 56 return $arr[SYNC_FOLDER_TYPE_APPOINTMENT]; 57 if ($class == "Contacts") 58 return $arr[SYNC_FOLDER_TYPE_CONTACT]; 59 60 } 61 62 return false; 63 } 64 65 /** 66 * Function which converts a hex entryid to a binary entryid. 67 * @param string @data the hexadecimal string 68 */ 69 if (!function_exists('hex2bin')) { 70 function hex2bin($data) 71 { 72 $len = byte_strlen($data); 73 $newdata = ""; 74 75 for ($i = 0;$i < $len;$i += 2) { 76 $newdata .= pack("C", hexdec(byte_substr($data, $i, 2))); 77 } 78 return $newdata; 79 } 80 } 81 function utf8_to_backendcharset($string, $option = "") 82 { 83 // if the store supports unicode return the string without converting it 84 if (defined('STORE_SUPPORTS_UNICODE') && STORE_SUPPORTS_UNICODE == true) return $string; 85 86 if (function_exists("iconv")){ 87 return @iconv("UTF-8", BACKEND_CHARSET . $option, $string); 88 }else{ 89 return utf8_decode($string); // no euro support here 90 } 91 } 92 93 function backendcharset_to_utf8($string, $option = "") 94 { 95 // if the store supports unicode return the string without converting it 96 if (defined('STORE_SUPPORTS_UNICODE') && STORE_SUPPORTS_UNICODE == true) return $string; 97 98 if (function_exists("iconv")){ 99 return @iconv(BACKEND_CHARSET, "UTF-8" . $option, $string); 100 }else{ 101 return utf8_encode($string); // no euro support here 102 } 103 } 104 105 function w2u($string) { return backendcharset_to_utf8($string); } 106 function u2w($string) { return utf8_to_backendcharset($string); } 107 108 function w2ui($string) { return backendcharset_to_utf8($string, "//TRANSLIT"); } 109 function u2wi($string) { return utf8_to_backendcharset($string, "//TRANSLIT"); } 110 111 /** 112 * Truncate an UTF-8 encoded sting correctly 113 * 114 * If it's not possible to truncate properly, an empty string is returned 115 * 116 * @param string $string - the string 117 * @param string $length - position where string should be cut 118 * @return string truncated string 119 */ 120 function utf8_truncate($string, $length) { 121 if (byte_strlen($string) <= $length) 122 return $string; 123 124 while ($length >= 0) { 125 if ((ord($string[$length]) < 0x80) || (ord($string[$length]) >= 0xC0)) 126 return byte_substr($string, 0, $length); 127 128 $length--; 129 } 130 return ""; 131 } 132 133 134 /** 135 * Build an address string from the components 136 * 137 * @param string $street - the street 138 * @param string $zip - the zip code 139 * @param string $city - the city 140 * @param string $state - the state 141 * @param string $country - the country 142 * @return string the address string or null 143 */ 144 function buildAddressString($street, $zip, $city, $state, $country) { 145 $out = ""; 146 147 if (isset($country) && $street != "") $out = $country; 148 149 $zcs = ""; 150 if (isset($zip) && $zip != "") $zcs = $zip; 151 if (isset($city) && $city != "") $zcs .= (($zcs)?" ":"") . $city; 152 if (isset($state) && $state != "") $zcs .= (($zcs)?" ":"") . $state; 153 if ($zcs) $out = $zcs . "\r\n" . $out; 154 155 if (isset($street) && $street != "") $out = $street . (($out)?"\r\n\r\n". $out: "") ; 156 157 return ($out)?$out:null; 158 } 159 160 /** 161 * Checks if the PHP-MAPI extension is available and in a requested version 162 * 163 * @param string $version - the version to be checked ("6.30.10-18495", parts or build number) 164 * @return boolean installed version is superior to the checked strin 165 */ 166 function checkMapiExtVersion($version = "") { 167 // compare build number if requested 168 if (preg_match('/^\d+$/',$version) && byte_strlen($version) > 3) { 169 $vs = preg_split('/-/', phpversion("mapi")); 170 return ($version <= $vs[1]); 171 } 172 173 if (extension_loaded("mapi")){ 174 if (version_compare(phpversion("mapi"), $version) == -1){ 175 return false; 176 } 177 } 178 else 179 return false; 180 181 return true; 182 } 183 184 function base64uri_decode($uri) { 185 $uri = base64_decode($uri); 186 $lenDevID = ord($uri{4}); 187 $lenPolKey = ord($uri{4+(1+$lenDevID)}); 188 $lenDevType = ord($uri{4+(1+$lenDevID)+(1+$lenPolKey)}); 189 $arr_ret = unpack("CProtVer/CCommand/vLocale/CDevIDLen/H".($lenDevID*2)."DevID/CPolKeyLen".($lenPolKey == 4 ? "/VPolKey" : "")."/CDevTypeLen/A".($lenDevType)."DevType",$uri); 190 $pos = (7+$lenDevType+$lenPolKey+$lenDevID); 191 $uri = byte_substr($uri,$pos); 192 while (byte_strlen($uri) > 0) { 193 $lenToken = ord($uri{1}); 194 switch (ord($uri{0})) { 195 case 0 : $type = "AttachmentName"; break; 196 case 1 : $type = "CollectionId"; break; //accroding to spec 20090712 197 case 2 : $type = "CollectionName"; break; //accroding to spec 20090712 198 case 3 : $type = "ItemId"; break; 199 case 4 : $type = "LongId"; break; 200 case 5 : $type = "ParentId"; break; //accroding to spec 20090712 201 case 6 : $type = "Occurrence"; break; 202 case 7 : $type = "Options"; break; 203 case 8 : $type = "User"; break; 204 default : $type = "unknown".ord($uri{0}); break; 205 } 206 $value = unpack("CType/CLength/A".$lenToken."Value",$uri); 207 $arr_ret[$type] = $value['Value']; 208 $pos = 2+$lenToken; 209 $uri = byte_substr($uri,$pos); 210 } 211 212 return $arr_ret; 213 } 214 215 /** 216 * Read the correct message body 217 * 218 * @param ressource $msg - the message 219 **/ 220 function eml_ReadMessage($msg) { 221 global $protocolversion; 222 $rtf = mapi_message_openproperty($msg, PR_RTF_COMPRESSED); 223 if (!$rtf) { 224 $body = mapi_message_openproperty($msg, PR_BODY); 225 $content = "text/plain"; 226 } else { 227 $rtf = preg_replace("/(\n.*)/m","",mapi_decompressrtf($rtf)); 228 if (strpos($rtf,"\\fromtext") != false || !($protocolversion >= 2.5)) { 229 $body = mapi_message_openproperty($msg, PR_BODY); 230 $content = "text/plain"; 231 } else { 232 $body = mapi_message_openproperty($msg, PR_HTML); 233 $content = "text/html"; 234 } 235 } 236 if (mb_detect_encoding($body) != "UTF-8") 237 $body = w2ui( $body ); 238 return array('body' => $body,'content' => $content); 239 } 240 241 // START ADDED dw2412 EML Attachment 242 function buildEMLAttachment($attach) { 243 $msgembedded = mapi_attach_openobj($attach); 244 $msgprops = mapi_getprops($msgembedded,array(PR_MESSAGE_CLASS,PR_CLIENT_SUBMIT_TIME,PR_DISPLAY_TO,PR_SUBJECT,PR_SENT_REPRESENTING_NAME,PR_SENT_REPRESENTING_EMAIL_ADDRESS)); 245 $msgembeddedrcpttable = mapi_message_getrecipienttable($msgembedded); 246 $msgto = $msgprops[PR_DISPLAY_TO]; 247 if($msgembeddedrcpttable) { 248 $msgembeddedrecipients = mapi_table_queryrows($msgembeddedrcpttable, array(PR_ADDRTYPE, PR_ENTRYID, PR_DISPLAY_NAME, PR_EMAIL_ADDRESS, PR_SMTP_ADDRESS, PR_RECIPIENT_TYPE, PR_RECIPIENT_FLAGS, PR_PROPOSEDNEWTIME, PR_PROPOSENEWTIME_START, PR_PROPOSENEWTIME_END, PR_RECIPIENT_TRACKSTATUS), 0, 99999999); 249 foreach($msgembeddedrecipients as $rcpt) { 250 if ($rcpt[PR_DISPLAY_NAME] == $msgprops[PR_DISPLAY_TO]) { 251 $msgto = $rcpt[PR_DISPLAY_NAME]; 252 if (isset($rcpt[PR_EMAIL_ADDRESS]) && 253 $rcpt[PR_EMAIL_ADDRESS] != $msgprops[PR_DISPLAY_TO]) $msgto .= " <".$rcpt[PR_EMAIL_ADDRESS].">"; 254 break; 255 } 256 } 257 } 258 $msgsubject = $msgprops[PR_SUBJECT]; 259 $msgfrom = $msgprops[PR_SENT_REPRESENTING_NAME]; 260 if (isset($msgprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS]) && 261 $msgprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS] != $msgprops[PR_SENT_REPRESENTING_NAME]) $msgfrom .= " <".$msgprops[PR_SENT_REPRESENTING_EMAIL_ADDRESS].">"; 262 $msgtime = $msgprops[PR_CLIENT_SUBMIT_TIME]; 263 $msgembeddedbody = eml_ReadMessage($msgembedded); 264 $msgembeddedattachtable = mapi_message_getattachmenttable($msgembedded); 265 $msgembeddedattachtablerows = mapi_table_queryallrows($msgembeddedattachtable, array(PR_ATTACH_NUM, PR_ATTACH_METHOD)); 266 if ($msgembeddedattachtablerows) { 267 $boundary = '=_zpush_static'; 268 $headercontenttype = "multipart/mixed"; 269 $msgembeddedbody['body'] = "Unfortunately your mobile is not able to handle MIME Messages\n". 270 "--".$boundary."\n". 271 "Content-Type: ".$msgembeddedbody['content']."; charset=utf-8\n". 272 "Content-Transfer-Encoding: quoted-printable\n\n". 273 $msgembeddedbody['body']."\n"; 274 foreach ($msgembeddedattachtablerows as $msgembeddedattachtablerow) { 275 $msgembeddedattach = mapi_message_openattach($msgembedded, $msgembeddedattachtablerow[PR_ATTACH_NUM]); 276 if(!$msgembeddedattach) { 277 debugLog("Unable to open attachment number $attachnum"); 278 } else { 279 $msgembeddedattachprops = mapi_getprops($msgembeddedattach, array(PR_ATTACH_MIME_TAG, PR_ATTACH_LONG_FILENAME,PR_ATTACH_FILENAME,PR_DISPLAY_NAME)); 280 if (isset($msgembeddedattachprops[PR_ATTACH_LONG_FILENAME])) 281 $attachfilename = w2u($msgembeddedattachprops[PR_ATTACH_LONG_FILENAME]); 282 else if (isset($msgembeddedattachprops[PR_ATTACH_FILENAME])) 283 $attachfilename = w2u($msgembeddedattachprops[PR_ATTACH_FILENAME]); 284 else if (isset($msgembeddedattachprops[PR_DISPLAY_NAME])) 285 $attachfilename = w2u($msgembeddedattachprops[PR_DISPLAY_NAME]); 286 else 287 $attachfilename = w2u("untitled"); 288 if ($msgembeddedattachtablerow[PR_ATTACH_METHOD] == ATTACH_EMBEDDED_MSG) 289 $attachfilename .= w2u(".eml"); 290 $msgembeddedbody['body'] .= "--".$boundary."\n". 291 "Content-Type: ".$msgembeddedattachprops[PR_ATTACH_MIME_TAG].";\n". 292 " name=\"".$attachfilename."\"\n". 293 "Content-Transfer-Encoding: base64\n". 294 "Content-Disposition: attachment;\n". 295 " filename=\"".$attachfilename."\"\n\n"; 296 $msgembeddedattachstream = mapi_openpropertytostream($msgembeddedattach, PR_ATTACH_DATA_BIN); 297 $msgembeddedattachment = ""; 298 while(1) { 299 $msgembeddedattachdata = mapi_stream_read($msgembeddedattachstream, 4096); 300 if(byte_strlen($msgembeddedattachdata) == 0) 301 break; 302 $msgembeddedattachment .= $msgembeddedattachdata; 303 } 304 $msgembeddedbody['body'] .= chunk_split(base64_encode($msgembeddedattachment))."\n"; 305 unset($msgembeddedattachment); 306 } 307 } 308 $msgembeddedbody['body'] .= "--".$boundary."--\n"; 309 } else { 310 $headercontenttype = $msgembeddedbody['content']."; charset=utf-8"; 311 $boundary = ''; 312 } 313 $msgembeddedheader = "Subject: ".$msgsubject."\n". 314 "From: ".$msgfrom."\n". 315 "To: ".$msgto."\n". 316 "Date: ".gmstrftime("%a, %d %b %Y %T +0000",$msgprops[PR_CLIENT_SUBMIT_TIME])."\n". 317 "MIME-Version: 1.0\n". 318 "Content-Type: ".$headercontenttype.";\n". 319 ($boundary ? " boundary=\"".$boundary."\"\n" : ""). 320 "\n"; 321 $stream = mapi_stream_create(); 322 mapi_stream_setsize($stream,byte_strlen($msgembeddedheader.$msgembeddedbody['body'])); 323 mapi_stream_write($stream,$msgembeddedheader.$msgembeddedbody['body']); 324 mapi_stream_seek($stream,0,STREAM_SEEK_SET); 325 return $stream; 326 } 327 // END ADDED dw2412 EML Attachment 328 329 330 /** 331 * Parses and returns an ecoded vCal-Uid from an 332 * OL compatible GlobalObjectID 333 * 334 * @param string $olUid - an OL compatible GlobalObjectID 335 * @return string the vCal-Uid if available in the olUid, else the original olUid as HEX 336 */ 337 function getICalUidFromOLUid($olUid){ 338 $icalUid = strtoupper(bin2hex($olUid)); 339 if(($pos = stripos($olUid,"vCal-Uid"))) { 340 $length = unpack("V", byte_substr($olUid, $pos-4,4)); 341 $icalUid = byte_substr($olUid, $pos+12, $length[1] -14); 342 } 343 return $icalUid; 344 } 345 346 /** 347 * Checks the given UID if it is an OL compatible GlobalObjectID 348 * If not, the given UID is encoded inside the GlobalObjectID 349 * 350 * @param string $icalUid - an appointment uid as HEX 351 * @return string an OL compatible GlobalObjectID 352 * 353 */ 354 function getOLUidFromICalUid($icalUid) { 355 if (byte_strlen($icalUid) <= 64) { 356 $len = 13 + byte_strlen($icalUid); 357 $OLUid = pack("V", $len); 358 $OLUid .= "vCal-Uid"; 359 $OLUid .= pack("V", 1); 360 $OLUid .= $icalUid; 361 return hex2bin("040000008200E00074C5B7101A82E0080000000000000000000000000000000000000000". bin2hex($OLUid). "00"); 362 } 363 else 364 return hex2bin($icalUid); 365 } 366 367 /** 368 * Extracts the basedate of the GlobalObjectID and the RecurStartTime 369 * 370 * @param string $goid - OL compatible GlobalObjectID 371 * @param long $recurStartTime - RecurStartTime 372 * @return long basedate 373 * 374 */ 375 function extractBaseDate($goid, $recurStartTime) { 376 $hexbase = byte_substr(bin2hex($goid), 32, 8); 377 $day = hexdec(byte_substr($hexbase, 6, 2)); 378 $month = hexdec(byte_substr($hexbase, 4, 2)); 379 $year = hexdec(byte_substr($hexbase, 0, 4)); 380 381 if ($day && $month && $year) { 382 $h = $recurStartTime >> 12; 383 $m = ($recurStartTime - $h * 4096) >> 6; 384 $s = $recurStartTime - $h * 4096 - $m * 64; 385 return gmmktime($h, $m, $s, $month, $day, $year); 386 } 387 else 388 return false; 389 } 390 391 // stripos is only available since php5 - just for compatibility reasons we have this function below... 392 if (!function_exists("stripos")) { 393 function stripos($string1, $string2) { 394 return strpos(strtolower($string1),strtolower($string2)); 395 } 396 } 397 398 /** 399 * Return the number of bytes of a string, independent of mbstring.func_overload 400 * AND the availability of mbstring 401 * 402 * @param string $str 403 * @return int 404 */ 405 function byte_strlen($str) { 406 return MBSTRING_OVERLOAD & 2 ? mb_strlen($str,'ascii') : strlen($str); 407 } 408 409 /** 410 * mbstring.func_overload safe substr 411 * 412 * @param string $data 413 * @param int $offset 414 * @param int $len 415 * @return string 416 */ 417 function byte_substr(&$data,$offset,$len=null) { 418 if ($len == null) 419 return MBSTRING_OVERLOAD & 2 ? mb_substr($data,$offset,byte_strlen($data),'ascii') : substr($data,$offset); 420 return MBSTRING_OVERLOAD & 2 ? mb_substr($data,$offset,$len,'ascii') : substr($data,$offset,$len); 421 } 422 423 // START ADDED dw2412 just to find out if include file is available (didn't find a better place to have this 424 // nice function reachable to check if common classes not already integrated in Zarafa Server exists) 425 function include_file_exists($filename) { 426 $path = explode(":", ini_get('include_path')); 427 foreach($path as $value) { 428 if (file_exists($value.$filename)) return true; 429 } 430 431 return false; 432 } 433 // END ADDED dw2412 just to find out if include file is available 434 435 // START ADDED dw2412 ResolveRecipient Support 436 function generateMergedFB($starttime, $endtime, $entries) { 437 $mergedfb = ''; 438 for ($i = 0; $i < ($endtime-$starttime)/60/30; $i++) { 439 $mergedfb .= '0'; 440 } 441 if (isset($entries) && sizeof($entries) > 0) { 442 foreach ($entries as $entry) { 443 for ($i=(($entry['start'] - $starttime) / 60 / 30); $i<(($entry['end'] - $starttime) / 60 / 30); $i++) { 444 $mergedfb{$i} = $entry['status']; 445 } 446 } 447 } 448 return $mergedfb; 449 } 450 451 function parseVFB($lines, &$line_no) { 452 for (;$line_no<sizeof($lines);$line_no++) { 453 $line = $lines[$line_no]; 454 if (($i = strpos($line,":"))) { 455 $field = substr($line,0,$i); 456 $value = substr($line,$i+1); 457 switch (strtolower($field)) { 458 case 'begin' : 459 $line_no++; 460 $vfb_loc[strtolower($value)] = parseVFB($lines,$line_no); 461 break; 462 case 'dtend' : 463 case 'dtstart' : 464 case 'dtstamp' : 465 $vfb_loc[strtolower($field)] = parseVFB_date($value); 466 break; 467 case 'freebusy' : 468 if (($i = strpos($value,"/"))) { 469 $val['starttime'] = parseVFB_date(substr($value,0,$i)); 470 $val['endtime'] = parseVFB_date(substr($value,$i+1)); 471 } 472 $vfb_loc[strtolower($field)][] = $val; 473 break; 474 case 'end' : 475 return $vfb_loc; 476 default : 477 $vfb_loc[strtolower($field)] = $value; 478 } 479 } 480 } 481 return $vfb_loc; 482 } 483 484 function parseVFB_date($tstring) { 485 if(preg_match("/(\d{4})[^0-9]*(\d{2})[^0-9]*(\d{2})T(\d{2})[^0-9]*(\d{2})[^0-9]*(\d{2})(.\d+)?Z/", $tstring, $matches)) { 486 if ($matches[1] >= 2038){ 487 $matches[1] = 2038; 488 $matches[2] = 1; 489 $matches[3] = 18; 490 $matches[4] = $matches[5] = $matches[6] = 0; 491 } 492 return gmmktime($matches[4], $matches[5], $matches[6], $matches[2], $matches[3], $matches[1]); 493 } 494 return false; 495 } 496 // END ADDED dw2412 ResolveRecipient Support 497 498 function InternalSMTPClient($from,$to,$cc,$bcc,$content) { 499 $addpath = ""; 500 if (strlen($to) > 0) $addpath .= $to.", "; 501 if (strlen($cc) > 0) $addpath .= $cc.", "; 502 if (strlen($bcc) > 0) $addpath .= $bcc.", "; 503 $addrs = array(); 504 $namefield=""; 505 $addrfield=""; 506 for($i=0;$i < strlen($addpath);$i++) { 507 switch ($addpath{$i}) { 508 case "\"" : // parse namefield 509 $namefield=""; 510 for($i++;$i < strlen($addpath); $i++) { 511 if ($addpath{$i} == "\\") { 512 $namefield .= $addpath{$i}; 513 $i++; 514 $namefield .= $addpath{$i}; 515 } else 516 if ($addpath{$i} == "\"") 517 break; 518 else 519 $namefield .= $addpath{$i}; 520 } 521 break; 522 case "<" : 523 $addrfield=""; 524 for($i++;$i < strlen($addpath); $i++) { 525 if ($addpath{$i} == ">") 526 break; 527 else 528 $addrfield .= $addpath{$i}; 529 } 530 break; 531 case "," : 532 if ($addrfield != "") { 533 $addr = array ("FullName" => $namefield, "addr" => $addrfield); 534 array_push($addrs,$addr); 535 } 536 $namefield=""; 537 $addrfield=""; 538 break; 539 } 540 } 541 if ($addrfield != "") { 542 $addr = array ("FullName" => $namefield, "addr" => $addrfield); 543 array_push($addrs,$addr); 544 } 545 if (sizeof($addrs) == 0) { 546 debugLog('Error: No eMail Recipients!'); 547 return false; 548 } 549 550 // Initiate connection with the SMTP server 551 if (!($handle = fsockopen(INTERNAL_SMTPCLIENT_SERVERNAME,INTERNAL_SMTPCLIENT_SERVERPORT))) { 552 debugLog('Error: ' . $errstr . ' (' . $errno . ')'); 553 return false; 554 } 555 556 if (substr(PHP_OS, 0, 3) != 'WIN') { 557 socket_set_timeout($handle, INTERNAL_SMTPCLIENT_CONNECTTIMEOUT, 0); 558 } 559 560 while ($line = fgets($handle, 515)) { 561 if (substr($line,3,1) == ' ') break; 562 } 563 564 if (substr(PHP_OS, 0, 3) != 'WIN') { 565 socket_set_timeout($handle, INTERNAL_SMTPCLIENT_SOCKETTIMEOUT, 0); 566 } 567 fputs($handle, "EHLO ".INTERNAL_SMTPCLIENT_MAILDOMAIN."\n"); 568 569 while ($line = fgets($handle, 515)) { 570 if (substr($line,3,1) == ' ') { 571 if (substr($line,0,3) != '250') { 572 debugLog('Error: EHLO not accepted from server!'); 573 return false; 574 } 575 } 576 } 577 578 // SMTP authorization 579 if (INTERNAL_SMTPCLIENT_USERNAME != '' && INTERNAL_SMTPCLIENT_PASSWORD != '') { 580 fputs($handle, "AUTH LOGIN\n"); 581 while ($line = fgets($handle, 515)) { 582 if (substr($line,3,1) == ' ') { 583 if (substr($line,0,3) != '334') { 584 debugLog('Error: AUTH LOGIN not accepted from server!'); 585 return false; 586 } 587 break; 588 } 589 } 590 fputs($handle, base64_encode(INTERNAL_SMTPCLIENT_USERNAME)."\n"); 591 while ($line = fgets($handle, 515)) { 592 if (substr($line,3,1) == ' ') { 593 if (substr($line,0,3) != '334') { 594 debugLog('Error: Username not accepted by server!'); 595 return false; 596 } 597 break; 598 } 599 } 600 fputs($handle, base64_encode(INTERNAL_SMTPCLIENT_PASSWORD)."\n"); 601 while ($line = fgets($handle, 515)) { 602 if (substr($line,3,1) == ' ') { 603 if (substr($line,0,3) != '235') { 604 debugLog('Error: Password not accepted by server!'); 605 return false; 606 } 607 break; 608 } 609 } 610 } 611 612 // Send out the e-mail 613 fputs($handle, "MAIL FROM: ".$from."\n"); 614 while ($line = fgets($handle, 515)) { 615 if (substr($line,3,1) == ' ') { 616 if (substr($line,0,3) != '250') { 617 debugLog('Error: MAIL FROM not accepted by server!'); 618 return false; 619 } 620 } 621 } 622 623 foreach ($addrs as $value) { 624 if ($value['addr'] != "") { 625 fputs($handle, "RCPT TO: ".$value['addr']."\n"); 626 while ($line = fgets($handle, 515)) { 627 if (substr($line,3,1) == ' ') { 628 if (substr($line,0,3) != '250' && substr($line,0,3) != '251') { 629 debugLog('Error: RCPT TO not accepted by server!'); 630 return false; 631 } 632 } 633 } 634 } 635 } 636 637 fputs($handle, "DATA\n"); 638 while ($line = fgets($handle, 515)) { 639 if (substr($line,3,1) == ' ') { 640 if (substr($line,0,3) != '354') { 641 debugLog('Error: DATA Command not accepted by server!'); 642 return false; 643 } 644 } 645 } 646 fputs($handle, $content. "\n"); 647 fputs($handle, ".\n"); 648 while ($line = fgets($handle, 515)) { 649 if (substr($line,3,1) == ' ') { 650 if (substr($line,0,3) != '250') { 651 debugLog('Error: DATA Content not accepted by server!'); 652 return false; 653 } 654 } 655 } 656 // Close connection to SMTP server 657 fputs($handle, "QUIT\n"); 658 while ($line = fgets($handle, 515)) { 659 if (substr($line,3,1) == ' ') { 660 if (substr($line,0,3) != '221') { 661 debugLog('Error: QUIT not accepted by server!'); 662 return false; 663 } 664 } 665 } 666 fclose ($handle); 667 return true; 668 } 669 670 ?>