<?php
/***************************************************************************************
* *
* This file is part of the XPertMailer package (http://xpertmailer.sourceforge.net/) *
* *
* XPertMailer is free software; you can redistribute it and/or modify it under the *
* terms of the GNU General Public License as published by the Free Software *
* Foundation; either version 2 of the License, or (at your option) any later version. *
* *
* XPertMailer 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 General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License along with *
* XPertMailer; if not, write to the Free Software Foundation, Inc., 51 Franklin St, *
* Fifth Floor, Boston, MA 02110-1301 USA *
* *
* XPertMailer SMTP & POP3 PHP Mail Client. Can send and read messages in MIME Format. *
* Copyright (C) 2006 Tanase Laurentiu Iulian *
* *
***************************************************************************************/
require_once 'func.php';
require_once 'mime.php';
class SMTP extends MIME {
var $_smtpconn;
var $_subject;
var $_content;
var $_arrcon;
var $_arrenc;
var $_crlf = "\r\n";
var $_port = 25;
var $_unique = 0;
var $_timeout = 30;
var $_chanklen = 70;
var $max_cl = 99;
var $max_sl = 1024;
var $result = 'unknown';
var $_header = false;
var $_attach = false;
var $_toaddrs = false;
var $_ccaddrs = false;
var $_bccaddrs = false;
var $_fromaddr = false;
var $_fromhost = false;
var $_relay = false;
var $_chunk = false;
var $_atext = false;
var $_ahtml = false;
function SMTP(){
//parent::MIME();
$this->_smtpconn = array('local');
$this->_arrcon = array('local' => '', 'client' => '', 'relay' => '');
$this->_arrenc = array('7bit' => '', '8bit' => '', 'quoted-printable' => '', 'base64' => ''); // binary not alowed
}
function delivery($conn){
$ret = false;
if(is_string($conn)){
$conn = trim($conn);
if(FUNC::is_alpha($conn, false, '-')){
$exp = explode('-', $conn);
$rep = array();
foreach($exp as $val){
$val = strtolower($val);
if(isset($this->_arrcon[$val])) $rep[] = $val;
else trigger_error('Invalid connection type value "'.$val.'", on class SMTP::delivery()', 512);
}
if(count($rep) > 0){
$this->_smtpconn = $rep;
$ret = true;
}
}else trigger_error('Invalid parameter value, on class SMTP::delivery()', 512);
}else trigger_error('Invalid parameter type value, on class SMTP::delivery()', 512);
return $ret;
}
function port($num){
$ret = false;
if(is_int($num)){
$this->_port = $num;
$ret = true;
}else trigger_error('Invalid parameter type value, on class SMTP::port()', 512);
return $ret;
}
function timeout($num){
$ret = false;
if(is_int($num)){
$this->_timeout = $num;
$ret = true;
}else trigger_error('Invalid parameter type value, on class SMTP::timeout()', 512);
return $ret;
}
function relay($raddr, $ruser = false, $rpass = false, $rport = 25, $rauth = 'autodetect', $rvssl = false){
$ret = false;
if(is_string($raddr)){
$raddr = FUNC::str_clear($raddr, array(' '));
$raddr = trim(strtolower($raddr));
if($raddr != ""){
$ret = true;
if(FUNC::is_ipv4($raddr)) $rvip = $raddr;
else{
$rvip = gethostbyname($raddr);
if($rvip == $raddr){
$ret = false;
trigger_error('Invalid hostname value "'.$raddr.'", on class SMTP::relay()', 512);
}
}
}else trigger_error('Invalid hostname/ip value, on class SMTP::relay()', 512);
}else trigger_error('Invalid hostname/ip type value, on class SMTP::relay()', 512);
if($ret){
if(is_bool($ruser)){
if(!$ruser) $ruser = '';
else trigger_error('Invalid username 1 type value, on class SMTP::relay()', 512);
}elseif(is_string($ruser)){
$ruser = FUNC::str_clear($ruser);
$ruser = trim($ruser);
}else{
$ruser = '';
trigger_error('Invalid username 2 type value, on class SMTP::relay()', 512);
}
if(is_bool($rpass)){
if(!$rpass) $rpass = '';
else trigger_error('Invalid password 1 type value, on class SMTP::relay()', 512);
}elseif(is_string($rpass)){
$rpass = FUNC::str_clear($rpass);
$rpass = trim($rpass);
}else{
$rpass = '';
trigger_error('Invalid password type value, on class SMTP::relay()', 512);
}
if(($ruser != "" && $rpass == "") || ($ruser == "" && $rpass != "")){
$ruser = $rpass = '';
trigger_error('Invalid username and password combination value, on class SMTP::relay()', 512);
}
if(!is_int($rport)){
$rport = 25;
trigger_error('Invalid port type value, on class SMTP::relay()', 512);
}
if(is_string($rauth)){
$rauth = trim(strtolower($rauth));
if(!($rauth == "autodetect" || $rauth == "login" || $rauth == "plain")){
$rauth = 'autodetect';
trigger_error('Invalid auth value, on class SMTP::relay()', 512);
}
}else{
$rauth = 'autodetect';
trigger_error('Invalid auth type value, on class SMTP::relay()', 512);
}
if(is_string($rvssl)){
$rvssl = FUNC::str_clear($rvssl);
$rvssl = trim(strtolower($rvssl));
if(!($rvssl == "tls" || $rvssl == "ssl")){
$rvssl = false;
trigger_error('Invalid TLS/SSL value, on class SMTP::relay()', 512);
}
}else{
if(is_bool($rvssl)){
$rvssl = $rvssl ? 'tls' : false;
}else{
$rvssl = false;
trigger_error('Invalid TLS/SSL type value, on class SMTP::relay()', 512);
}
}
$this->_relay = array('host' => $raddr, 'ip' => $rvip, 'user' => $ruser, 'pass' => $rpass, 'port' => $rport, 'auth' => $rauth, 'ssl' => $rvssl);
}
return $ret;
}
function addheader($hname, $hvalue){
$ret = false;
if(is_string($hname)){
$hname = FUNC::str_clear($hname, array(' '));
$hname = trim($hname);
if($hname != ""){
if(is_string($hvalue)){
$hvalue = str_replace("\r\n\t", " ", $hvalue);
$hvalue = FUNC::str_clear($hvalue);
$hvalue = trim($hvalue);
if($hvalue != ""){
$vname = strtolower($hname);
if($vname == "subject") trigger_error('Can not set "Subject" header value, for this, use function "Send()", on class SMTP::addheader()', 512);
elseif($vname == "from") trigger_error('Can not set "From" header value, for this, use function "From()", on class SMTP::addheader()', 512);
elseif($vname == "to") trigger_error('Can not set "To" header value, for this, use function "AddTo()", on class SMTP::addheader()', 512);
elseif($vname == "cc") trigger_error('Can not set "Cc" header value, for this, use function "AddCc()", on class SMTP::addheader()', 512);
elseif($vname == "bcc") trigger_error('Can not set "Bcc" header value, for this, use function "AddBcc()", on class SMTP::addheader()', 512);
elseif($vname == "date") trigger_error('Can not set "Date" header value, this value is automaticaly set, on class SMTP::addheader()', 512);
elseif($vname == "x-mailer") trigger_error('Can not set "X-Mailer" header value, this value is automaticaly set, on class SMTP::addheader()', 512);
elseif($vname == "content-type") trigger_error('Can not set "Content-Type" header value, this value is automaticaly set, on class SMTP::addheader()', 512);
elseif($vname == "content-transfer-encoding") trigger_error('Can not set "Content-Transfer-Encoding" header value, this value is automaticaly set, on class SMTP::addheader()', 512);
elseif($vname == "content-disposition") trigger_error('Can not set "Content-Disposition" header value, this value is automaticaly set, on class SMTP::addheader()', 512);
elseif($vname == "x-priority") trigger_error('Can not set "X-Priority" header value, for this, use function "Priority()", on class SMTP::addheader()', 512);
elseif($vname == "x-msmail-priority") trigger_error('Can not set "X-MSMail-Priority" header value, for this, use function "Priority()", on class SMTP::addheader()', 512);
elseif($vname == "mime-version") trigger_error('Can not set "MIME-Version" header value, this value is automaticaly set, on class SMTP::addheader()', 512);
else{
$ret = true;
$this->_header[] = array('name' => ucfirst($hname), 'value' => $hvalue);
}
}else trigger_error('Invalid 2\'nd parameter value, on class SMTP::addheader()', 512);
}else trigger_error('Invalid 2\'nd parameter type value, on class SMTP::addheader()', 512);
}else trigger_error('Invalid 1\'st parameter value, on class SMTP::addheader()', 512);
}else trigger_error('Invalid 1\'st parameter type value, on class SMTP::addheader()', 512);
return $ret;
}
function delheader($hname){
$ret = false;
if(is_string($hname)){
$hname = FUNC::str_clear($hname, array(' '));
$hname = trim($hname);
if($hname != ""){
if($this->_header && count($this->_header) > 0){
$reparr = array();
foreach($this->_header as $harr){
if(strtolower($harr['name']) != strtolower($hname)) $reparr[] = $harr;
else $ret = true;
}
$this->_header = $reparr;
}
}else trigger_error('Invalid parameter value, on class SMTP::delheader()', 512);
}else trigger_error('Invalid parameter type value, on class SMTP::delheader()', 512);
return $ret;
}
function addto($adrr, $name = ''){
$ret = false;
if(is_string($adrr)){
$adrr = FUNC::str_clear($adrr, array(' '));
$adrr = strtolower(trim($adrr));
if($adrr != "" && FUNC::is_mail($adrr)){
if(!isset($this->_toaddrs[$adrr])){
$this->_toaddrs[$adrr] = '';
$ret = true;
if(is_string($name)){
$name = FUNC::str_clear($name);
$name = trim($name);
if($name != "") $this->_toaddrs[$adrr] = $this->qpheader($name);
}else trigger_error('Invalid 2\'nd parameter type value, on class SMTP::addto()', 512);
}else trigger_error('Already exists, on class SMTP::addto()', 512);
}else trigger_error('Invalid 1\'st parameter value, on class SMTP::addto()', 512);
}else trigger_error('Invalid 1\'st parameter type value, on class SMTP::addto()', 512);
return $ret;
}
function delto($adrr = 'all'){
$ret = false;
if(is_string($adrr)){
$adrr = FUNC::str_clear($adrr, array(' '));
$adrr = strtolower(trim($adrr));
if($adrr != ""){
if($adrr == "all"){
$this->_toaddrs = false;
$ret = true;
}elseif(FUNC::is_mail($adrr)){
if(is_array($this->_toaddrs) && count($this->_toaddrs) > 0){
$reb = array();
foreach($this->_toaddrs as $num => $val){
if($num != $adrr) $reb[$num] = $val;
else $ret = true;
}
$this->_toaddrs = $reb;
}
}else trigger_error('Invalid 2 parameter value, on class SMTP::delto()', 512);
}else trigger_error('Invalid 1 parameter value, on class SMTP::delto()', 512);
}else trigger_error('Invalid parameter type value, on class SMTP::delto()', 512);
return $ret;
}
function addcc($adrr, $name = ''){
$ret = false;
if(is_string($adrr)){
$adrr = FUNC::str_clear($adrr, array(' '));
$adrr = strtolower(trim($adrr));
if($adrr != "" && FUNC::is_mail($adrr)){
if(!isset($this->_ccaddrs[$adrr])){
$this->_ccaddrs[$adrr] = '';
$ret = true;
if(is_string($name)){
$name = FUNC::str_clear($name);
$name = trim($name);
if($name != "") $this->_ccaddrs[$adrr] = $this->qpheader($name);
}else trigger_error('Invalid 2\'nd parameter type value, on class SMTP::addcc()', 512);
}else trigger_error('Already exists, on class SMTP::addcc()', 512);
}else trigger_error('Invalid 1\'st parameter value, on class SMTP::addcc()', 512);
}else trigger_error('Invalid 1\'st parameter type value, on class SMTP::addcc()', 512);
return $ret;
}
function delcc($adrr = 'all'){
$ret = false;
if(is_string($adrr)){
$adrr = FUNC::str_clear($adrr, array(' '));
$adrr = strtolower(trim($adrr));
if($adrr != ""){
if($adrr == "all"){
$this->_ccaddrs = false;
$ret = true;
}elseif(FUNC::is_mail($adrr)){
if(is_array($this->_ccaddrs) && count($this->_ccaddrs) > 0){
$reb = array();
foreach($this->_ccaddrs as $num => $val){
if($num != $adrr) $reb[$num] = $val;
else $ret = true;
}
$this->_ccaddrs = $reb;
}
}else trigger_error('Invalid 2 parameter value, on class SMTP::delcc()', 512);
}else trigger_error('Invalid 1 parameter value, on class SMTP::delcc()', 512);
}else trigger_error('Invalid parameter type value, on class SMTP::delcc()', 512);
return $ret;
}
function addbcc($adrr){
$ret = false;
if(is_string($adrr)){
$adrr = FUNC::str_clear($adrr, array(' '));
$adrr = strtolower(trim($adrr));
if($adrr != "" && FUNC::is_mail($adrr)){
if(!isset($this->_bccaddrs[$adrr])){
$this->_bccaddrs[$adrr] = '';
$ret = true;
}else trigger_error('Already exists, on class SMTP::addbcc()', 512);
}else trigger_error('Invalid parameter value, on class SMTP::addbcc()', 512);
}else trigger_error('Invalid parameter type value, on class SMTP::addbcc()', 512);
return $ret;
}
function delbcc($adrr = 'all'){
$ret = false;
if(is_string($adrr)){
$adrr = FUNC::str_clear($adrr, array(' '));
$adrr = strtolower(trim($adrr));
if($adrr != ""){
if($adrr == "all"){
$this->_bccaddrs = false;
$ret = true;
}elseif(FUNC::is_mail($adrr)){
if(is_array($this->_bccaddrs) && count($this->_bccaddrs) > 0){
$reb = array();
foreach($this->_bccaddrs as $num => $val){
if($num != $adrr) $reb[$num] = $val;
else $ret = true;
}
$this->_bccaddrs = $reb;
}
}else trigger_error('Invalid 2 parameter value, on class SMTP::delbcc()', 512);
}else trigger_error('Invalid 1 parameter value, on class SMTP::delbcc()', 512);
}else trigger_error('Invalid parameter type value, on class SMTP::delbcc()', 512);
return $ret;
}
function from($adrr, $name = ''){
$this->_fromaddr = $ret = false;
if(is_string($adrr)){
$adrr = FUNC::str_clear($adrr, array(' '));
$adrr = strtolower(trim($adrr));
if($adrr != "" && FUNC::is_mail($adrr)){
$ret = true;
$this->_fromaddr = array('address' => $adrr, 'name' => '');
if(is_string($name)){
$name = FUNC::str_clear($name);
$name = trim($name);
if($name != "") $this->_fromaddr = array('address' => $adrr, 'name' => $this->qpheader($name));
}else trigger_error('Invalid 2\'nd parameter type value, on class SMTP::from()', 512);
}else trigger_error('Invalid mail address format, on class SMTP::from()', 512);
}else trigger_error('Invalid first parameter type value, on class SMTP::from()', 512);
return $ret;
}
function fromhost($server, &$havemx){
$this->_fromhost = $ret = $havemx = false;
if(is_string($server)){
$server = FUNC::str_clear($server, array(' '));
$server = strtolower(trim($server));
if($server != ""){
$ret = true;
$this->_fromhost = $server;
if(FUNC::is_hostname($server)){
$havemx = FUNC::is_win() ? FUNC::getmxrr_win($server, $mxhost) : getmxrr($server, $mxhost);
}
}else trigger_error('Invalid parameter value, on class SMTP::fromhost()', 512);
}else trigger_error('Invalid parameter type value, on class SMTP::fromhost()', 512);
return $ret;
}
function text($text, $charset = 'iso-8859-1', $encoding = 'quoted-printable', $disposition = 'inline'){
$this->_atext = $ret = false;
if(is_string($charset)){
$charset = FUNC::str_clear($charset, array(' '));
$charset = trim($charset);
$charlen = strlen($charset);
if(!($charlen > 1 && $charlen < 60)){
$charset = 'us-ascii';
trigger_error('Invalid charset value, on class SMTP::text()', 512);
}
}else{
$charset = 'us-ascii';
trigger_error('Invalid charset type value, on class SMTP::text()', 512);
}
if(is_string($encoding)){
$encoding = FUNC::str_clear($encoding, array(' '));
$encoding = trim(strtolower($encoding));
if(!($encoding != "" && isset($this->_arrenc[$encoding]))){
$encoding = 'quoted-printable';
trigger_error('Invalid encoding value, on class SMTP::text()', 512);
}
}else{
$encoding = 'quoted-printable';
trigger_error('Invalid encoding type value, on class SMTP::text()', 512);
}
if(is_string($disposition)){
$disposition = FUNC::str_clear($disposition, array(' '));
$disposition = trim(strtolower($disposition));
if(!($disposition == "attachment" || $disposition == "inline")){
$disposition = 'inline';
trigger_error('Invalid disposition value, on class SMTP::text()', 512);
}
}else{
$disposition = 'inline';
trigger_error('Invalid disposition type value, on class SMTP::text()', 512);
}
if(is_string($text)){
$text = trim($text);
if($text != ""){
$htext = 'Content-Type: text/plain;'.$this->_crlf."\t".'charset="'.$charset.'"'.$this->_crlf.
'Content-Transfer-Encoding: '.$encoding.$this->_crlf.
'Content-Disposition: '.$disposition;
$this->_atext = array($htext, $encoding, $text);
$ret = true;
}else trigger_error('Invalid text/plain value, on class SMTP::text()', 512);
}else trigger_error('Invalid text/plain type value, on class SMTP::text()', 512);
return $ret;
}
function html($html, $charset = 'iso-8859-1', $encoding = 'quoted-printable', $disposition = 'inline'){
$this->_ahtml = $ret = false;
if(is_string($charset)){
$charset = FUNC::str_clear($charset, array(' '));
$charset = trim($charset);
$charlen = strlen($charset);
if(!($charlen > 1 && $charlen < 60)){
$charset = 'us-ascii';
trigger_error('Invalid charset value, on class SMTP::html()', 512);
}
}else{
$charset = 'us-ascii';
trigger_error('Invalid charset type value, on class SMTP::html()', 512);
}
if(is_string($encoding)){
$encoding = FUNC::str_clear($encoding, array(' '));
$encoding = trim(strtolower($encoding));
if(!($encoding != "" && isset($this->_arrenc[$encoding]))){
$encoding = 'quoted-printable';
trigger_error('Invalid encoding value, on class SMTP::html()', 512);
}
}else{
$encoding = 'quoted-printable';
trigger_error('Invalid encoding type value, on class SMTP::html()', 512);
}
if(is_string($disposition)){
$disposition = FUNC::str_clear($disposition, array(' '));
$disposition = trim(strtolower($disposition));
if(!($disposition == "attachment" || $disposition == "inline")){
$disposition = 'inline';
trigger_error('Invalid disposition value, on class SMTP::html()', 512);
}
}else{
$disposition = 'inline';
trigger_error('Invalid disposition type value, on class SMTP::html()', 512);
}
if(is_string($html)){
$html = trim($html);
if($html != ""){
$hhtml = 'Content-Type: text/html;'.$this->_crlf."\t".'charset="'.$charset.'"'.$this->_crlf.
'Content-Transfer-Encoding: '.$encoding.$this->_crlf.
'Content-Disposition: '.$disposition;
$this->_ahtml = array($hhtml, $encoding, $html);
$ret = true;
}else trigger_error('Invalid text/html value, on class SMTP::html()', 512);
}else trigger_error('Invalid text/html type value, on class SMTP::html()', 512);
return $ret;
}
function attachsource($source, $name, $mimetype = 'autodetect', $disposition = 'attachment', $encoding = 'base64'){
$ret = false;
if(is_string($source) && $source != ""){
if(is_string($name)){
$name = FUNC::str_clear($name);
$name = trim($name);
if($name != ""){
$ret = true;
$mime = 'application/octet-stream';
if(is_string($mimetype)){
$mimetype = FUNC::str_clear($mimetype, array(' '));
$mimetype = trim(strtolower($mimetype));
$mime = ($mimetype == "autodetect" || $mimetype == "") ? FUNC::mimetype($name) : $mimetype;
}
$disp = 'attachment';
if(is_string($disposition)){
$disposition = FUNC::str_clear($disposition, array(' '));
$disposition = trim(strtolower($disposition));
if($disposition == "attachment" || $disposition == "inline") $disp = $disposition;
else trigger_error('Invalid disposition value, on class SMTP::attachsource()', 512);
}else trigger_error('Invalid disposition type value, on class SMTP::attachsource()', 512);
$encode = 'base64';
if(is_string($encoding)){
$encoding = FUNC::str_clear($encoding, array(' '));
$encoding = trim(strtolower($encoding));
if($encoding != "" && isset($this->_arrenc[$encoding])) $encode = $encoding;
else trigger_error('Invalid encoding value, on class SMTP::attachsource()', 512);
}else trigger_error('Invalid encoding type value, on class SMTP::attachsource()', 512);
$this->_attach[] = array('name' => $name, 'mime' => $mime, 'disp' => $disp, 'encode' => $encode, 'source' => $source);
}else trigger_error('Invalid name value, on class SMTP::attachsource()', 512);
}else trigger_error('Invalid name type value, on class SMTP::attachsource()', 512);
}else trigger_error('Invalid source value, on class SMTP::attachsource()', 512);
return $ret;
}
function attachfile($file, $name = false, $mimetype = 'autodetect', $disposition = 'attachment', $encoding = 'base64'){
$ret = false;
if(is_string($file)){
$file = FUNC::str_clear($file);
$file = trim($file);
if($file != "" && is_file($file) && is_readable($file)){
if((is_bool($name) && !$name) || (is_string($name) && $name == '')){
$exp1 = explode("/", $file);
$name = $exp1[count($exp1)-1];
$exp2 = explode("\\", $name);
$name = $exp2[count($exp2)-1];
}
$ret = $this->attachsource(file_get_contents($file), $name, $mimetype, $disposition, $encoding);
}else trigger_error('Invalid file source, on class SMTP::attachfile()', 512);
}else trigger_error('Invalid file type value, on class SMTP::attachfile()', 512);
return $ret;
}
function delattach($name = true){
$ret = false;
if(is_bool($name)){
if($name){
$this->_attach = false;
$ret = true;
}else trigger_error('Invalid 2 file name type value, on class SMTP::delattach()', 512);
}elseif(is_string($name)){
$name = trim($name);
if($name != ""){
if($this->_attach && count($this->_attach) > 0){
$rebatt = array();
foreach($this->_attach as $attarr){
if($attarr['name'] != $name) $rebatt[] = $attarr;
else $ret = true;
}
if($ret) $this->_attach = $rebatt;
}
}else trigger_error('Invalid file name value, on class SMTP::delattach()', 512);
}else trigger_error('Invalid file name type value, on class SMTP::delattach()', 512);
return $ret;
}
function priority($level = 3){
$ret = $set = false;
if(is_int($level)){
if($level == 1) $set = array('1', 'High');
elseif($level == 3) $set = array('3', 'Normal');
elseif($level == 5) $set = array('5', 'Low');
else trigger_error('Invalid 1 parameter value, on class SMTP::priority()', 512);
}elseif(is_string($level)){
$level = FUNC::str_clear($level, array(' '));
$level = trim(strtolower($level));
if($level == "high") $set = array('1', 'High');
elseif($level == "normal") $set = array('3', 'Normal');
elseif($level == "low") $set = array('5', 'Low');
else trigger_error('Invalid 2 parameter value, on class SMTP::priority()', 512);
}else trigger_error('Invalid parameter type value, on class SMTP::priority()', 512);
if($set){
$this->delheader('X-Priority');
$this->delheader('X-MSMail-Priority');
$this->_header[] = array('name' => 'X-Priority', 'value' => $set[0]);
$this->_header[] = array('name' => 'X-MSMail-Priority', 'value' => $set[1]);
$ret = true;
}
return $ret;
}
function _sendtoip($ip, $arrto, $isrelay){
$ssl = '';
$pnm = $this->_port;
if($isrelay){
$ssl = $this->_relay['ssl'] ? $this->_relay['ssl'].'://' : '';
$pnm = $this->_relay['port'];
}
if(!$sock = fsockopen($ssl.$ip, $pnm, $errnum, $errmsg, $this->_timeout)){
$this->result = 'Error 10: '.$errmsg;
return false;
}
stream_set_timeout($sock, $this->_timeout);
$loop = $rcv = 0;
while(!feof($sock)){
$loop++;
if($rcv = fgets($sock, $this->max_sl)){
if($loop == $this->max_cl || substr($rcv, 0, 4) != "220-") break;
}else break;
}
if(!$rcv){
$this->result = 'Error 11: can\'t read';
return false;
}
if(substr($rcv, 0, 4) != "220 "){
$this->result = 'Error 12: '.$rcv;
return false;
}
if(!FUNC::is_connection($sock)){
$this->result = 'Error 13: invalid resource connection';
return false;
}
if($isrelay && $this->_relay['user'] != "" && $this->_relay['pass'] != ""){
if(!fputs($sock, 'EHLO '.$this->_fromhost.$this->_crlf)){
$this->result = 'Error 20: can\'t write';
return false;
}
$loop = $rcv = 0;
$getinfo = '';
while(!feof($sock)){
$loop++;
if($rcv = fgets($sock, $this->max_sl)){
$getinfo .= $rcv;
if($loop == $this->max_cl || substr($rcv, 0, 4) != "250-") break;
}else break;
}
if(!$rcv){
$this->result = 'Error 21: can\'t read';
return false;
}
if(substr($rcv, 0, 4) != "250 "){
if(!FUNC::is_connection($sock)){
$this->result = 'Error 22: invalid resource connection';
return false;
}
if(!fputs($sock, 'HELO '.$this->_fromhost.$this->_crlf)){
$this->result = 'Error 23: can\'t write';
return false;
}
$loop = $rcv = 0;
$getinfo = '';
while(!feof($sock)){
$loop++;
if($rcv = fgets($sock, $this->max_sl)){
$getinfo .= $rcv;
if($loop == $this->max_cl || substr($rcv, 0, 4) != "250-") break;
}else break;
}
if(!$rcv){
$this->result = 'Error 24: can\'t read';
return false;
}
if(substr($rcv, 0, 4) != "250 "){
$this->result = 'Error 25: '.$rcv;
return false;
}
}
$authlogin = strstr($getinfo, 'LOGIN');
$authplain = strstr($getinfo, 'PLAIN');
$authtype = 'login';
if($this->_relay['auth'] == "autodetect" || $this->_relay['auth'] == "login"){
if(!$authlogin){
if($authplain) $authtype = 'plain';
}
}elseif($this->_relay['auth'] == "plain"){
if($authplain) $authtype = 'plain';
}
if(!FUNC::is_connection($sock)){
$this->result = 'Error 26: invalid resource connection';
return false;
}
if($authtype == "login"){
if(!fputs($sock, 'AUTH LOGIN'.$this->_crlf)){
$this->result = 'Error 270: can\'t write';
return false;
}
if(!$rcv = fgets($sock, $this->max_sl)){
$this->result = 'Error 271: can\'t read';
return false;
}
if(substr($rcv, 0, 4) != "334 "){
$this->result = 'Error 272: '.$rcv;
return false;
}
if(!FUNC::is_connection($sock)){
$this->result = 'Error 273: invalid resource connection';
return false;
}
if(!fputs($sock, base64_encode($this->_relay['user']).$this->_crlf)){
$this->result = 'Error 274: can\'t write';
return false;
}
if(!$rcv = fgets($sock, $this->max_sl)){
$this->result = 'Error 275: can\'t read';
return false;
}
if(substr($rcv, 0, 4) != "334 "){
$this->result = 'Error 276: '.$rcv;
return false;
}
if(!FUNC::is_connection($sock)){
$this->result = 'Error 277: invalid resource connection';
return false;
}
if(!fputs($sock, base64_encode($this->_relay['pass']).$this->_crlf)){
$this->result = 'Error 278: can\'t write';
return false;
}
if(!$rcv = fgets($sock, $this->max_sl)){
$this->result = 'Error 279: can\'t read';
return false;
}
if(substr($rcv, 0, 4) != "235 "){
$this->result = 'Error 280: '.$rcv;
return false;
}
}elseif($authtype == "plain"){
if(!FUNC::is_connection($sock)){
$this->result = 'Error 281: invalid resource connection';
return false;
}
if(!fputs($sock, 'AUTH PLAIN '.base64_encode($this->_relay['user'].chr(0).$this->_relay['user'].chr(0).$this->_relay['pass']).$this->_crlf)){
$this->result = 'Error 282: can\'t write';
return false;
}
if(!$rcv = fgets($sock, $this->max_sl)){
$this->result = 'Error 283: can\'t read';
return false;
}
if(substr($rcv, 0, 4) != "235 "){
$this->result = 'Error 284: '.$rcv;
return false;
}
}
}else{
if(!fputs($sock, 'HELO '.$this->_fromhost.$this->_crlf)){
$this->result = 'Error 30: can\'t write';
return false;
}
$loop = $rcv = 0;
while(!feof($sock)){
$loop++;
if(!$rcv = fgets($sock, $this->max_sl)){
if($loop == $this->max_cl || substr($rcv, 0, 4) != "250-") break;
}else break;
}
if(!$rcv){
$this->result = 'Error 31: can\'t read';
return false;
}
if(substr($rcv, 0, 4) != "250 "){
if(!FUNC::is_connection($sock)){
$this->result = 'Error 32: invalid resource connection';
return false;
}
if(!fputs($sock, 'EHLO '.$this->_fromhost.$this->_crlf)){
$this->result = 'Error 33: can\'t write';
return false;
}
$loop = $rcv = 0;
while(!feof($sock)){
$loop++;
if(!$rcv = fgets($sock, $this->max_sl)){
if($loop == $this->max_cl || substr($rcv, 0, 4) != "250-") break;
}else break;
}
if(!$rcv){
$this->result = 'Error 34: can\'t read';
return false;
}
if(substr($rcv, 0, 4) != "250 "){
$this->result = 'Error 35: '.$rcv;
return false;
}
}
}
if(!FUNC::is_connection($sock)){
$this->result = 'Error 40: invalid resource connection';
return false;
}
if(!fputs($sock, 'MAIL FROM:<'.$this->_fromaddr['address'].'>'.$this->_crlf)){
$this->result = 'Error 41: can\'t write';
return false;
}
if(!$rcv = fgets($sock, $this->max_sl)){
$this->result = 'Error 42: can\'t read';
return false;
}
if(substr($rcv, 0, 4) != "250 "){
$this->result = 'Error 43: '.$rcv;
return false;
}
$relayh = $isrelay ? '@'.$this->_relay['host'].':' : '';
$setver = true;
foreach($arrto as $arrval){
if(!FUNC::is_connection($sock)){
$this->result = 'Error 50: invalid resource connection';
$setver = false;
break;
}
if(!fputs($sock, 'RCPT TO:<'.$relayh.$arrval.'>'.$this->_crlf)){
$this->result = 'Error 51: can\'t write';
$setver = false;
break;
}
if(!$rcv = fgets($sock, $this->max_sl)){
$this->result = 'Error 52: can\'t read';
$setver = false;
break;
}
$submsg = substr($rcv, 0, 4);
if(!($submsg == "250 " || $submsg == "251 ")){
$this->result = 'Error 53: '.$rcv;
$setver = false;
break;
}
}
if(!$setver) return false;
if(!FUNC::is_connection($sock)){
$this->result = 'Error 60: invalid resource connection';
return false;
}
if(!fputs($sock, 'DATA'.$this->_crlf)){
$this->result = 'Error 61: can\'t write';
return false;
}
if(!$rcv = fgets($sock, $this->max_sl)){
$this->result = 'Error 62: can\'t read';
return false;
}
if(substr($rcv, 0, 4) != "354 "){
$this->result = 'Error 63: '.$rcv;
return false;
}
if(!FUNC::is_connection($sock)){
$this->result = 'Error 70: invalid resource connection';
return false;
}
if(!fputs($sock, $this->_content['header']['client'])){
$this->result = 'Error 71: can\'t write';
return false;
}
$setver = true;
foreach($this->_content['body'] as $partmsg){
if(!FUNC::is_connection($sock)){
$this->result = 'Error 72: invalid resource connection';
$setver = false;
break;
}
if(!fputs($sock, $partmsg)){
$this->result = 'Error 73: can\'t write';
$setver = false;
break;
}
}
if(!$setver) return false;
if(!FUNC::is_connection($sock)){
$this->result = 'Error 80: invalid resource connection';
return false;
}
if(!fputs($sock, $this->_crlf.'.'.$this->_crlf)){
$this->result = 'Error 81: can\'t write';
return false;
}
if(!$rcv = fgets($sock, $this->max_sl)){
$this->result = 'Error 82: can\'t read';
return false;
}
if(substr($rcv, 0, 4) != "250 "){
$this->result = 'Error 83: '.$rcv;
return false;
}
if(FUNC::is_connection($sock)){
if(fputs($sock, 'RSET'.$this->_crlf)){
if(FUNC::is_connection($sock)){
if($rcvr = @fgets($sock, $this->max_sl)){
if(substr($rcvr, 0, 3) == "250"){
if(fputs($sock, 'QUIT'.$this->_crlf)){
if(FUNC::is_connection($sock)){
if($rcvq = @fgets($sock, $this->max_sl)) $rcv = $rcvq;
FUNC::close($sock);
}
}
}
}
}
}
}
$this->result = 'Success: '.$rcv;
return true;
}
function _sendtohost($hname, $arrto, $isrelay){
$ret = false;
if($hname == "localhost"){
$ret = mail($this->_content['header']['to'], $this->_subject, implode('', $this->_content['body']), $this->_content['header']['local']);
if(!$ret) $ret = $this->_sendtoip('127.0.0.1', $arrto, $isrelay);
}else{
if($isrelay) $ret = $this->_sendtoip($hname, $arrto, $isrelay);
else{
if(FUNC::is_ipv4($hname)) $ret = $this->_sendtoip($hname, $arrto, $isrelay);
else{
$resmx = FUNC::is_win() ? FUNC::getmxrr_win($hname, $mxhost) : getmxrr($hname, $mxhost);
$iparr = array();
if($resmx){
foreach($mxhost as $hostname){
$iphost = gethostbyname($hostname);
if($iphost != $hname && FUNC::is_ipv4($iphost) && !isset($iparr[$iphost])) $iparr[$iphost] = $iphost;
}
}else{
$iphost = gethostbyname($hname);
if($iphost != $hname && FUNC::is_ipv4($iphost)) $iparr[$iphost] = $iphost;
}
if(count($iparr) > 0){
foreach($iparr as $ipaddr) if($ret = $this->_sendtoip($ipaddr, $arrto, $isrelay)) break;
}else trigger_error('Can not find any valid ip address for hostname "'.$hname.'", on class SMTP::_sendtohost()', 512);
}
}
}
return $ret;
}
function _splitmsg($longmsg, $approx = 10240){
$longmsg = str_replace(array(".\r\n", ".\n", ".\r"), ". ".$this->_crlf, $longmsg);
$msgarr = explode($this->_crlf, $longmsg);
$addmsg = "";
$arrmsg = array();
foreach($msgarr as $inline){
$addmsg .= $inline.$this->_crlf;
if(strlen($addmsg) >= $approx){
$arrmsg[] = $addmsg;
$addmsg = "";
}
}
if(count($arrmsg) > 0 && $addmsg != "") $arrmsg[] = $addmsg;
else $arrmsg[] = $longmsg;
return $arrmsg;
}
function _getunique(){
return md5(microtime(1).$this->_unique++);
}
function _putcid($str, $ids){
$find1 = $repl1 = array();
foreach($ids as $name => $code){
$find1[] = "=\"".$name;
$repl1[] = "=\"cid:".$code;
$find2[] = "=".$name;
$repl2[] = "=cid:".$code;
}
$res = str_replace($find1, $repl1, $str);
$res = str_replace($find2, $repl2, $res);
return $res;
}
function _encodemsg($src, $enc){
$res = '';
if($enc == "7bit" || $enc == "8bit") $res .= chunk_split($src, $this->_chanklen, $this->_crlf);
elseif($enc == "base64") $res .= chunk_split(base64_encode($src), $this->_chanklen, $this->_crlf);
elseif($enc == "quoted-printable") $res .= $this->qpencode($src, $this->_chanklen, $this->_crlf);
return $res;
}
function _writemsg(){
if(!$this->_fromaddr){
$fromaddr = ini_get('sendmail_from');
if($fromaddr == ""){
if(isset($_SERVER['SERVER_ADMIN']) && FUNC::is_mail($_SERVER['SERVER_ADMIN'])) $fromaddr = $_SERVER['SERVER_ADMIN'];
elseif(isset($_SERVER['SERVER_NAME'])) $fromaddr = 'postmaster@'.$_SERVER['SERVER_NAME'];
elseif(isset($_SERVER['HTTP_HOST'])) $fromaddr = 'postmaster@'.$_SERVER['HTTP_HOST'];
elseif(isset($_SERVER['REMOTE_ADDR'])) $fromaddr = 'postmaster@'.$_SERVER['REMOTE_ADDR'];
elseif(isset($_SERVER['SERVER_ADDR'])) $fromaddr = 'postmaster@'.$_SERVER['SERVER_ADDR'];
else $fromaddr = 'hide@address.com';
}
$this->_fromaddr = array('address' => $fromaddr, 'name' => '');
}
if(!$this->_fromhost){
if(isset($_SERVER['SERVER_NAME'])) $this->_fromhost = $_SERVER['SERVER_NAME'];
elseif(isset($_SERVER['HTTP_HOST'])) $this->_fromhost = $_SERVER['HTTP_HOST'];
elseif(isset($_SERVER['REMOTE_ADDR'])) $this->_fromhost = $_SERVER['REMOTE_ADDR'];
elseif(isset($_SERVER['SERVER_ADDR'])) $this->_fromhost = $_SERVER['SERVER_ADDR'];
else{
$fexp = explode('@', $this->_fromaddr['address']);
$this->_fromhost = $fexp[1];
}
}
$tostr = $ccstr = $bccstr = '';
foreach($this->_toaddrs as $taddr => $tname){
if($tname == "") $tostr .= $taddr.', ';
else $tostr .= '"'.str_replace('"', '\\"', $tname).'" <'.$taddr.'>, ';
}
$tostr = $hto = substr($tostr, 0, -2);
if($this->_ccaddrs && count($this->_ccaddrs) > 0){
foreach($this->_ccaddrs as $caddr => $cname){
if($cname == "") $ccstr .= $caddr.', ';
else $ccstr .= '"'.str_replace('"', '\\"', $cname).'" <'.$caddr.'>, ';
}
$ccstr = substr($ccstr, 0, -2);
}
if($this->_bccaddrs && count($this->_bccaddrs) > 0){
foreach($this->_bccaddrs as $baddr => $bname) $bccstr .= $baddr.', ';
$bccstr = substr($bccstr, 0, -2);
}
if($this->_fromaddr['name'] == "") $fromstr = $this->_fromaddr['address'];
else $fromstr = '"'.str_replace('"', '\\"', $this->_fromaddr['name']).'" <'.$this->_fromaddr['address'].'>';
$arrval1 = $arrval2 = array();
$arrval1[] = array('name' => 'From', 'value' => $fromstr);
$arrval2[] = array('name' => 'From', 'value' => $fromstr);
$arrval2[] = array('name' => 'To', 'value' => $tostr);
$arrval2[] = array('name' => 'Subject', 'value' => $this->_subject);
if($ccstr != ""){
$arrval1[] = array('name' => 'Cc', 'value' => $ccstr);
$arrval2[] = array('name' => 'Cc', 'value' => $ccstr);
}
if($bccstr != "") $arrval1[] = array('name' => 'Bcc', 'value' => $bccstr);
$arrval2[] = array('name' => 'Date', 'value' => date('r'));
if($this->_header && count($this->_header) > 0){
foreach($this->_header as $hvarr){
$arrval1[] = $hvarr;
$arrval2[] = $hvarr;
}
}
$xmail = array('name' => base64_decode('WC1NYWlsZXI='), 'value' => base64_decode('WFBNMiB2LjAuMSA8d3d3LnhwZXJ0bWFpbGVyLmNvbT4='));
$arrval1[] = $xmail;
$arrval2[] = $xmail;
$hval1 = $hval2 = $bval = '';
foreach($arrval1 as $heach1) $hval1 .= $heach1['name'].': '.$heach1['value'].$this->_crlf;
foreach($arrval2 as $heach2) $hval2 .= $heach2['name'].': '.$heach2['value'].$this->_crlf;
$multipart = false;
if($this->_atext && $this->_ahtml) $multipart = true;
if($this->_attach && count($this->_attach) > 0) $multipart = true;
if($multipart){
$bval .= 'This is a message in MIME Format. If you see this, your mail reader does not support this format.'.$this->_crlf.$this->_crlf;
$boundary1 = '=_'.$this->_getunique();
$boundary2 = '=_'.$this->_getunique();
$boundary3 = '=_'.$this->_getunique();
$haveatt = ($this->_attach && count($this->_attach) > 0) ? true : false;
$inline = $attachment = false;
$idarr = array();
if($haveatt){
foreach($this->_attach as $attdesc){
if($attdesc['disp'] == "inline"){
$inline = true;
$fname = $attdesc['name'];
if(!isset($idarr[$fname])) $idarr[$fname] = $this->_getunique();
}else $attachment = true;
}
}
$hadd = '';
if($this->_atext && $this->_ahtml){
$vhtml = (count($idarr) > 0) ? $this->_putcid($this->_ahtml[2], $idarr) : $this->_ahtml[2];
if($inline && $attachment){
$hadd .= 'Content-Type: multipart/mixed;'.$this->_crlf."\t".'boundary="'.$boundary1.'"'.$this->_crlf;
$bval .= '--'.$boundary1.$this->_crlf.
'Content-Type: multipart/related;'.$this->_crlf."\t".'boundary="'.$boundary2.'"'.$this->_crlf.$this->_crlf.
'--'.$boundary2.$this->_crlf.
'Content-Type: multipart/alternative;'.$this->_crlf."\t".'boundary="'.$boundary3.'"'.$this->_crlf.$this->_crlf.
'--'.$boundary3.$this->_crlf.
$this->_atext[0].$this->_crlf.$this->_crlf.
$this->_encodemsg($this->_atext[2], $this->_atext[1]).
$this->_crlf.'--'.$boundary3.$this->_crlf.
$this->_ahtml[0].$this->_crlf.$this->_crlf.
$this->_encodemsg($vhtml, $this->_ahtml[1]).
$this->_crlf.'--'.$boundary3.'--'.$this->_crlf;
foreach($this->_attach as $attdesc){
if($attdesc['disp'] == "inline"){
$bval .= '--'.$boundary2.$this->_crlf.
'Content-Type: '.$attdesc['mime'].$this->_crlf.
'Content-Transfer-Encoding: '.$attdesc['encode'].$this->_crlf.
'Content-Disposition: '.$attdesc['disp'].';'.$this->_crlf."\t".'filename="'.$attdesc['name'].'"'.$this->_crlf.
'Content-ID: <'.$idarr[$attdesc['name']].'>'.$this->_crlf.$this->_crlf.
$this->_encodemsg($attdesc['source'], $attdesc['encode']);
}
}
$bval .= '--'.$boundary2.'--'.$this->_crlf;
foreach($this->_attach as $attdesc){
if($attdesc['disp'] == "attachment"){
$bval .= '--'.$boundary1.$this->_crlf.
'Content-Type: '.$attdesc['mime'].$this->_crlf.
'Content-Transfer-Encoding: '.$attdesc['encode'].$this->_crlf.
'Content-Disposition: '.$attdesc['disp'].';'.$this->_crlf."\t".'filename="'.$attdesc['name'].'"'.$this->_crlf.$this->_crlf.
$this->_encodemsg($attdesc['source'], $attdesc['encode']);
}
}
$bval .= '--'.$boundary1.'--';
}elseif($inline){
$hadd .= 'Content-Type: multipart/related;'.$this->_crlf."\t".'boundary="'.$boundary1.'"'.$this->_crlf;
$bval .= '--'.$boundary1.$this->_crlf.
'Content-Type: multipart/alternative;'.$this->_crlf."\t".'boundary="'.$boundary2.'"'.$this->_crlf.$this->_crlf.
'--'.$boundary2.$this->_crlf.
$this->_atext[0].$this->_crlf.$this->_crlf.
$this->_encodemsg($this->_atext[2], $this->_atext[1]).
$this->_crlf.'--'.$boundary2.$this->_crlf.
$this->_ahtml[0].$this->_crlf.$this->_crlf.
$this->_encodemsg($vhtml, $this->_ahtml[1]).
$this->_crlf.'--'.$boundary2.'--'.$this->_crlf;
foreach($this->_attach as $attdesc){
$bval .= '--'.$boundary1.$this->_crlf.
'Content-Type: '.$attdesc['mime'].$this->_crlf.
'Content-Transfer-Encoding: '.$attdesc['encode'].$this->_crlf.
'Content-Disposition: '.$attdesc['disp'].';'.$this->_crlf."\t".'filename="'.$attdesc['name'].'"'.$this->_crlf.
'Content-ID: <'.$idarr[$attdesc['name']].'>'.$this->_crlf.$this->_crlf.
$this->_encodemsg($attdesc['source'], $attdesc['encode']);
}
$bval .= '--'.$boundary1.'--';
}elseif($attachment){
$hadd .= 'Content-Type: multipart/mixed;'.$this->_crlf."\t".'boundary="'.$boundary1.'"'.$this->_crlf;
$bval .= '--'.$boundary1.$this->_crlf.
'Content-Type: multipart/alternative;'.$this->_crlf."\t".'boundary="'.$boundary2.'"'.$this->_crlf.$this->_crlf.
'--'.$boundary2.$this->_crlf.
$this->_atext[0].$this->_crlf.$this->_crlf.
$this->_encodemsg($this->_atext[2], $this->_atext[1]).
$this->_crlf.'--'.$boundary2.$this->_crlf.
$this->_ahtml[0].$this->_crlf.$this->_crlf.
$this->_encodemsg($vhtml, $this->_ahtml[1]).
$this->_crlf.'--'.$boundary2.'--'.$this->_crlf;
foreach($this->_attach as $attdesc){
$bval .= '--'.$boundary1.$this->_crlf.
'Content-Type: '.$attdesc['mime'].$this->_crlf.
'Content-Transfer-Encoding: '.$attdesc['encode'].$this->_crlf.
'Content-Disposition: '.$attdesc['disp'].';'.$this->_crlf."\t".'filename="'.$attdesc['name'].'"'.$this->_crlf.$this->_crlf.
$this->_encodemsg($attdesc['source'], $attdesc['encode']);
}
$bval .= '--'.$boundary1.'--';
}else{
$hadd .= 'Content-Type: multipart/alternative;'.$this->_crlf."\t".'boundary="'.$boundary1.'"'.$this->_crlf;
$bval .= '--'.$boundary1.$this->_crlf.
$this->_atext[0].$this->_crlf.$this->_crlf.
$this->_encodemsg($this->_atext[2], $this->_atext[1]).
$this->_crlf.'--'.$boundary1.$this->_crlf.
$this->_ahtml[0].$this->_crlf.$this->_crlf.
$this->_encodemsg($vhtml, $this->_ahtml[1]).
$this->_crlf.'--'.$boundary1.'--';
}
}elseif($this->_atext){
$hadd .= 'Content-Type: multipart/mixed;'.$this->_crlf."\t".'boundary="'.$boundary1.'"'.$this->_crlf;
$bval .= '--'.$boundary1.$this->_crlf.
$this->_atext[0].$this->_crlf.$this->_crlf.
$this->_encodemsg($this->_atext[2], $this->_atext[1]).$this->_crlf;
foreach($this->_attach as $attdesc){
$bval .= '--'.$boundary1.$this->_crlf.
'Content-Type: '.$attdesc['mime'].$this->_crlf.
'Content-Transfer-Encoding: '.$attdesc['encode'].$this->_crlf.
'Content-Disposition: '.$attdesc['disp'].';'.$this->_crlf."\t".'filename="'.$attdesc['name'].'"'.$this->_crlf.$this->_crlf.
$this->_encodemsg($attdesc['source'], $attdesc['encode']);
}
$bval .= '--'.$boundary1.'--';
}elseif($this->_ahtml){
$vhtml = (count($idarr) > 0) ? $this->_putcid($this->_ahtml[2], $idarr) : $this->_ahtml[2];
if($inline && $attachment){
$hadd .= 'Content-Type: multipart/mixed;'.$this->_crlf."\t".'boundary="'.$boundary1.'"'.$this->_crlf;
$bval .= '--'.$boundary1.$this->_crlf.
'Content-Type: multipart/related;'.$this->_crlf."\t".'boundary="'.$boundary2.'"'.$this->_crlf.$this->_crlf.
'--'.$boundary2.$this->_crlf.
$this->_ahtml[0].$this->_crlf.$this->_crlf.
$this->_encodemsg($vhtml, $this->_ahtml[1]).$this->_crlf;
foreach($this->_attach as $attdesc){
if($attdesc['disp'] == "inline"){
$bval .= '--'.$boundary2.$this->_crlf.
'Content-Type: '.$attdesc['mime'].$this->_crlf.
'Content-Transfer-Encoding: '.$attdesc['encode'].$this->_crlf.
'Content-Disposition: '.$attdesc['disp'].';'.$this->_crlf."\t".'filename="'.$attdesc['name'].'"'.$this->_crlf.
'Content-ID: <'.$idarr[$attdesc['name']].'>'.$this->_crlf.$this->_crlf.
$this->_encodemsg($attdesc['source'], $attdesc['encode']);
}
}
$bval .= '--'.$boundary2.'--'.$this->_crlf;
foreach($this->_attach as $attdesc){
if($attdesc['disp'] == "attachment"){
$bval .= '--'.$boundary1.$this->_crlf.
'Content-Type: '.$attdesc['mime'].$this->_crlf.
'Content-Transfer-Encoding: '.$attdesc['encode'].$this->_crlf.
'Content-Disposition: '.$attdesc['disp'].';'.$this->_crlf."\t".'filename="'.$attdesc['name'].'"'.$this->_crlf.$this->_crlf.
$this->_encodemsg($attdesc['source'], $attdesc['encode']);
}
}
$bval .= '--'.$boundary1.'--';
}elseif($inline){
$hadd .= 'Content-Type: multipart/related;'.$this->_crlf."\t".'boundary="'.$boundary1.'"'.$this->_crlf;
$bval .= '--'.$boundary1.$this->_crlf.
$this->_ahtml[0].$this->_crlf.$this->_crlf.
$this->_encodemsg($vhtml, $this->_ahtml[1]).$this->_crlf;
foreach($this->_attach as $attdesc){
$bval .= '--'.$boundary1.$this->_crlf.
'Content-Type: '.$attdesc['mime'].$this->_crlf.
'Content-Transfer-Encoding: '.$attdesc['encode'].$this->_crlf.
'Content-Disposition: '.$attdesc['disp'].';'.$this->_crlf."\t".'filename="'.$attdesc['name'].'"'.$this->_crlf.
'Content-ID: <'.$idarr[$attdesc['name']].'>'.$this->_crlf.$this->_crlf.
$this->_encodemsg($attdesc['source'], $attdesc['encode']);
}
$bval .= '--'.$boundary1.'--';
}elseif($attachment){
$hadd .= 'Content-Type: multipart/mixed;'.$this->_crlf."\t".'boundary="'.$boundary1.'"'.$this->_crlf;
$bval .= '--'.$boundary1.$this->_crlf.
$this->_ahtml[0].$this->_crlf.$this->_crlf.
$this->_encodemsg($vhtml, $this->_ahtml[1]).$this->_crlf;
foreach($this->_attach as $attdesc){
$bval .= '--'.$boundary1.$this->_crlf.
'Content-Type: '.$attdesc['mime'].$this->_crlf.
'Content-Transfer-Encoding: '.$attdesc['encode'].$this->_crlf.
'Content-Disposition: '.$attdesc['disp'].';'.$this->_crlf."\t".'filename="'.$attdesc['name'].'"'.$this->_crlf.$this->_crlf.
$this->_encodemsg($attdesc['source'], $attdesc['encode']);
}
$bval .= '--'.$boundary1.'--';
}
}
$hadd .= 'MIME-Version: 1.0';
$hval1 .= $hadd;
$hval2 .= $hadd;
}else{
if($this->_atext){
$hval1 .= $this->_atext[0];
$hval2 .= $this->_atext[0];
$bval .= $this->_encodemsg($this->_atext[2], $this->_atext[1]);
}else{
$hval1 .= $this->_ahtml[0];
$hval2 .= $this->_ahtml[0];
$bval .= $this->_encodemsg($this->_ahtml[2], $this->_ahtml[1]);
}
}
return array('header' => array('to' => $hto, 'local' => $hval1, 'client' => $hval2.$this->_crlf.$this->_crlf), 'body' => $this->_splitmsg($bval));
}
function send($subject){
$ret = false;
if(is_string($subject)){
$subject = FUNC::str_clear($subject);
$subject = trim($subject);
if($subject != ""){
$this->_subject = $this->qpheader($subject);
$ver = true;
if(!($this->_toaddrs && count($this->_toaddrs) > 0)){
$ver = false;
trigger_error('You must set "To" e-mail address(es) using function "AddTo()", on class SMTP::send()', 512);
}
if(!($this->_atext || $this->_ahtml)){
$ver = false;
trigger_error('You must set the mail message using function(s) "Text() or/and Html()", on class SMTP::send()', 512);
}
if($ver){
if($this->_ccaddrs && count($this->_ccaddrs) > 0){
$clearcc1 = array();
foreach($this->_ccaddrs as $ccaddrs1 => $ccname1){
$vercc1 = true;
foreach($this->_toaddrs as $toaddrs1 => $toname1){
if($ccaddrs1 == $toaddrs1) $vercc1 = false;
}
if($vercc1) $clearcc1[$ccaddrs1] = $ccname1;
else trigger_error('The e-mail address "'.$ccaddrs1.'" appear in To and Cc, on class SMTP::send()', 512);
}
$this->_ccaddrs = $clearcc1;
}
if($this->_bccaddrs && count($this->_bccaddrs) > 0){
$clearbcc1 = array();
foreach($this->_bccaddrs as $bccaddrs1 => $bccname1){
$verbcc1 = true;
foreach($this->_toaddrs as $toaddrs2 => $toname2){
if($bccaddrs1 == $toaddrs2) $verbcc1 = false;
}
if($verbcc1) $clearbcc1[$bccaddrs1] = $bccname1;
else trigger_error('The e-mail address "'.$bccaddrs1.'" appear in To and Bcc, on class SMTP::send()', 512);
}
$this->_bccaddrs = $clearbcc1;
}
if($this->_bccaddrs && count($this->_bccaddrs) > 0 && $this->_ccaddrs && count($this->_ccaddrs) > 0){
$clearbcc2 = array();
foreach($this->_bccaddrs as $bccaddrs2 => $bccname2){
$verbcc2 = true;
foreach($this->_ccaddrs as $ccaddrs2 => $ccname2){
if($bccaddrs2 == $ccaddrs2) $verbcc2 = false;
}
if($verbcc2) $clearbcc2[$bccaddrs2] = $bccname2;
else trigger_error('The e-mail address "'.$bccaddrs2.'" appear in Cc and Bcc, on class SMTP::send()', 512);
}
$this->_bccaddrs = $clearbcc2;
}
$group = $alldom = array();
foreach($this->_toaddrs as $toaddrs3 => $toname3){
$exp1 = explode('@', $toaddrs3);
$group[$exp1[1]][] = $toaddrs3;
$alldom[] = $toaddrs3;
}
if($this->_ccaddrs && count($this->_ccaddrs) > 0){
foreach($this->_ccaddrs as $ccaddrs3 => $ccname3){
$exp2 = explode('@', $ccaddrs3);
$group[$exp2[1]][] = $ccaddrs3;
$alldom[] = $ccaddrs3;
}
}
if($this->_bccaddrs && count($this->_bccaddrs) > 0){
foreach($this->_bccaddrs as $bccaddrs3 => $bccname3){
$exp3 = explode('@', $bccaddrs3);
$group[$exp3[1]][] = $bccaddrs3;
$alldom[] = $bccaddrs3;
}
}
$this->_content = $this->_writemsg();
$success = false;
foreach($this->_smtpconn as $conntype){
if(!$success){
if($conntype == "local"){
$success = $this->_sendtohost('127.0.0.1', $alldom, false);
}elseif($conntype == "relay"){
if($this->_relay) $success = $this->_sendtohost($this->_relay['ip'], $alldom, true);
else trigger_error('You must set relay options with function "Relay()" in order to use relay connection, on class SMTP::send()', 512);
}elseif($conntype == "client"){
$back1 = $back2 = true;
foreach($group as $hostname => $domaddrs){
$back1 = $this->_sendtohost($hostname, $domaddrs, false);
if(!$back1) $back2 = false;
}
$success = $back2;
}
}else break;
}
$ret = $success;
}
}else trigger_error('Invalid subject value, on class SMTP::send()', 512);
}else trigger_error('Invalid subject type value, on class SMTP::send()', 512);
return $ret;
}
}
?>