Logo classes.scriptsphp.org PHP

go to nav bar

Mail5

La classe mail5 fourni des fonctions permettant de construire puis d'envoyer des mail texte, html avec ou sans pièces jointes.

La nouvelle mouture permet l'envoi grace aux fonctions intégrées a PHP ainsi que directement grace au sockets. Ainsi que l'envoi a des destinataires multiples. De plus la nouvelle mouture devrait mieux s'accordé avec les système antispam. Par contre elle nécessite l'usage de PHP5.

Les Méthodes

Exemples

  1. Exemple plain text
  2. Exemple HTML et attachement

La Source

<?php
class mailFieldFilter {
    public 
$log = array();

    function 
__construct() {
    }

    function 
checkAddress($address) {
        if ( 
preg_match('`([[:alnum:]]([-_.]?[[:alnum:]])*@[[:alnum:]]([-_.]?[[:alnum:]])*\.([a-z]{2,4}))`'$address) ) {
            return 
TRUE;
        } else {
            
$this->log['Error'][] = "invalid address: $address;"; return FALSE;
        }
    }

    function 
checkName($name) {
        if ( 
preg_match("`[0-9a-zA-Z\.\-_ ]*`" $name ) ) {
            return 
TRUE;
        } else {
            
$this->log['Error'][] = "invalid name: $name;"; return FALSE;
        }
    }

}

class 
QP {

    static function 
encode($input$line_max 76) {

        
$hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
        
$lines preg_split("/(?:\r\n|\r|\n)/"$input);
        
$eol "\r\n";
        
$escape "=";
        
$output "";

        while( list(, 
$line) = each($lines) ) {
            
$line rtrim($line);
            
$linlen strlen($line);
            
$newline "";
            for(
$i 0$i $linlen$i++) {
                
$c substr($line$i1);
                
$dec ord($c);
                if ( (
$dec == 32) && ($i == ($linlen 1)) ) {
                    
$c "=20";
                } elseif ( (
$dec == 61) || ($dec 32 ) || ($dec 126) ) {
                    
$h2 floor($dec/16); $h1 floor($dec%16);
                    
$c $escape.$hex["$h2"].$hex["$h1"];
                }
                if ( (
strlen($newline) + strlen($c)) >= $line_max ) {
                    
$output .= $newline.$escape.$eol;
                    
$newline "";
                }
                
$newline .= $c;
            }
            
$output .= $newline.$eol;
        }
        return 
trim($output);
    }

    static function 
headerEncode($in) {

        
$in QP::encode($in);
        
$in str_replace("=\r\n"""$in);
        
$in str_replace("?""=3F"$in);
        
$in chunk_split($in55);
        if (
substr($in, -2) == "\r\n"$in substr($in0, -2);
        
$in str_replace("\r\n""?=\r\n =?ISO-8859-1?Q?"$in);
        
$in "=?ISO-8859-1?Q?" $in "?=" ;
        return 
$in;
    }

    static function 
needQP($in) {
        
$in = (string) $in;
        if ( empty(
$in) ) return FALSE;
        
$return FALSE;
        for(
$i 0;$i<strlen($in) ;$i++ ) {
            
$ord ord($in{$i});
            if (
$ord<32 || $ord>126) {
                
$return TRUE;
            }
        }
        return 
$return;
    }
}

class 
mailHeaderField {
    public 
$name NULL;
    public 
$value NULL;
    public 
$type NULL;
    public 
$list = array();

    function 
__construct($name$value NULL$type 'S') {
        
$this->name $name;
        
$this->value $value;
        
$this->type $type;
    }

    function 
addRecipient($namePlusAddress) {
        
$this->type 'RL';
        
$this->list[] = $namePlusAddress ;
    }

    function 
addValueString($value) {
        
$this->type 'S';
        
$this->value $value;
    }

    function 
value2string() {
        return (string) 
$this->value;
    }

    function 
recipientList2string() {
        return 
implode ', ',$this->list );
    }

    function 
rawValue() {
        if (
$this->type == 'S') return $this->value2string();
        if (
$this->type == 'RL') return $this->recipientList2string();
        return 
FALSE;
    }

    function 
rawValueIter() {
        if ( ! list(, 
$val) = each($this->list) ) return FALSE;
        if (
is_string($val)) return $val;
        return 
FALSE;
    }

    function 
toString() {
        if (
$this->type == 'S'$buffer $this->value2string();
        if (
$this->type == 'RL'$buffer $this->recipientList2string();
        if ( 
QP::needQP($buffer) ) {
            
$buffer QP::headerEncode($buffer);
            return 
sprintf('%s: %s',$this->name,$buffer);
        } else {
            
$buffer chunk_splitsprintf('%s: %s',$this->name$buffer), 74"\r\n\t");
            if (
substr($buffer, -3) == "\r\n\t"$buffer substr($buffer0, -3);
            return 
$buffer;
        }
    }
}

class 
mailModel {
    public 
$header = array();
    public 
$body = array();
    public 
$log = array();
    public 
$param = array();
    private 
$fieldFilter;

    function 
__construct() {
        
$this->fieldFilter = new mailFieldFilter;
        
$this->param['TO1by1'] = false;
        
$this->param['addHeaderNoCRLF'] = false;

        
$this->header['XMailer'] = new mailHeaderField ('X-mailer','PHP');
        
$this->header['XPriority'] = new mailHeaderField ('X-priority','3');
    }

    private function 
makeNamePlusAddress($address ,$name NULL) {
        if ( empty(
$name) ) { return $address; }
        if ( !
$this->fieldFilter->checkAddress($address) ) return FALSE;
        if ( !
$this->fieldFilter->checkName($name) ) return FALSE;
        return 
sprintf('"%s" <'.'%s>',$name,$address);
    }

    public function 
setParam($param $value ) {
        
$this->param[$param] = $value;
        return 
TRUE;
    }

    function 
addHeaderField($label$field ,$value$type 'S') {
        
$this->header['addField'][$label] = new mailHeaderField $field$value$type );
    }

    private function 
addRecipient ($label$header$mail ,$name='') {
        
$tmp $this->makenameplusaddress($mail$name);
        if ( !
$tmp ) {
            
$this->log['Error'][] = 'Add recipient '.$header.' error: '.$tmp;
            return 
FALSE;
        }
        if (!isset(
$this->header[$label])) $this->header[$label] = new mailHeaderField ($header);
        
$this->header[$label]->addRecipient$tmp );
        return 
TRUE;
    }

    public function 
addTO($mail$name ='' ) {
        
$check $this->addRecipient('TO','To'$mail$name );
        if ( 
count($this->header['TO']->list)>$this->param['TO1by1'] = true;
        return 
$check;
    }

    public function 
addCC($mail$name ='' ) {
        return 
$this->addRecipient('CC''Cc'$mail$name );
    }

    public function 
addBCC($mail$name ='' ) {
        return 
$this->addRecipient('BCC''BCC'$mail$name );
    }

    public function 
addReturnPath($mail$name ='' ) {
        return 
$this->addRecipient('ReturnP''Return-Path'$mail$name );
    }

    public function 
addReplyTo($mail$name ='' ) {
        return 
$this->addRecipient('ReplyT''Reply-To'$mail$name );
    }

    public function 
addFROM($mail$name ='' ) {
        return 
$this->addRecipient('FROM''From'$mail$name );
    }

    public function 
addSubject($subject ) {
        return 
$this->header['Subject'] = new mailHeaderField 'Subject'$subject )  ;
    }

    public function 
addPlainText($text ) {
        
$this->body['PlainText'] = $text;
        return 
TRUE;
    }

    public function 
addHTML($text ) {
        
$this->body['HTML'] = $text;
        return 
TRUE;
    }

    public function 
addFile($filename$contenttype NULL) {
        if (!
file_exists($filename)) {
            
$this->log['Error'][] = 'No file : '.$filename;
            return 
FALSE;
        }
        
$this->body['attachement'][] = array ( 'filename' => $filename'contenttype' => $contenttype ) ;
        return 
TRUE;
    }

    public function 
addHTMLfile($filename ,$cid '' $contenttype '') {
        if (!
file_exists($filename)) {
            
$this->log['Error'][] = 'No file : '.$filename;
            return 
FALSE;
        }
        
$this->body['htmlattachement'][] = array (  'filename'=>$filename ,
                                                    
'cid'=>$cid ,
                                                    
'contenttype'=>$contenttype );
        return 
TRUE;
    }

}

class 
buildMail {

    public 
$charset 'iso-8859-1';
    public 
$B1B "----=_001";
    public 
$B2B "----=_002";
    public 
$B3B "----=_003";
    public 
$mailModel;
    public 
$log = array();
    public 
$headers '';
    public 
$body '';
    public 
$to '';
    public 
$TZ 'Europe/Paris';

    function 
__construct($mailModel) {
        
$this->mailModel $mailModel;
        
date_default_timezone_set($this->TZ);
    }

    function 
AddField2Header($Field$Value NULL) {
        if (
$Field instanceof mailHeaderField && $this->mailModel->param['TO1by1'] && $Field->name == 'To') {
            if ( ! list(, 
$val) = each($Field->list) ) return FALSE;
            if (
is_string($val)) $this->headers .= chunk_split(sprintf('%s :%s',$Field->name$val), 74,"\r\n\t ")."\r\n";
            return 
TRUE;
        }

        if (
$Field instanceof mailHeaderField$this->headers .= $Field->toString()."\r\n";
        if (
is_string($Field)) $this->headers .= wordwrap(sprintf('%s: %s',$Field$Value), 74,"\r\n\t ")."\r\n";
        return 
TRUE;
    }



    
# Main part #
    
function makeHeader($param = array()) {
        

        
$this->headers '';

        if ( !isset(
$this->mailModel->header['TO'])) {
            
$this->log['Error'][]= "No TO";
            return 
FALSE;
        }

        if ( !isset(
$param['noTO']))
        
$this->AddField2Header($this->mailModel->header['TO']);
        
        if (isset(
$param['TO']))
            
$this->AddField2Header("To"$param['TO']);

        if ( !isset(
$this->mailModel->header['Subject']) ) {
            
$this->log['Error'][] = 'No subject';
            return 
FALSE;
        }

        if ( !isset(
$param['noSubject'])) $this->AddField2Header($this->mailModel->header['Subject']);

        
$this->AddField2Header("Date"date ('r'));

        if ( !isset(
$this->mailModel->header['Xsender']) ) {
            
$this->mailModel->header['Xsender'] = clone $this->mailModel->header['FROM'];
            
$this->mailModel->header['Xsender']->name 'X-sender';
        }
        
$this->AddField2Header($this->mailModel->header['Xsender']);

        if ( !isset(
$this->mailModel->header['ErrorsTo']) ) {
            
$this->mailModel->header['ErrorsTo'] = new mailHeaderField ('Errors-To'$this->mailModel->header['FROM']->rawValue() );
        }
        
$this->AddField2Header($this->mailModel->header['ErrorsTo']);

        if ( isset(
$this->mailModel->header['XMailer']) ) $this->AddField2Header($this->mailModel->header['XMailer']);

        if ( isset(
$this->mailModel->header['XPriority']) ) $this->AddField2Header($this->mailModel->header['XPriority']);

        if ( isset(
$this->mailModel->header['FROM']) ) $this->AddField2Header($this->mailModel->header['FROM']);

        if ( isset(
$this->mailModel->header['ReturnP']) ) $this->AddField2Header($this->mailModel->header['ReturnP']);

        if ( isset(
$this->mailModel->header['ReplyT']) ) $this->AddField2Header($this->mailModel->header['ReplyT']);
        
        if ( 
is_array($this->mailModel->header['addField']) ) {
            foreach(
$this->mailModel->header['addField'] as $val ) {
                
$this->AddField2Header($val);
            }
        }

        
$this->headers .= "MIME-Version: 1.0\r\n";

        if ( !
$this->mailModel->body['HTML'] && $this->mailModel->body['PlainText'] && !empty($this->mailModel->body['attachement']) ) {
            
$this->headers .= sprintf("Content-Type: multipart/mixed;\r\n\t boundary=\"%s\"\r\n"$this->B1B);
        } elseif ( !
$this->mailModel->body['HTML'] && $this->mailModel->body['PlainText'] && empty($this->mailModel->body['attachement']) ) {
            
$this->headers .= "Content-Type: text/plain; charset=iso-8859-1; format=flowed\r\n";
            
$this->headers .= "Content-Transfer-Encoding: quoted-printable\r\n";
        } elseif ( 
$this->mailModel->body['HTML'] ) {
            if ( !
$this->mailModel->body['PlainText'] ) { $this->mailModel->body['PlainText'] = "HTML only!"; }
            
$this->headers .= sprintf("Content-Type: multipart/mixed;\r\n\t boundary=\"%s\"\r\n",$this->B1B);
        }

        if ( isset(
$this->mailModel->header['CC']) && !isset($param['noCC']) ) $this->AddField2Header($this->mailModel->header['CC']);
        
        if ( isset(
$this->mailModel->header['BCC']) && !isset($param['noBCC']) ) $this->AddField2Header($this->mailModel->header['BCC']);

        return 
$this->headers;

    }

    function 
makeBody() {
        
$message='';
        if ( !
$this->mailModel->body['HTML'] && $this->mailModel->body['PlainText'] && !empty($this->mailModel->body['attachement']) ) {
            
$message ="This is a multi-part message in MIME format.";
            
$message .= sprintf("\r\n--%s\r\n",$this->B1B);

            
$message .= "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n";
            
$message .= "Content-Transfer-Encoding: quoted-printable\r\n\r\n";
            
// plaintext goes here
            
$message .= QP::encode($this->mailModel->body['PlainText'])."\r\n\r\n";
            
$message .= $this->writeAttachement($this->mailModel->body['attachement'],$this->B1B);
        }
        elseif ( !
$this->mailModel->body['HTML'] && $this->mailModel->body['PlainText'] && empty($this->mailModel->body['attachement']) ) {
            
// plaintext goes here
            
$message.= QP::encode($this->mailModel->body['PlainText'])."\r\n\r\n";
        }
        elseif ( 
$this->mailModel->body['HTML'] ) {
            
//Messages start with text/html alternatives in OB
            
$message "This is a multi-part message in MIME format.\r\n";
            
$message .= sprintf("\r\n--%s\r\n",$this->B1B);
            
$message .= sprintf("Content-Type: multipart/alternative;\r\n\t boundary=\"%s\"\r\n\r\n",$this->B2B);

            
//plaintext section
            
$message .= sprintf("\r\n--%s\r\n",$this->B2B);
            
$message .= "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n";
            
$message .= "Content-Transfer-Encoding: quoted-printable\r\n\r\n";
            
// plaintext goes here
            
$message .= QP::encode($this->mailModel->body['PlainText'])."\r\n\r\n";

            
$message .= sprintf("\r\n--%s\r\n",$this->B2B);
            
$message .= sprintf("Content-Type: multipart/related;\r\n\t boundary=\"%s\"\r\n\r\n",$this->B3B);

            
// html section
            
$message .= sprintf("\n--%s\n",$this->B3B);
            
$message .= "Content-Type: text/html; charset=\"iso-8859-1\"\r\n";
            
$message .= "Content-Transfer-Encoding: quoted-printable\r\n\r\n";
            
// html goes here
            
$message .= QP::encode($this->mailModel->body['HTML'])."\r\n\r\n";

            
// attachments html
            
if (empty($this->mailModel->body['htmlattachement'])) {
                
$message .= sprintf("\r\n--%s--\r\n",$this->B3B);
            } else {
                
$message.=$this->writeAttachement$this->mailModel->body['htmlattachement'],$this->B3B);
            }

            
// end of html
            
$message .= sprintf ("\r\n--%s--\r\n",$this->B2B);

            
// attachments
            
if (empty($this->mailModel->body['attachement'])) {
                
$message .= sprintf("\r\n--%s--\r\n",$this->B1B);
            } else {
                
$message.=$this->writeAttachement($this->mailModel->body['attachement'],$this->B1B);
            }

        }
        
$this->body $message;
        return 
$message;
    }

    function 
writeAttachement($attachement,$B) {
        
$message '';
        if ( !empty(
$attachement) ) {
            foreach(
$attachement as $AttmFile){
                
$patharray explode ("/"$AttmFile['filename']);
                
$FileName $patharray[count($patharray)-1];
                
$message .= "\r\n--".$B."\r\n";
                if (!empty(
$AttmFile['cid'])) {
                    
$message .= "Content-Type: {$AttmFile['contenttype']};\r\n name=\"".$FileName."\"\r\n";
                    
$message .= "Content-Transfer-Encoding: base64\r\n";
                    
$message .= "Content-ID: <{$AttmFile['cid']}>\r\n";
                    
$message .= "Content-Disposition: inline;\n filename=\"".$FileName."\"\r\n\r\n";
                } else {
                    if (
$AttmFile['contenttype']) {
                        
$ctype $AttmFile['contenttype'] ;
                    } else {
                        
$ctype $AttmFile['contenttype']= 'application/octetstream';
                    }
                    
$message .= "Content-Type: ".$ctype.";\r\n name=\"".$FileName."\"\r\n";
                    
$message .= "Content-Transfer-Encoding: base64\r\n";
                    
$message .= "Content-Disposition: attachment;\r\n filename=\"".$FileName."\"\r\n\r\n";
                }

                
$fd=fopen ($AttmFile['filename'], "rb");
                
$FileContent=fread($fd,filesize($AttmFile['filename']));
                
fclose ($fd);

                
$FileContent chunk_split(base64_encode($FileContent));
                
$message .= $FileContent;
                
//$message .= "\r\n";
            
}
            
$message .= "--".$B."--\r\n";
        }
        return 
$message;
    }
}

class 
mailSender {
    public 
$set_mode 'socket';
    public 
$log = array();

    function 
__construct($buildMail) {
        
$this->buildMail $buildMail;
        
$this->socketErrorCode '`251|421|450|451|452|500|501|503|521|550|551|552|553|554`';
    }

    function 
send() {
        switch(
$this->set_mode)    {
            case 
'php' $this->phpMail(); break;
            case 
'socket'$this->socketMailLoop(); break;
        }
        return 
TRUE;
    }

    
# Mail send by PHPmail #
    
function phpMail() {

        
$body $this->CleanMailDataString($this->buildMail->makeBody());
        
$subject $this->buildMail->mailModel->header['Subject']->rawValue();
        if ( 
$this->buildMail->mailModel->param['addHeaderNoCRLF'] ):
            
$header $this->DirtMailDataString($this->buildMail->makeHeader(array ( 'noTO' =>  TRUE'noSubject' => TRUE )));
        else:
            
$header $this->CleanMailDataString($this->buildMail->makeHeader(array ( 'noTO' =>  TRUE'noSubject' => TRUE )));
        endif;

        if (
$this->buildMail->mailModel->param['TO1by1']) {
            while ( 
$to $this->buildMail->mailModel->header['TO']->rawValueIter() ) {
                
                
$mailSentReport mail$to,
                                        
$subject,
                                        
$body,
                                        
$header
                                    
);
                
                if (
$mailSentReport){
                    
$this->log['Success'][] = "Success sending to $to";
                } else {
                    
$this->log['Error'][] = "Error sending to $to";
                }
            }
        } else {
            
$to $this->buildMail->mailModel->header['TO']->rawValue();
            
            
$mailSentReport mail$to,
                                    
$subject,
                                    
$body,
                                    
$header
                                
);
            
            if (
$mailSentReport){
                
$this->log['Success'][] = "Success sending to $to";
            } else {
                
$this->log['Error'][] = "Error sending to $to";
            }

        }
        return 
TRUE;
    }

    
# Socket Function #
    
function SocketStart() {
        if (!
$this->connect fsockopen (ini_get("SMTP"), ini_get("smtp_port"), $errno$errstr30))  {
            
$this->log[] = 'Could not talk to the sendmail server!';
            return 
FALSE;
        }
        return 
fgets($this->connect1024);
    }

    function 
SocketStop() {
        
fclose($this->connect);
        return 
TRUE;
    }

    function 
SocketSend($in,$wait='') {
        
fputs($this->connect$instrlen($in));
        if(empty(
$wait)) {