Axiom (v1.2.0)

A lightweight PHP framework
H:/Workspace/php-axiom/www/php-axiom/libraries/axiom/axMail.class.php
Go to the documentation of this file.
00001 <?php
00018 class axMail {
00019     
00024     const HEADER_BCC = "Bcc";
00025     const HEADER_CC = "Cc";
00026     const HEADER_CONTENT_DESCRIPTION = "Content-Description";
00027     const HEADER_CONTENT_TYPE = "Content-Type";
00028     const HEADER_CONTENT_TRANSFERT_ENCODING = "Content-Transfer-Encoding";
00029     const HEADER_DATE = "Date";
00030     const HEADER_FROM = "From";
00031     const HEADER_MIME_VERSION = "MIME-Version";
00032     const HEADER_PRIORITY = "Priority";
00033     const HEADER_REPLY_TO = "Reply-To";
00034     const HEADER_SENDER = "Sender";
00035     const HEADER_SUBJECT = "Subject";
00036     const HEADER_TO = "To";
00037     const HEADER_X_CONFIRM_READING_TO = "X-Confirm-Reading-To";
00038     const HEADER_X_MAILER = "X-Mailer";
00039     const HEADER_X_PRIORITY = "X-Priority";
00040     const HEADER_X_UNSUBSCRIBE_EMAIL = "X-Unsubscribe-Email";
00041     const HEADER_X_UNSUBSCRIBE_WEB = "X-Unsubscribe-Web";
00042     
00043     const HEADER_SEPARATOR_CRLF = "\r\n";
00044     const HEADER_SEPARATOR_LF = "\n";
00045     
00050     public static $allowed_headers = array(
00051         self::HEADER_BCC,                        self::HEADER_CC,                   self::HEADER_CONTENT_DESCRIPTION,
00052         self::HEADER_CONTENT_TRANSFERT_ENCODING, self::HEADER_CONTENT_TYPE,         self::HEADER_DATE,
00053         self::HEADER_FROM,                       self::HEADER_MIME_VERSION,         self::HEADER_PRIORITY,
00054         self::HEADER_REPLY_TO,                   self::HEADER_SENDER,               self::HEADER_SUBJECT,
00055         self::HEADER_TO,                         self::HEADER_X_CONFIRM_READING_TO, self::HEADER_X_MAILER,
00056         self::HEADER_X_PRIORITY,                 self::HEADER_X_UNSUBSCRIBE_WEB,    self::HEADER_X_UNSUBSCRIBE_EMAIL
00057     );
00058     
00063     protected $_header_separator = self::HEADER_SEPARATOR_CRLF;
00064     
00069     protected $_from;
00070     
00075     protected $_to = array();
00076     
00081     protected $_subject;
00082     
00087     protected $_message_parts = array();
00088     
00093     protected $_headers = array();
00094     
00114     public function __construct ($from, $to, $subject = "No Subject", $message = null, array $headers = array()) {
00115         if (!self::validateEmail($from))
00116             throw new InvalidArgumentException('First parameter is expected to be a valid email', 2014);
00117             
00118         $this->_from = $from;
00119             
00120         $to = (array)$to;
00121         foreach ($to as $destination)
00122             $this->addDestination($destination);
00123         
00124         if (!empty($subject))
00125             $this->setSubject($subject);
00126             
00127         if (!empty($message))
00128             $this->addMessagePart($message);
00129         
00130         foreach ($headers as $header => $value)
00131             $this->setHeader($header, $value);
00132     }
00133     
00143     public static function validateEmail ($email) {
00144         if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
00145             return false;
00146         }
00147         
00148         if (function_exists('checkdnsrr')) {
00149             $host = substr($email, strpos($email, '@') + 1);
00150             return checkdnsrr($host, 'MX');
00151         }
00152                 
00153         return true;
00154     }
00155     
00163     public function addDestination ($to) {
00164         if (!self::validateEmail($to))
00165             throw new InvalidArgumentException("Invalid destination", 2015);
00166         
00167         if (!array_keys($this->_to, $to))
00168             $this->_to[] = $to;
00169     }
00170     
00176     public function removeDestination ($to) {
00177         foreach (array_keys($this->_to, $to) as $key)
00178             unset($this->_to[$key]);
00179     }
00180     
00194     public function setHeader ($header, $value) {
00195         if (!in_array($header, self::$allowed_headers))
00196             throw new InvalidArgumentException("Invalid Header $header", 2016);
00197             
00198         switch ($header) {
00199             case self::HEADER_SENDER:
00200             case self::HEADER_FROM:
00201             case self::HEADER_CC:
00202             case self::HEADER_BCC:
00203             case self::HEADER_REPLY_TO:
00204             case self::HEADER_X_CONFIRM_READING_TO:
00205             case self::HEADER_X_UNSUBSCRIBE_EMAIL:
00206                 if (!self::validateEmail($value))
00207                     throw new InvalidArgumentException("Invalid email for $header", 2017);
00208                 break;
00209                 
00210             case self::HEADER_CONTENT_TRANSFERT_ENCODING:
00211                 if (!in_array($value, array('7bits', '8bits', 'binary', 'quoted-printable', 'base64', 'ietf-token', 
00212                                 'x-token')))
00213                     throw new InvalidArgumentException("Invalid value for $header", 2018);
00214                 break;
00215                 
00216             case self::HEADER_DATE:
00217                 if ($time = strtotime($value))
00218                     $value = date('r', $time);
00219                 else
00220                     throw new InvalidArgumentException("Invalid date format for $header", 2019);
00221                 break;
00222                 
00223             case self::HEADER_PRIORITY:
00224                 if (!in_array($value, array('normal', 'urgent', 'non-urgent')))
00225                     throw new InvalidArgumentException("Invalid priority for $header", 2020);
00226                 break;
00227                 
00228             case self::HEADER_X_UNSUBSCRIBE_WEB:
00229                 if (!$value = filter_var($value, FILTER_VALIDATE_URL))
00230                     throw new InvalidArgumentException("Invalid url for $header", 2021);
00231                 break;
00232                 
00233             case self::HEADER_MIME_VERSION:
00234             case self::HEADER_CONTENT_TYPE:
00235             case self::HEADER_CONTENT_DESCRIPTION:
00236             case self::HEADER_REPLY_TO:
00237             case self::HEADER_SENDER:
00238             case self::HEADER_SUBJECT:
00239             case self::HEADER_TO:
00240             case self::HEADER_X_CONFIRM_READING_TO:
00241             case self::HEADER_X_MAILER:
00242             case self::HEADER_X_PRIORITY:
00243                 $value = trim($value);
00244                 if (empty($value))
00245                     throw new InvalidArgumentException("A non empty value is mandatory for $header", 2022);
00246                 break;
00247         }
00248         
00249         $this->_headers[$header] = $value;
00250         return $this;
00251     }
00252     
00264     public function setHeaderSeparator ($glue) {
00265         if (!in_array($glue, array(self::HEADER_SEPARATOR_CRLF, self::HEADER_SEPARATOR_LF)))
00266             throw new InvalidArgumentException("Unrecognized separator", 2023);
00267         $this->_header_separator = $glue;
00268         return $this;
00269     }
00270     
00275     public function getSubject () {
00276         return $this->_subject;
00277     }
00278     
00284     public function setSubject ($subject) {
00285         $this->_subject = strip_tags(trim($subject));
00286     }
00287     
00300     public function addMessagePart ($message, $content_type = null, $charset = "utf-8") {
00301         $part  = $content_type ? "Content-Type: {$content_type}; charset={$charset}": "";
00302         $part .= $this->_header_separator;
00303         $part .= $this->_header_separator;
00304         $part .= $message;
00305         $part .= $this->_header_separator;
00306         $this->_message_parts[$key = uniqid("part-")] = $part;
00307         
00308         return $key;
00309     }
00310     
00324     public function addAttachment ($path, $content_type = null, $filename = null) {
00325         if (!is_file($path))
00326             throw new axMissingFileException($path, 2024);
00327             
00328         if (is_dir($path))
00329             throw new InvalidArgumentException("First parameter is expected to be regular file, directory given", 2025);
00330             
00331         if (!$filename)
00332             $filename = basename($path);
00333             
00334         if (function_exists('finfo_open') && $finfo = finfo_open(FILEINFO_MIME_TYPE)) {
00335             $content_type = finfo_file($finfo, $path);
00336             finfo_close($finfo);
00337         }
00338         else if (function_exists('mime_content_type'))
00339             $content_type = mime_content_type($path);
00340         else if (empty($content_type))
00341             $content_type = "application/octet-stream";
00342             
00343         if (!$content = file_get_contents($path, false))
00344             throw new RuntimeException("Cannot read $path", 2027);
00345             
00346         $part  = "Content-Type: $content_type; name=$filename";
00347 
00348                                 $part .= $this->_header_separator;
00349         $part .= "Content-transfer-encoding: base64";
00350                                 $part .= $this->_header_separator;
00351         $part .= $this->_header_separator;
00352         $part .= chunk_split(base64_encode($content));
00353         $part .= $this->_header_separator;
00354         $this->_message_parts[$key = uniqid("part-")] = $part;
00355         
00356         return $key;
00357     }
00358     
00364     public function removeMessagePart ($key) {
00365         unset($this->_message_parts[$key]);
00366     }
00367     
00374     public function removeAttachement ($key) {
00375         return $this->removeMessagePart($key);
00376     }
00377     
00386     public function send () {
00387         if (empty($this->_message_parts))
00388             throw new RuntimeException("Cannot send mail with empty body");
00389         
00390         $message = (string)$this;
00391         $headers = "";
00392         $results = array();
00393         
00394         if (empty($message))
00395             throw new RuntimeException("Cannot send empty mail");
00396 
00397         foreach ($this->_headers as $name => $value)
00398             $headers .= "{$name}: {$value}{$this->_header_separator}";
00399         $headers .= $this->_header_separator;
00400         
00401         foreach ($this->_to as $destination)
00402             $results[$destination] = mail($destination, $this->_subject, $message, $headers);
00403         
00404         return $results;
00405     }
00406     
00416     public function __toString () {
00417         try {
00418             $c = count($this->_message_parts);
00419             $this->setHeader(self::HEADER_FROM, $this->_from);
00420             
00421             if ($c > 1) {
00422                 $boundary = md5(uniqid(microtime(), true));
00423                 $this->setHeader(self::HEADER_CONTENT_TYPE, "multipart/mixed;boundary=$boundary");
00424                                                                 $str  = "--" . $boundary;
00425                                                                 $str .= $this->_header_separator;
00426                                                                 $str .= implode("--" . $boundary . $this->_header_separator, $this->_message_parts);
00427                                                                 $str .= "--" . $boundary . "--";
00428                 return $str;
00429             }
00430             
00431             return $c == 1 ? array_shift($this->_message_parts) : "";
00432         }
00433         catch (Exception $e) {
00434             return "";
00435         }
00436     }
00437 }
00438 
 All Data Structures Files Functions Variables