* * and Joseph Engo * * This module should replace php's mail() function. It is fully syntax * * compatible. In addition, when an error occures, a detailed error info * * is stored in the array $send->err (see ../inc/email/global.inc.php for * * details on this variable). * * Copyright (C) 2000, 2001 Itzchak Rehberg * * -------------------------------------------------------------------------* * This library is part of the phpGroupWare API * * http://www.phpgroupware.org/api * * ------------------------------------------------------------------------ * * This library is free software; you can redistribute it and/or modify it * * under the terms of the GNU Lesser General Public License as published by * * the Free Software Foundation; either version 2.1 of the License, * * or any later version. * * This library is distributed in the hope that it will be useful, but * * WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. * * See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * * along with this library; if not, write to the Free Software Foundation, * * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * \**************************************************************************/ /* $Id$ */ class send { var $err = array("code","msg","desc"); var $to_res = array(); function send() { $this->err["code"] = " "; $this->err["msg"] = " "; $this->err["desc"] = " "; } function msg($service, $to, $subject, $body, $msgtype="", $cc="", $bcc="", $from ="") { global $phpgw_info, $phpgw, $attach_sig; if ($from ==""){ $from = $phpgw_info["user"]["fullname"]." <".$phpgw_info["user"]["preferences"]["email"]["address"].">"; } if ($service == "email") { $now = getdate(); $header = "Date: " . gmdate("D, d M Y H:i:s") . " +0000\n"; $header .= "From: ".$from."\n"; $header .= "Reply-To: ".$phpgw_info["user"]["preferences"]["email"]["address"]."\n"; $header .= "To: $to\n"; if (!empty($cc)) { $header .= "Cc: $cc\n"; } if (!empty($bcc)) { $header .= "Bcc: $bcc\n"; } if (!empty($msgtype)) { $header .= "X-phpGW-Type: $msgtype\n"; } $header .= "X-Mailer: phpGroupWare (http://www.phpgroupware.org)\n"; if ($phpgw_info["user"]["preferences"]["email"]["email_sig"] && $attach_sig) { $body .= "\n-----\n" . $phpgw_info["user"]["preferences"]["email"]["email_sig"]; } if (ereg("Message-Boundary", $body)) { $header .= "Subject: " . stripslashes($subject) . "\n" . "MIME-Version: 1.0\n" . "Content-Type: multipart/mixed;\n" . " boundary=\"Message-Boundary\"\n\n" . "--Message-Boundary\n" . "Content-type: text/plain; charset=US-ASCII\n"; // if (!empty($msgtype)) { // $header .= "Content-type: text/plain; phpgw-type=".$msgtype."\n"; // } $header .= "Content-Disposition: inline\n" . "Content-transfer-encoding: 7BIT\n\n" . $body; $body = ""; } else { $header .= "Subject: " . stripslashes($subject) . "\n" . "MIME-version: 1.0\n" . "Content-type: text/plain; charset=\"".lang("charset")."\"\n"; if (!empty($msgtype)) { $header .= "Content-type: text/plain; phpgw-type=".$msgtype."\n"; } $header .= "Content-Disposition: inline\n" . "Content-description: Mail message body\n"; } if ($phpgw_info["user"]["preferences"]["email"]["mail_server_type"] == "imap" && $phpgw_info["user"]["apps"]["email"] && is_object($phpgw->msg)){ $stream = $phpgw->msg->login("Sent"); $phpgw->msg->append($stream, "Sent", $header, $body, "\\Seen"); $phpgw->msg->close($stream); } if (strlen($cc)>1) $to .= ",".$cc; if (strlen($bcc)>1) $to .= ",".$bcc; $returnccode = $this->smail($to, "", $body, $header); return $returnccode; } elseif ($type == "nntp") { } } // ==================================================[ some sub-functions ]=== function socket2msg($socket) { $followme = "-"; $this->err["msg"] = ""; do { $rmsg = fgets($socket,255); // echo "< $rmsg
\n"; $this->err["code"] = substr($rmsg,0,3); $followme = substr($rmsg,3,1); $this->err["msg"] = substr($rmsg,4); if (substr($this->err["code"],0,1) != 2 && substr($this->err["code"],0,1) != 3) { $rc = fclose($socket); return false; } if ($followme = " ") { break; } } while ($followme = "-"); return true; } function msg2socket($socket,$message) { // send single line\n // echo "raw> $message
\n"; // echo "hex> ".bin2hex($message)."
\n"; $rc = fputs($socket,"$message"); if (!$rc) { $this->err["code"] = "420"; $this->err["msg"] = "lost connection"; $this->err["desc"] = "Lost connection to smtp server."; $rc = fclose($socket); return false; } return true; } function put2socket($socket,$message) { // check for multiple lines 1st $pos = strpos($message,"\n"); if (!is_int($pos)) { // no new line found $message .= "\r\n"; $this->msg2socket($socket,$message); } else { // multiple lines, we have to split it do { $msglen = $pos + 1; $msg = substr($message,0,$msglen); $message = substr($message,$msglen); $pos = strpos($msg,"\r\n"); if (!is_int($pos)) { // line not terminated $msg = chop($msg)."\r\n"; } $pos = strpos($msg,"."); // escape leading periods if (is_int($pos) && !$pos) { $msg = "." . $msg; } if (!$this->msg2socket($socket,$msg)) { return false; } $pos = strpos($message,"\n"); } while (strlen($message)>0); } return true; } function check_header($subject,$header) { // check if header contains subject // and is correctly terminated $header = chop($header); $header .= "\n"; if (is_string($subject) && !$subject) { // no subject specified return $header; } $theader = strtolower($header); $pos = strpos($theader,"\nsubject:"); if (is_int($pos)) { // found after a new line return $header; } $pos = strpos($theader,"subject:"); if (is_int($pos) && !$pos) { // found at start return $header; } $pos = substr($subject,"\n"); if (!is_int($pos)) $subject .= "\n"; $subject = "Subject: " .$subject; $header .= $subject; return $header; } // ==============================================[ main function: smail() ]=== function smail($to,$subject,$message,$header) { global $phpgw_info; $fromuser = $phpgw_info["user"]["preferences"]["email"]["address"]; $mymachine = $phpgw_info["server"]["hostname"]; $errcode = ""; $errmsg = ""; // error code and message of failed connection $timeout = 5; // timeout in secs // now we try to open the socket and check, if any smtp server responds $socket = fsockopen($phpgw_info["server"]["smtp_server"],$phpgw_info["server"]["smtp_port"],$errcode,$errmsg,$timeout); if (!$socket) { $this->err["code"] = "420"; $this->err["msg"] = "$errcode:$errmsg"; $this->err["desc"] = "Connection to ".$phpgw_info["server"]["smtp_server"].":".$phpgw_info["server"]["smtp_port"]." failed - could not open socket."; return false; } else { $rrc = $this->socket2msg($socket); } // now we can send our message. 1st we identify ourselves and the sender $cmds = array ( "\$src = \$this->msg2socket(\$socket,\"HELO \$mymachine\r\n\");", "\$rrc = \$this->socket2msg(\$socket);", "\$src = \$this->msg2socket(\$socket,\"MAIL FROM:<\$fromuser>\r\n\");", "\$rrc = \$this->socket2msg(\$socket);" ); for ($src=true,$rrc=true,$i=0; $imsg2socket($socket,"RCPT TO:<$toaddr[$i]>\r\n"); $rrc = $this->socket2msg($socket); $this->to_res[$i][addr] = $toaddr[$i]; // for lateron validation $this->to_res[$i][code] = $this->err["code"]; $this->to_res[$i][msg] = $this->err["msg"]; $this->to_res[$i][desc] = $this->err["desc"]; } //now we have to make sure that at least one $to-address was accepted $stop = 1; for ($i=0;$ito_res);$i++) { $rc = substr($this->to_res[$i][code],0,1); if ($rc == 2) { // at least to this address we can deliver $stop = 0; } } if ($stop) return false; // no address found we can deliver to // now we can go to deliver the message! if (!$this->msg2socket($socket,"DATA\r\n")) return false; if (!$this->socket2msg($socket)) return false; if ($header != "") { $header = $this->check_header($subject,$header); if (!$this->put2socket($socket,$header)) return false; if (!$this->put2socket($socket,"\r\n")) return false; } $message = chop($message); $message .= "\n"; if (!$this->put2socket($socket,$message)) return false; if (!$this->msg2socket($socket,".\r\n")) return false; if (!$this->socket2msg($socket)) return false; if (!$this->msg2socket($socket,"QUIT\r\n")) return false; Do { $closing = $this->socket2msg($socket); } while ($closing); return true; } // end of class }