From a2e6e301ee680d36414433fa055467d3e139b0f7 Mon Sep 17 00:00:00 2001 From: Klaus Leithoff Date: Mon, 19 Apr 2010 15:11:16 +0000 Subject: [PATCH] apply egroupware changes to phpmailer 5.1; logging errors to error_log for smtp class; additional functions to retrieve Header and Body of a created mail; being able to attach ics files as additional multipart/alternative part; AddString Part; being able to pass ssl and tls as part of the host string --- phpgwapi/inc/class.phpmailer.inc.php | 92 ++++++++++++++++++++++++++-- phpgwapi/inc/class.smtp.php | 90 +++++++++++++++++---------- 2 files changed, 146 insertions(+), 36 deletions(-) diff --git a/phpgwapi/inc/class.phpmailer.inc.php b/phpgwapi/inc/class.phpmailer.inc.php index 602f1210ce..141cc1393c 100644 --- a/phpgwapi/inc/class.phpmailer.inc.php +++ b/phpgwapi/inc/class.phpmailer.inc.php @@ -790,6 +790,11 @@ class PHPMailer { $host = $hosts[$index]; $port = $this->Port; } + $hostA = explode("://", $host); + if (strtolower($hostA[0]) == 'tls' || strtolower($hostA[0]) == 'ssl') { + $this->SMTPSecure = strtolower($hostA[0]); + $host = $hostA[1]; + } $tls = ($this->SMTPSecure == 'tls'); $ssl = ($this->SMTPSecure == 'ssl'); @@ -1057,6 +1062,7 @@ class PHPMailer { switch($this->message_type) { case 'alt': case 'alt_attachments': + case 'alt_extended': $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap); break; default: @@ -1162,6 +1168,7 @@ class PHPMailer { break; case 'attachments': case 'alt_attachments': + case 'alt_extended': if($this->InlineImageExists()){ $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE); } else { @@ -1227,6 +1234,22 @@ class PHPMailer { $body .= $this->EndBoundary($this->boundary[2]); $body .= $this->AttachAll(); break; + case 'alt_extended': + $body .= sprintf("--%s%s", $this->boundary[1], $this->LE); + $body .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE); + $body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body + $body .= $this->EncodeString($this->AltBody, $this->Encoding); + $body .= $this->LE.$this->LE; + $body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body + $body .= $this->EncodeString($this->Body, $this->Encoding); + $body .= $this->LE.$this->LE; + // Create the extended body for an attached text/calendar + $body .= $this->GetBoundary($this->boundary[2], '', $this->attachment[0][4], '') . $this->LE; + $body .= $this->EncodeString($this->attachment[0][0], $this->attachment[0][3]); + $body .= $this->LE.$this->LE; + $body .= $this->EndBoundary($this->boundary[2]); + $body .= $this->AttachAll(); + break; } if ($this->IsError()) { @@ -1272,7 +1295,7 @@ class PHPMailer { $encoding = $this->Encoding; } $result .= $this->TextLine('--' . $boundary); - $result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet); + $result .= sprintf("Content-Type: %s; charset =\"%s\"", $contentType, $charSet); $result .= $this->LE; $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding); $result .= $this->LE; @@ -1306,6 +1329,9 @@ class PHPMailer { if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) { $this->message_type = 'alt_attachments'; } + if(strlen($this->AltBody) > 0 && count($this->attachment) > 0 && stripos($this->attachment[0][4],'text/calendar')!==false) { + $this->message_type = 'alt_extended'; + } } } @@ -1417,14 +1443,22 @@ class PHPMailer { $cidUniq[$cid] = true; $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE); - $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE); + if($disposition == 'part') { + $mime[] = sprintf("Content-Type: %s; charset=\"%s\"%s", $type, $this->CharSet, $this->LE); + } else { + $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE); + } $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE); if($disposition == 'inline') { $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE); } - $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); + if($disposition != "part") { + $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE); + } else { + $mime[] = sprintf("%s", $this->LE); + } // Encode as string attachment if($bString) { @@ -1767,6 +1801,30 @@ class PHPMailer { ); } + /** + * Adds a string or binary attachment (non-filesystem) to the list. + * This method can be used to attach ascii or binary data, + * such as a BLOB record from a database. + * @param string $string String attachment data. + * @param string $filename Name of the attachment. + * @param string $encoding File encoding (see $Encoding). + * @param string $type File extension (MIME) type. + * @return void + */ + function AddStringPart($string, $filename, $encoding = "base64", $type = "application/octet-stream") { + // Append to $attachment array + $this->attachment[] = array( + 0 => $string, + 1 => $filename, + 2 => $filename, + 3 => $encoding, + 4 => $type, + 5 => true, // isString + 6 => "part", + 7 => 0 + ); + } + /** * Adds an embedded attachment. This can include images, sounds, and * just about any other document. Make sure to set the $type to an @@ -1895,6 +1953,32 @@ class PHPMailer { $this->CustomHeader = array(); } + public function getMessageHeader() { + if(!isset($this->sentHeader)) { + // Set whether the message is multipart/alternative + if(!empty($this->AltBody)) $this->ContentType = "multipart/alternative"; + + $this->SetMessageType(); + $header = $this->CreateHeader(); + $this->sentHeader = $header; + } + + return $this->sentHeader; + } + + public function getMessageBody() { + if(!isset($this->sentBody)) { + // Set whether the message is multipart/alternative + if(!empty($this->AltBody)) $this->ContentType = "multipart/alternative"; + + $this->SetMessageType(); + $body = $this->CreateBody(); + $this->sentBody = $body; + } + + return $this->sentBody; + } + ///////////////////////////////////////////////// // CLASS METHODS, MISCELLANEOUS ///////////////////////////////////////////////// @@ -2317,4 +2401,4 @@ class phpmailerException extends Exception { return $errorMsg; } } -?> \ No newline at end of file +?> diff --git a/phpgwapi/inc/class.smtp.php b/phpgwapi/inc/class.smtp.php index 6d3f24eff8..e16df7a9f5 100644 --- a/phpgwapi/inc/class.smtp.php +++ b/phpgwapi/inc/class.smtp.php @@ -136,7 +136,7 @@ class SMTP { "errno" => $errno, "errstr" => $errstr); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->"."SMTP -> ERROR: " . $this->error["error"] . ": $errstr ($errno)" . $this->CRLF); } return false; } @@ -150,7 +150,7 @@ class SMTP { $announce = $this->get_lines(); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $announce . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> FROM SERVER:" . $announce . $this->CRLF ); } return true; @@ -179,7 +179,7 @@ class SMTP { $code = substr($rply,0,3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> FROM SERVER:" . $rply . $this->CRLF ); } if($code != 220) { @@ -188,14 +188,18 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply,4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF ); } return false; } // Begin encrypted connection if(!stream_socket_enable_crypto($this->smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) { - return false; + // try a different method, as sometimes you must first switch to blocking mode, if you have problems with timeouts + stream_set_blocking($this->smtp_conn, true); + $retval = stream_socket_enable_crypto($this_smtp_conn, true, STREAM_CRYPTO_METHOD_TLS_CLIENT); + stream_set_blocking ($this->smtp_conn, false); + if (!$retval) return false; } return true; @@ -220,7 +224,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply,4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF ); } return false; } @@ -237,7 +241,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply,4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF ); } return false; } @@ -254,7 +258,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply,4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF ); } return false; } @@ -273,7 +277,7 @@ class SMTP { if($sock_status["eof"]) { // the socket is valid but we are not connected if($this->do_debug >= 1) { - echo "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected"; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> NOTICE:" . $this->CRLF . "EOF caught while checking if connected"); } $this->Close(); return false; @@ -338,7 +342,7 @@ class SMTP { $code = substr($rply,0,3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> FROM SERVER:" . $rply . $this->CRLF ); } if($code != 354) { @@ -347,7 +351,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply,4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF ); } return false; } @@ -379,7 +383,7 @@ class SMTP { $field = substr($lines[0],0,strpos($lines[0],":")); $in_headers = false; - if(!empty($field) && !strstr($field," ")) { + if(!empty($field) && strpos($field," ")===false) { $in_headers = true; } @@ -429,10 +433,32 @@ class SMTP { fputs($this->smtp_conn, $this->CRLF . "." . $this->CRLF); $rply = $this->get_lines(); + # if the server is slow try to get an answer within 30 seconds + $timeout_counter = 0; + while(($rply=="") && ($timeout_counter<30)) + { + $timeout_counter+=1; + sleep(1); + $rply = $this->get_lines(); + } + # still no response to our data -> fail! + if($rply=="") + { + $this->error = array("error" => "timeout from server after data sent.", + "smtp_code" => 0, + "smtp_msg" => "(nothing)"); + + if($this->do_debug >= 1) { + error_log(__METHOD__."->". "SMTP -> ERROR: " . $this->error["error"] . + ": " . $rply . $this->CRLF); + } + return false; + } + $code = substr($rply,0,3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> FROM SERVER:" . $rply . $this->CRLF ); } if($code != 250) { @@ -441,7 +467,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply,4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF ); } return false; } @@ -497,7 +523,7 @@ class SMTP { $code = substr($rply,0,3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER: " . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> FROM SERVER: " . $rply . $this->CRLF ); } if($code != 250) { @@ -506,7 +532,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply,4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF ); } return false; } @@ -546,7 +572,7 @@ class SMTP { $code = substr($rply,0,3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> FROM SERVER:" . $rply . $this->CRLF ); } if($code != 250) { @@ -555,7 +581,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply,4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF ); } return false; } @@ -583,13 +609,13 @@ class SMTP { } // send the quit command to the server - fputs($this->smtp_conn,"quit" . $this->CRLF); + fputs($this->smtp_conn,"QUIT" . $this->CRLF); // get any good-bye messages $byemsg = $this->get_lines(); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> FROM SERVER:" . $byemsg . $this->CRLF ); } $rval = true; @@ -603,7 +629,7 @@ class SMTP { "smtp_rply" => substr($byemsg,4)); $rval = false; if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> ERROR: " . $e["error"] . ": " . $byemsg . $this->CRLF ); } } @@ -641,7 +667,7 @@ class SMTP { $code = substr($rply,0,3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> FROM SERVER:" . $rply . $this->CRLF ); } if($code != 250 && $code != 251) { @@ -650,7 +676,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply,4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF ); } return false; } @@ -684,7 +710,7 @@ class SMTP { $code = substr($rply,0,3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> FROM SERVER:" . $rply . $this->CRLF ); } if($code != 250) { @@ -693,7 +719,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply,4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF ); } return false; } @@ -732,7 +758,7 @@ class SMTP { $code = substr($rply,0,3); if($this->do_debug >= 2) { - echo "SMTP -> FROM SERVER:" . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> FROM SERVER:" . $rply . $this->CRLF ); } if($code != 250) { @@ -741,7 +767,7 @@ class SMTP { "smtp_code" => $code, "smtp_msg" => substr($rply,4)); if($this->do_debug >= 1) { - echo "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> ERROR: " . $this->error["error"] . ": " . $rply . $this->CRLF ); } return false; } @@ -765,7 +791,7 @@ class SMTP { $this->error = array("error" => "This method, TURN, of the SMTP ". "is not implemented"); if($this->do_debug >= 1) { - echo "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> NOTICE: " . $this->error["error"] . $this->CRLF ); } return false; } @@ -796,12 +822,12 @@ class SMTP { $data = ""; while($str = @fgets($this->smtp_conn,515)) { if($this->do_debug >= 4) { - echo "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF . '
'; - echo "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> get_lines(): \$data was \"$data\"" . $this->CRLF ); + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> get_lines(): \$str is \"$str\"" . $this->CRLF ); } $data .= $str; if($this->do_debug >= 4) { - echo "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF . '
'; + error_log(__METHOD__.' Line:'.__LINE__."->". "SMTP -> get_lines(): \$data is \"$data\"" . $this->CRLF ); } // if 4th character is a space, we are done reading, break the loop if(substr($str,3,1) == " ") { break; } @@ -811,4 +837,4 @@ class SMTP { } -?> \ No newline at end of file +?>