Просмотр файла class_sendmail.php

Размер файла: 10.42Kb
<?php
/*
Класс рассыльщика почты с вложениями.
1. Письма в тектовом и html форматах.
2. Присоединение любого количества вложений.
3. Реализация прямого соединения с smtp сервером.
Автор: Denvas
*/
class SendMailClass{

    var $boundary = "--------SCS-2006-07-31-i-solutions"; //разделитель
    var $priority=3;//приоритет
    var $charset="";
    var $from; //Отправитель
    var $to;   //Получатель
    var $subj; //Тема письма
    var $replyto;//Кому отвечать

    var $body_plain;  //текст письма
    var $attach=array();//вложенные файлы

    var $SMTPhost;
    var $SMTPlogin;
    var $SMTPpwd;
    
    var $sd;//хэнд сокета

    var $Error="";
    var $endline;//конец строки
    //==================================================//
    /*
    Конструктор
    */
    function SendMailClass(){
        $this->Clear();
        $this->endline="\n";//концом строки у нас будет просто перевод
    }
    //==================================================//
    /*
    Установка кодировки для письма
    */
    function SetCharset($charset){
        $this->charset=$charset;
    }
    //==================================================//
    function Clear(){
        $this->Error="";
        $this->from="";
        $this->replyto="";
        $this->to="";
        $this->subj="";
        $this->body_plain="";
        $this->attach=array();
    }
    //==================================================//
    /*
    Действие: генерация заголовка
    */
    function Header(){
        $header="Reply-To: ".(($this->replyto)?(substr($this->replyto,0,strpos($this->replyto,"@"))." <".$this->replyto.">"):$this->from).$this->endline;
        $header.="From: ".$this->from.$this->endline;
        $header.="MIME-Version: 1.0".$this->endline;
        if(count($this->attach)>0){//письмо с аттачами
            $header.="Content-Type: multipart/mixed; boundary=\"".$this->boundary."\"".$this->endline;
        }
        else{//простое письмо
            if(!empty($this->charset))$charset="; charset=".$this->charset; else $charset="";
            $header.="Content-Type: text/plain".$charset.$this->endline;
        };
        $header.="X-Priority: ".$this->priority.$this->endline;
        return $header;
    }//function Header()
    //==================================================//
    /*
    Действие: присоедининие данных
    */
    function Attach($name, $type, $data){
        $this->attach[]=array($name, $type, $data);
    }//function Attach($name, $type, $data)
    //==================================================//
    /*
    Действие: присоединение файла
    */
    function FileAttach($namefile, $type, $name=""){
        $fd=@fopen($namefile,'r');
        if(!$fd)return false;
        if(!$name)
            $name=basename($namefile);
        if(!$type)$type=mime_content_type($namefile);//автоопределение не работает, но если не оставлять пустым $type, то ошибку выдавать не будет
        $this->Attach($name, $type, fread($fd,filesize($namefile)));
        fclose($fd);
        return true;
    }//function FileAttach($namefile, $type)
    //==================================================//
    /*
    Действие: генерация тела письма
    */
    function Body(){
        $body="";
        $nattach=count($this->attach);
        //письмо без вложений
        if($nattach==0){
            $body.=$this->body_plain.$this->endline;
            return $body;
        };
        //письмо с вложениями
        if(!empty($this->charset))$charset="; charset=".$this->charset; else $charset="";
        $body.="--".$this->boundary.$this->endline; 
        if($this->body_plain){
            $body.="Content-Type: text/plain".$charset.$this->endline;
            $body.="Content-Transfer-Encoding: quoted-printable".$this->endline.$this->endline;
            $body.=$this->body_plain.$this->endline.$this->endline;
            $body.="--".$this->boundary.$this->endline;
        };//if(empty($this->body_plain))
        //вложения
        for($j=0;$j<$nattach;$j++){
            list($name, $type, $data)=$this->attach[$j];
            //файлы для ссылок из html
            if(($name)&&(strpos($type,"text/")!==0)){
                $body.="Content-Type: ".$type.$this->endline;
                $body.="Content-Transfer-Encoding: base64".$this->endline;
                $body.="Content-Location: ".$name.$this->endline;
                $body.="Content-ID: <".$name.">".$this->endline;
                $body.="Content-Disposition: attachment; filename=\"".$this->EncodeBQ($name)."\"".$this->endline.$this->endline;
                $body.=chunk_split(base64_encode($data)).$this->endline;
            }
            else{//нельзя выставлять Content-Disposition, т.к. Outlook начнет считать его вложением и не будет открывать
                $body.="Content-Type: ".$type.$charset.$this->endline;
                $body.="Conent-Transfer-Encoding: quoted-printable".$this->endline.$this->endline;
                $body.=$data.$this->endline.$this->endline;
            };
            $body.= "--".$this->boundary;
            if($j==($nattach-1))$body.="--";
            $body.=$this->endline;
        };//for($j=0;$j<$nattach;$j++)

        return $body;
    }//function Body()
    //==================================================//
    /*
    закодировать русские буквы
    */
    function EncodeBQ($str){
        if($this->charset){
            $str="=?".$this->charset."?B?".base64_encode($str)."?=";
        };
        return $str;
    }//function EncodeBQ($str)
    //==================================================//
    /*
    Действие: данные для письма
    */
    function Mail($from,$to,$subj,$text="",$html=""){
        $this->body_plain=$text;
        if(is_array($from)){
            list($this->from, $this->replyto)=$from;//первое от кого отсылать, второе кому ответить
        }
        else{
            $this->from=$from;
            $this->replyto=$from;
        };
        $this->to=$to;
        $this->subj=(strlen($subj)>0)?$this->EncodeBQ($subj):"";
        if($html)
            $this->Attach("", "text/html", $html);
    }//function Mail($from,$to,$subj,$text,$html="")
    //==================================================//
    /*
    Дальше идет реализация отсылки почты
    */
    //==================================================//
    /*
    Действие: настройка smtp для отправки почты и соединение с сервером
    */
    function SMTPConf($host,$login="",$password=""){
        global $CONF;
        $this->Error="";
        //если хост такойже как и был, то не переконективатся
        if(strcmp($this->SMTPhost,$host)==0){
            return true;
        }
        else{
            if(!empty($this->SMTPhost))$this->SMTPclose();
        };
        $this->SMTPhost=$host;
        $this->SMTPlogin=$login;
        $this->SMTPpwd=$password;
        if(!$host)return true;//отсылка с помощью sendmail
        $port="25";
        $myhost=isset($CONF['domain'])?$CONF['domain']:@$_SERVER['HTTP_HOST'];

        $this->sd = @fsockopen($this->SMTPhost, $port, $errno, $errstr, 30);
        if($this->sd===false){
            $this->Error="SMTP: ERROR CONNECT ".$errstr;
            return false;
        };
        $res=fgets($this->sd, 512);
        //print "S: ".trim($res)."\n";
        //авторизация если задан логи
        if($this->SMTPlogin){
            $this->mess("AUTH LOGIN".$this->endline);
            $this->mess(base64_encode($this->SMTPlogin).$this->endline);
            $this->mess(base64_encode($this->SMTPpwd).$this->endline);
        };//if($login)
        $this->mess("HELO ".$myhost.$this->endline);
        return true;
    }
    //==================================================//
    /*
    Действие: сгенерировать и послать письмо
    */
    function Send(){
        if(!empty($this->SMTPhost)){
            return $this->SendSMTP("To: ".$this->to.$this->endline."Subject: ".$this->subj.$this->endline.$this->Header(), $this->Body());
        }
        else{
            return mail($this->to,$this->subj,$this->Body(),$this->Header());
        };
    }//function Send()
    //==================================================//
    /*
    Действие: послать письмо c уже сформированным заголовком и телом
    */
    function SendHB($head,$body){
        if(!empty($this->SMTPhost)){
            return $this->SendSMTP("To: ".$this->to.$this->endline."Subject: ".$this->subj.$this->endline.$head, $body);
        }
        else{
            return mail($this->to,$this->subj,$body,$head);
        };
    }//function Send()
    //==================================================//
    /*
    Действие: посылка порции данных в сокет
    */
    function mess($str){
        //print "C: ".trim($str)."\n";
        $res="";
        //исправить конец строки
        $str=str_replace("\r","",$str);
        $str=str_replace("\n","\r\n",$str);
        //записать в сокет
        $rw=fwrite($this->sd, $str);
        if(strlen($str)!=$rw){
            $this->Error="Send 0";
            return false;
        };
        $res=fgets($this->sd, 512);//fread не работает. а fgets работает получив конец строки
        //print "S: ".trim($res)."\n";
        return $res;
    }//function mess($str)
    //==================================================//
    /*
    Действие: отсылка письма через SMTP протокол
    Возвращает: истину есил отсылка прошла успешно
    */
    function SendSMTP($head,$body){
        if($this->Error)return false;

        $this->mess("MAIL FROM: ".$this->from.$this->endline);
        $res=$this->mess("RCPT TO: ".$this->to.$this->endline);
        if(!strstr($res,"250")){
            $this->Error="SMTP ERROR: $res\n";
            return false;
        };
        $this->mess("DATA".$this->endline);
        //эти данные нужно добавить, т.к. используя sendmail они подставятся, а напрямую по протоколу нет.
        //отсылка данных
        $this->mess($head.$this->endline.$body.$this->endline.".".$this->endline);
        return true;
    }//function SendSMTP($host,$login="",$password="")
    //==================================================//
    /*
    Закрыть smtp соединение
    */
    function SMTPclose(){
        //завершение
        if(!$this->sd)return;
        $this->mess("QUIT".$this->endline);
        //print "Mail send\n";
        fclose($this->sd);
        unset($this->sd);
    }
    //==================================================//
};
?>