<?php
/**
 * CogiMail : PPH Class for mail sending
 *
 * Simple PHP class to send email to different address 
 * with files attached
 *
 * PHP version 5
 *
 * LICENSE: This source file is subject to version 3.01 of the PHP license
 * that is available through the world-wide-web at the following URI:
 * http://www.php.net/license/3_01.txt.  If you did not receive a copy of
 * the PHP License and are unable to obtain it through the web, please
 * send a note to license@php.net so we can mail you a copy immediately.
 *
 * @author     Philippe Giraud (Cogitium) <phgiraud@cogitium.com>
 * @copyright  2010-2016 COGITIUM
 * @license    http://www.php.net/license/3_01.txt  PHP License 3.01
 */

/**
 * CogiMail - PHP email creation and transport class.
 * @package CogiMail
 * @author Philippe Giraud (Cogitium) <phgiraud@cogitium.com>
 */
class CogiMail {

    /**
     * Name of the sender
     * @var string 
     */
    private $_senderName;

    /**
     * Email of the sender
     * @var string 
     */
    private $_senderMail;      

    /**
     * Email for reply to
     * @var string 
     */
    private $_replyToMail;         

    /**
     * Recipients mails list (separated by ;)
     * @var string
     */
    private $_recipientsMails;  

    /**
     * Recipients bcc mails list (separated by ;)
     * @var string 
     */
    private $_bccMails;           

    /**
     * Email object
     * @var string 
     */
    private $_mailObject;         

    /**
     * Email content in plain text
     * @var string 
     */
    private $_mailPlainText;         

    /**
     * Email content in html formated text
     * @var string 
     */
    private $_mailHtml;        

    /**
     * Files list to join the email (separated by ;)
     * @var string 
     */
    private $_mailFiles;    

    /**
     * Message built to be send
     * @var string 
     */
    private $_message;          

    /**
     * Frontier to separate the different parts of the content
     * @var string 
     */
    private $_frontier;       

    /**
     * Headers of the email
     * @var string 
     */
    private $_headers;       

    /**
     * Constructor.
     *
     * Initialize the component with the sender informations.
     *
     * @param string $senderMail Email of the sender.
     *
     * @param string $senderName Name of the sender.
     *
     * @param string $replyToMail (optional) Email for reply to.
     *
     * @throws InvalidArgumentException If the sender mail or replyto mail is invalid.
     *
     * @return void
     */
    public function __construct($senderMail, $senderName, $replyToMail = "") {

        if (!self::_isEmail($senderMail)) {
            throw new InvalidArgumentException("Invalid sender email!");
        }
        if (!self::_isEmail($replyToMail)) {
            throw new InvalidArgumentException("Invalid replyto email !");
        }

        $this->_senderName = $senderName;
        $this->_senderMail = $senderMail;
        $this->_replyToMail = $replyToMail;
        $this->_recipientsMails = '';
        $this->_bccMails = '';
        $this->_mailObject = '';
        $this->_mailPlainText = '';
        $this->_mailHtml = '';
        $this->_mailFiles = '';
        $this->_message = '';
        $this->_frontier = md5(uniqid(mt_rand()));
        $this->_headers = '';
    }  

    /**
     * Email validation.
     *
     * Return true or false if the email is valid or not
     *
     * @param string $email Email to be validated
     *
     * @return boolean
     */
    private static function _isEmail($email) {
        return filter_var($email, FILTER_VALIDATE_EMAIL);
    }

    /**
     * Add a recipient email.
     *
     * Add a recipient email to the recipients list.
     *
     * @param string $mail Email of the recipient to add.
     *
     * @throws InvalidArgumentException If the recipient mail is invalid.
     *
     * @return void
     */
    public function addRecipientEmail($mail) {

        if (!self::_isEmail($mail)) {
            throw new InvalidArgumentException("Invalid recipient email !");
        }
        if ($this->_recipientsMails === '') {
            $this->_recipientsMails = $mail;
        } else {
            $this->_recipientsMails .= ';' . $mail;
        }
    }

    /**
     * Add a bcc recipient email.
     *
     * Add a bcc recipient email to the bcc recipients list.
     *
     * @param string $mail Email of the bcc recipient to add.
     *
     * @throws InvalidArgumentException If the bcc recipient mail is invalid.
     *
     * @return void
     */
    public function addBccRecipientMail($mail) {

        if (!self::_isEmail($mail)) {
            throw new InvalidArgumentException("Invalid bcc recipent email !");
        }
        if ($this->_bccMails === '') {
            $this->_bccMails = $mail;
        } else {
            $this->_bccMails .= ';' . $mail;
        }
    }

    /**
     * Add a file to join to the email.
     *
     * Add a file to the files list to join to the email.
     * File type could be jpg, jpeg, gif, png, pdf, doc, and others
     *
     * @param string $fileUrl Url of the file to add to the list.
     *
     * @throws InvalidArgumentException If the file url does not exist.
     *
     * @return void
     */
    public function addFile($fileUrl) {

        if (!file_exists($fileUrl)) {
            throw new InvalidArgumentException('The file does not exist !');
        }
        if ($this->_mailFiles === '') {
            $this->_mailFiles = $fileUrl;
        } else {
            $this->_mailFiles .= ';' . $fileUrl;
        }
    }

    /**
     * Initialize the content of the email.
     *
     * Initialize the content of the email : object, text, html text.
     *
     * @param string $mailObject The object of the email.
     *
     * @param string $mailPlainText The plain text of the email.
     *
     * @param string $mailHtml The html text of the email.
     *
     * @return void
     */
    public function contentMail($mailObject, $mailPlainText, $mailHtml) {

        $this->_mailObject = $mailObject;
        $this->_mailPlainText = $mailPlainText;
        $this->_mailHtml = $mailHtml;
    }

    /**
     * Email debug.
     *
     * Display a formated dump of the email object.
     *
     * @return void
     */
    public function debugMail() {

        echo "<p>=========== Mail debug ===========</p>";
        echo "<pre>";
        print_r($this);
        echo "</pre>";
        echo "<p>============ Debug end ===========</p>";
    }

    /**
     * Send the email.
     *
     * Send the email with the data initialized.
     *
     * @throws InvalidArgumentException If the cannot be sent.
     *
     * @return void
     */
    public function sendMail() {

        // Mail header
        $this->_headers  = 'From: "' . $this->_senderName . '" <' . $this->_senderMail . '>' . "\n"; 
        $this->_headers .= 'Return-Path: <' . $this->_replyToMail . '>' . "\n"; 
        $this->_headers .= 'MIME-Version: 1.0' . "\n"; 
        if ($this->_bccMails !== '') {
            $this->_headers .= "Bcc: " . $this->_bccMails . "\n";
        }
        $this->_headers .= 'Content-Type: multipart/mixed; boundary="' . $this->_frontier . '"';

        // Plain text
        if ($this->_mailPlainText !== '') {
            $this->_message .= '--' . $this->_frontier . "\n"; 
            $this->_message .= 'Content-Type: text/plain; charset="utf-8"' . "\n"; 
            $this->_message .= 'Content-Transfer-Encoding: 8bit' . "\n\n"; 
            $this->_message .= $this->_mailPlainText . "\n\n";
        }

        // Html text
        if ($this->_mailHtml !== '') {
            $this->_message .= '--' . $this->_frontier . "\n"; 
            $this->_message .= 'Content-Type: text/html; charset="utf-8"' . "\n"; 
            $this->_message .= 'Content-Transfer-Encoding: 8bit' . "\n\n"; 
            $this->_message .= $this->_mailHtml . "\n\n"; 
        }

        // Files
        if ($this->_mailFiles !== '') {
            $tabFichiers = explode(';', $this->_mailFiles);
            $nbFichiers = count($tabFichiers);

            for ($i = 0; $i < $nbFichiers; $i++) {
                $this->_message .= '--' . $this->_frontier . "\n"; 
                $this->_message .= 'Content-Type: ' . mime_content_type($tabFichiers[$i]) . '; name="' . $tabFichiers[$i] . '"' . "\n"; 
                $this->_message .= 'Content-Transfer-Encoding: base64' . "\n"; 
                $this->_message .= 'Content-Disposition:attachement; filename="' . $tabFichiers[$i] . '"' . "\n\n"; 
                $this->_message .= chunk_split(base64_encode(file_get_contents($tabFichiers[$i]))) . "\n\n"; 
            }
        }

        // Sending 
        if (!mail($this->_recipientsMails, $this->_mailObject, $this->_message, $this->_headers)) {
            throw new Exception('The mail cannot be send !');
        }

    }

}  
