5 Modification information for LGPL compliance
7 Author: Eddy Ramirez <eddy@sugarcrm.com>
8 2011-03-03 18:00:00 -0700 (Thu, 03 Mar 2011) - eddy - bug 31778 - added html chars (apostrophe and ampersand) back to email address before sending
10 r58121 - 2010-09-09 11:35:17 -0700 (Thu, 09 Sep 2010) - kjing - Merge: 717e037 0ca4d1c
11 Author: Jenny Gonsalves <jenny@sugarcrm.com>
12 Merge branch 'master' of git+ssh://github.com/sugarcrm/Mango
14 r57158 - 2010-06-27 20:13:23 -0700 (Sun, 27 Jun 2010) - kjing - commit a2a7548e2a06c075c99a17472c9c5672e1ec1926
15 Author: John Mertic <jmertic@sugarcrm.com>
16 Bug 8312 - Set the encoding type to 'base64' by default if we are sending an HTML email
18 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
20 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
22 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
24 r55695 - 2010-03-30 17:46:05 -0700 (Tue, 30 Mar 2010) - mitani - #36026
25 Fixes an issue where CCed recipents would not be listed in the email. Need to upgrade PHP Mailer later on to the latest
27 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
29 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
31 r51443 - 2009-10-12 13:34:36 -0700 (Mon, 12 Oct 2009) - jmertic - Bug 33332 - Made application PHP 5.3 compliant with E_DEPRECATED warnings on by:
32 - Changing all ereg function to either preg or simple string based ones
33 - No more references to magic quotes.
34 - Change all the session_unregister() functions to just unset() the correct session variable instead.
36 r51251 - 2009-09-30 09:30:59 -0700 (Wed, 30 Sep 2009) - roger - svn merge from Tokyo rev: 50982 - 51248.
38 r50983 - 2009-09-21 13:45:37 -0700 (Mon, 21 Sep 2009) - ajay - Merged code from branches/tokyo version 50739 thru 50982
40 r50519 - 2009-08-31 15:20:00 -0700 (Mon, 31 Aug 2009) - sgandhi - 31348
42 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
44 r50023 - 2009-08-07 16:30:05 -0700 (Fri, 07 Aug 2009) - eddy - Bug 32412
45 Split logic in file to allow string to be parsed for template conversion
46 include/phpmailer/class.phpmailer.php
48 r43691 - 2009-01-29 15:25:53 -0800 (Thu, 29 Jan 2009) - faissah - 27521 : Update to phpmailer version 2.3.
50 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
52 r39785 - 2008-09-12 15:49:45 -0700 (Fri, 12 Sep 2008) - faissah - Update to PHPmailer 2.2.1
54 r39146 - 2008-08-26 17:16:04 -0700 (Tue, 26 Aug 2008) - awu - Merging pre_5_1_0 to trunk
56 r23880 - 2007-06-26 15:14:35 -0700 (Tue, 26 Jun 2007) - julian - Fix for bug #13475: security vulnerability in phpmailer
58 r11652 - 2006-02-21 18:24:06 -0800 (Tue, 21 Feb 2006) - chris - Bug 4719: updating PHPMailer classes for security (DDoS)
60 include/phpmailer (everything)
61 include/SugarPHPMailer.php (adding our constructor)
62 modules/Email/Email.php (to use the new constructor)
64 r10887 - 2006-01-05 22:51:15 -0800 (Thu, 05 Jan 2006) - chris - Bug 3979: fixed filename generation issues that caused PDFs to be sent with the wrong encoding type
66 r10886 - 2006-01-05 18:24:55 -0800 (Thu, 05 Jan 2006) - chris - Bug 3979: initial code checkin to get reports scheduling in Scheduler
68 r6053 - 2005-07-06 01:04:42 -0700 (Wed, 06 Jul 2005) - clint - Bug #1400
69 Even if I have "Clint Oram <clint@sugarcrm.com>" in the to field, I only end up seeing "clint@sugarcrm.com" in the received email.
71 r5104 - 2005-05-04 15:33:41 -0700 (Wed, 04 May 2005) - majed - gets rid of HTTP_GET_VARS and what not which has been deprecated
73 r1573 - 2004-10-29 17:23:17 -0700 (Fri, 29 Oct 2004) - julian - Fix: path to phpmailer language file wrong
75 r915 - 2004-10-08 15:31:10 -0700 (Fri, 08 Oct 2004) - julian - E-mail notification feature + new admin console
81 /*~ class.phpmailer.php
82 .---------------------------------------------------------------------------.
83 | Software: PHPMailer - PHP email class |
85 | Contact: via sourceforge.net support pages (also www.codeworxtech.com) |
86 | Info: http://phpmailer.sourceforge.net |
87 | Support: http://sourceforge.net/projects/phpmailer/ |
88 | ------------------------------------------------------------------------- |
89 | Author: Andy Prevost (project admininistrator) |
90 | Author: Brent R. Matzelle (original founder) |
91 | Copyright (c) 2004-2007, Andy Prevost. All Rights Reserved. |
92 | Copyright (c) 2001-2003, Brent R. Matzelle |
93 | ------------------------------------------------------------------------- |
94 | License: Distributed under the Lesser General Public License (LGPL) |
95 | http://www.gnu.org/copyleft/lesser.html |
96 | This program is distributed in the hope that it will be useful - WITHOUT |
97 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
98 | FITNESS FOR A PARTICULAR PURPOSE. |
99 | ------------------------------------------------------------------------- |
100 | We offer a number of paid services (www.codeworxtech.com): |
101 | - Web Hosting on highly optimized fast and secure servers |
102 | - Technology Consulting |
103 | - Oursourcing (highly qualified programmers and graphic designers) |
104 '---------------------------------------------------------------------------'
107 * PHPMailer - PHP email transport class
108 * NOTE: Designed for use with PHP version 5 and up
110 * @author Andy Prevost
111 * @copyright 2004 - 2008 Andy Prevost
116 /////////////////////////////////////////////////
117 // PROPERTIES, PUBLIC
118 /////////////////////////////////////////////////
121 * Email priority (1 = High, 3 = Normal, 5 = low).
124 public $Priority = 3;
127 * Sets the CharSet of the message.
130 public $CharSet = 'utf-8';
133 * Sets the Content-type of the message.
136 public $ContentType = 'text/plain';
139 * Sets the Encoding of the message. Options for this are "8bit",
140 * "7bit", "binary", "base64", and "quoted-printable".
143 public $Encoding = '8bit';
146 * Holds the most recent mailer error message.
149 public $ErrorInfo = '';
152 * Sets the From email address for the message.
155 public $From = 'root@localhost';
158 * Sets the From name of the message.
161 public $FromName = 'Root User';
164 * Sets the Sender email (Return-Path) of the message. If not empty,
165 * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
171 * Sets the Subject of the message.
174 public $Subject = '';
177 * Sets the Body of the message. This can be either an HTML or text body.
178 * If HTML then run IsHTML(true).
184 * Sets the text-only body of the message. This automatically sets the
185 * email to multipart/alternative. This body can be read by mail
186 * clients that do not have HTML email capability such as mutt. Clients
187 * that can read HTML will view the normal Body.
190 public $AltBody = '';
193 * Sets word wrapping on the body of the message to a given number of
197 public $WordWrap = 0;
200 * Method to send mail: ("mail", "sendmail", or "smtp").
203 public $Mailer = 'mail';
206 * Sets the path of the sendmail program.
209 public $Sendmail = '/usr/sbin/sendmail';
213 * Path to PHPMailer plugins. This is now only useful if the SMTP class
214 * is in a different directory than the PHP include path.
217 public $PluginDir = 'include/phpmailer/';
220 * Holds PHPMailer version.
223 public $Version = "2.3";
226 * Sets the email address that a reading confirmation will be sent.
229 public $ConfirmReadingTo = '';
232 * Sets the hostname to use in Message-Id and Received headers
233 * and as default HELO string. If empty, the value returned
234 * by SERVER_NAME is used or 'localhost.localdomain'.
237 public $Hostname = '';
240 * Sets the message ID to be used in the Message-Id header.
241 * If empty, a unique id will be generated.
244 public $MessageID = '';
246 /////////////////////////////////////////////////
247 // PROPERTIES FOR SMTP
248 /////////////////////////////////////////////////
251 * Sets the SMTP hosts. All hosts must be separated by a
252 * semicolon. You can also specify a different port
253 * for each host by using this format: [hostname:port]
254 * (e.g. "smtp1.example.com:25;smtp2.example.com").
255 * Hosts will be tried in order.
258 public $Host = 'localhost';
261 * Sets the default SMTP server port.
267 * Sets the SMTP HELO of the message (Default is $Hostname).
273 * Sets connection prefix.
274 * Options are "", "ssl" or "tls"
277 public $SMTPSecure = "";
280 * Sets SMTP authentication. Utilizes the Username and Password variables.
283 public $SMTPAuth = false;
286 * Sets SMTP username.
289 public $Username = '';
292 * Sets SMTP password.
295 public $Password = '';
298 * Sets the SMTP server timeout in seconds. This function will not
299 * work with the win32 version.
302 public $Timeout = 10;
305 * Sets SMTP class debugging on or off.
308 public $SMTPDebug = false;
311 * Prevents the SMTP connection from being closed after each mail
312 * sending. If this is set to true then to close the connection
313 * requires an explicit call to SmtpClose().
316 public $SMTPKeepAlive = false;
319 * Provides the ability to have the TO field process individual
320 * emails, instead of sending to entire TO addresses
323 public $SingleTo = false;
326 * Provides the ability to change the line ending
331 /////////////////////////////////////////////////
332 // PROPERTIES, PRIVATE
333 /////////////////////////////////////////////////
336 private $to = array();
337 private $cc = array();
338 private $bcc = array();
339 private $ReplyTo = array();
340 public $attachment = array();
341 private $CustomHeader = array();
342 private $message_type = '';
343 public $boundary = array();
344 private $language = array();
345 private $error_count = 0;
346 private $sign_cert_file = "";
347 private $sign_key_file = "";
348 private $sign_key_pass = "";
350 /////////////////////////////////////////////////
351 // METHODS, VARIABLES
352 /////////////////////////////////////////////////
355 * Sets message type to HTML.
359 public function IsHTML($bool) {
361 $this->ContentType = 'text/html';
362 $this->Encoding = 'base64';
364 $this->ContentType = 'text/plain';
365 $this->Encoding = 'quoted-printable';
370 * Sets Mailer to send message using SMTP.
373 public function IsSMTP() {
374 $this->Mailer = 'smtp';
378 * Sets Mailer to send message using PHP mail() function.
381 public function IsMail() {
382 $this->Mailer = 'mail';
386 * Sets Mailer to send message using the $Sendmail program.
389 public function IsSendmail() {
390 $this->Mailer = 'sendmail';
394 * Sets Mailer to send message using the qmail MTA.
397 public function IsQmail() {
398 $this->Sendmail = '/var/qmail/bin/sendmail';
399 $this->Mailer = 'sendmail';
402 /////////////////////////////////////////////////
403 // METHODS, RECIPIENTS
404 /////////////////////////////////////////////////
407 * Adds a "To" address.
408 * @param string $address
409 * @param string $name
412 public function AddAddress($address, $name = '') {
413 $cur = count($this->to);
414 $this->to[$cur][0] = trim($address);
415 $this->to[$cur][1] = $name;
419 * Adds a "Cc" address. Note: this function works
420 * with the SMTP mailer on win32, not with the "mail"
422 * @param string $address
423 * @param string $name
426 public function AddCC($address, $name = '') {
427 $cur = count($this->cc);
428 $this->cc[$cur][0] = trim($address);
429 $this->cc[$cur][1] = $name;
433 * Adds a "Bcc" address. Note: this function works
434 * with the SMTP mailer on win32, not with the "mail"
436 * @param string $address
437 * @param string $name
440 public function AddBCC($address, $name = '') {
441 $cur = count($this->bcc);
442 $this->bcc[$cur][0] = trim($address);
443 $this->bcc[$cur][1] = $name;
447 * Adds a "Reply-to" address.
448 * @param string $address
449 * @param string $name
452 public function AddReplyTo($address, $name = '') {
453 $cur = count($this->ReplyTo);
454 $this->ReplyTo[$cur][0] = trim($address);
455 $this->ReplyTo[$cur][1] = $name;
458 /////////////////////////////////////////////////
459 // METHODS, MAIL SENDING
460 /////////////////////////////////////////////////
463 * Creates message and assigns Mailer. If the message is
464 * not sent successfully then it returns false. Use the ErrorInfo
465 * variable to view description of the error.
468 public function Send() {
473 if((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
474 $this->SetError($this->Lang('provide_address'));
478 //iterate through recipients and add back in html characters (apostrophe ' and ampersand &) to email addresses
479 //this was causing email bounces in names like "O'Reilly@example.com" being sent over as "O'Reilly@example.com"
480 foreach($this->to as $k=>$addr){
481 $this->to[$k][0] = htmlspecialchars_decode($addr[0],ENT_QUOTES);
483 foreach($this->cc as $k=>$addr){
484 $this->cc[$k][0] = htmlspecialchars_decode($addr[0],ENT_QUOTES);
486 foreach($this->bcc as $k=>$addr){
487 $this->bcc[$k][0] = htmlspecialchars_decode($addr[0],ENT_QUOTES);
490 /* Set whether the message is multipart/alternative */
491 if(!empty($this->AltBody)) {
492 $this->ContentType = 'multipart/alternative';
495 $this->error_count = 0; // reset errors
496 $this->SetMessageType();
497 $header .= $this->CreateHeader();
498 $body = $this->CreateBody();
504 /* Choose the mailer */
505 switch($this->Mailer) {
507 $result = $this->SendmailSend($header, $body);
510 $result = $this->SmtpSend($header, $body);
513 $result = $this->MailSend($header, $body);
516 $result = $this->MailSend($header, $body);
518 //$this->SetError($this->Mailer . $this->Lang('mailer_not_supported'));
527 * Sends mail using the $Sendmail program.
531 public function SendmailSend($header, $body) {
532 if ($this->Sender != '') {
533 $sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
535 $sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
538 if(!@$mail = popen($sendmail, 'w')) {
539 $this->SetError($this->Lang('execute') . $this->Sendmail);
543 fputs($mail, $header);
546 $result = pclose($mail);
547 if (version_compare(phpversion(), '4.2.3') == -1) {
548 $result = $result >> 8 & 0xFF;
551 $this->SetError($this->Lang('execute') . $this->Sendmail);
559 * Sends mail using the PHP mail() function.
563 public function MailSend($header, $body) {
566 for($i = 0; $i < count($this->to); $i++) {
567 if($i != 0) { $to .= ', '; }
568 $to .= $this->AddrFormat($this->to[$i]);
571 $toArr = explode(',', $to);
573 $params = sprintf("-oi -f %s", $this->Sender);
574 if ($this->Sender != '' && strlen(ini_get('safe_mode'))< 1) {
575 $old_from = ini_get('sendmail_from');
576 ini_set('sendmail_from', $this->Sender);
577 if ($this->SingleTo === true && count($toArr) > 1) {
578 foreach ($toArr as $key => $val) {
579 $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
582 $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
585 if ($this->SingleTo === true && count($toArr) > 1) {
586 foreach ($toArr as $key => $val) {
587 $rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
590 $rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
594 if (isset($old_from)) {
595 ini_set('sendmail_from', $old_from);
599 $this->SetError($this->Lang('instantiate'));
607 * Sends mail via SMTP using PhpSMTP (Author:
608 * Chris Ryan). Returns bool. Returns false if there is a
609 * bad MAIL FROM, RCPT, or DATA input.
613 public function SmtpSend($header, $body) {
614 include_once($this->PluginDir . 'class.smtp.php');
618 if(!$this->SmtpConnect()) {
622 $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
623 if(!$this->smtp->Mail($smtp_from)) {
624 $error = $this->Lang('from_failed') . $smtp_from;
625 $this->SetError($error);
626 $this->smtp->Reset();
630 /* Attempt to send attach all recipients */
631 for($i = 0; $i < count($this->to); $i++) {
632 if(!$this->smtp->Recipient($this->to[$i][0])) {
633 $bad_rcpt[] = $this->to[$i][0];
636 for($i = 0; $i < count($this->cc); $i++) {
637 if(!$this->smtp->Recipient($this->cc[$i][0])) {
638 $bad_rcpt[] = $this->cc[$i][0];
641 for($i = 0; $i < count($this->bcc); $i++) {
642 if(!$this->smtp->Recipient($this->bcc[$i][0])) {
643 $bad_rcpt[] = $this->bcc[$i][0];
647 if(count($bad_rcpt) > 0) { // Create error message
648 for($i = 0; $i < count($bad_rcpt); $i++) {
652 $error .= $bad_rcpt[$i];
654 $error = $this->Lang('recipients_failed') . $error;
655 $this->SetError($error);
656 $this->smtp->Reset();
660 if(!$this->smtp->Data($header . $body)) {
661 $this->SetError($this->Lang('data_not_accepted'));
662 $this->smtp->Reset();
665 if($this->SMTPKeepAlive == true) {
666 $this->smtp->Reset();
675 * Initiates a connection to an SMTP server. Returns false if the
680 public function SmtpConnect() {
681 if($this->smtp == NULL) {
682 $this->smtp = new SMTP();
685 $this->smtp->do_debug = $this->SMTPDebug;
686 $hosts = explode(';', $this->Host);
688 $connection = ($this->smtp->Connected());
690 /* Retry while there is no connection */
691 while($index < count($hosts) && $connection == false) {
693 if(preg_match('/^(.+):([0-9]+)$/i', $hosts[$index], $hostinfo)) {
694 $host = $hostinfo[1];
695 $port = $hostinfo[2];
697 $host = $hosts[$index];
701 $tls = ($this->SMTPSecure == 'tls');
702 $ssl = ($this->SMTPSecure == 'ssl');
704 if($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) {
706 $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname());
707 $this->smtp->Hello($hello);
710 if(!$this->smtp->StartTLS()) {
711 $this->SetError($this->Lang("tls"));
712 $this->smtp->Reset();
716 //We must resend HELLO after tls negociation
717 $this->smtp->Hello($hello);
721 if($this->SMTPAuth) {
722 if(!$this->smtp->Authenticate($this->Username, $this->Password)) {
723 $this->SetError($this->Lang('authenticate'));
724 $this->smtp->Reset();
732 $this->SetError($this->Lang('connect_host'));
739 * Closes the active SMTP session if one exists.
742 public function SmtpClose() {
743 if($this->smtp != NULL) {
744 if($this->smtp->Connected()) {
746 $this->smtp->Close();
752 * Sets the language for all class error messages. Returns false
753 * if it cannot load the language file. The default language type
755 * @param string $lang_type Type of language (e.g. Portuguese: "br")
756 * @param string $lang_path Path to the language file directory
760 function SetLanguage($lang_type = 'en', $lang_path = 'language/') {
761 $filename = $lang_path.'phpmailer.lang-'.$lang_type.'.php';
762 if (file_exists($filename)) {
765 $PHPMAILER_LANG = array();
766 $PHPMAILER_LANG["provide_address"] = 'You must provide at least one ' .
767 $PHPMAILER_LANG["mailer_not_supported"] = ' mailer is not supported.';
768 $PHPMAILER_LANG["execute"] = 'Could not execute: ';
769 $PHPMAILER_LANG["instantiate"] = 'Could not instantiate mail function.';
770 $PHPMAILER_LANG["authenticate"] = 'SMTP Error: Could not authenticate.';
771 $PHPMAILER_LANG["from_failed"] = 'The following From address failed: ';
772 $PHPMAILER_LANG["recipients_failed"] = 'SMTP Error: The following ' .
773 $PHPMAILER_LANG["data_not_accepted"] = 'SMTP Error: Data not accepted.';
774 $PHPMAILER_LANG["connect_host"] = 'SMTP Error: Could not connect to SMTP host.';
775 $PHPMAILER_LANG["file_access"] = 'Could not access file: ';
776 $PHPMAILER_LANG["file_open"] = 'File Error: Could not open file: ';
777 $PHPMAILER_LANG["encoding"] = 'Unknown encoding: ';
778 $PHPMAILER_LANG["signing"] = 'Signing Error: ';
780 $this->language = $PHPMAILER_LANG;
784 /////////////////////////////////////////////////
785 // METHODS, MESSAGE CREATION
786 /////////////////////////////////////////////////
789 * Creates recipient headers.
793 public function AddrAppend($type, $addr) {
794 $addr_str = $type . ': ';
795 $addr_str .= $this->AddrFormat($addr[0]);
796 if(count($addr) > 1) {
797 for($i = 1; $i < count($addr); $i++) {
798 $addr_str .= ', ' . $this->AddrFormat($addr[$i]);
801 $addr_str .= $this->LE;
807 * Formats an address correctly.
811 public function AddrFormat($addr) {
812 if(empty($addr[1])) {
813 $formatted = $this->SecureHeader($addr[0]);
815 $formatted = $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
822 * Wraps message for use with mailers that do not
823 * automatically perform wrapping and for quoted-printable.
824 * Original written by philippe.
828 public function WrapText($message, $length, $qp_mode = false) {
829 $soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
830 // If utf-8 encoding is used, we will need to make sure we don't
831 // split multibyte characters when we wrap
832 $is_utf8 = (strtolower($this->CharSet) == "utf-8");
834 $message = $this->FixEOL($message);
835 if (substr($message, -1) == $this->LE) {
836 $message = substr($message, 0, -1);
839 $line = explode($this->LE, $message);
841 for ($i=0 ;$i < count($line); $i++) {
842 $line_part = explode(' ', $line[$i]);
844 for ($e = 0; $e<count($line_part); $e++) {
845 $word = $line_part[$e];
846 if ($qp_mode and (strlen($word) > $length)) {
847 $space_left = $length - strlen($buf) - 1;
849 if ($space_left > 20) {
852 $len = $this->UTF8CharBoundary($word, $len);
853 } elseif (substr($word, $len - 1, 1) == "=") {
855 } elseif (substr($word, $len - 2, 1) == "=") {
858 $part = substr($word, 0, $len);
859 $word = substr($word, $len);
861 $message .= $buf . sprintf("=%s", $this->LE);
863 $message .= $buf . $soft_break;
867 while (strlen($word) > 0) {
870 $len = $this->UTF8CharBoundary($word, $len);
871 } elseif (substr($word, $len - 1, 1) == "=") {
873 } elseif (substr($word, $len - 2, 1) == "=") {
876 $part = substr($word, 0, $len);
877 $word = substr($word, $len);
879 if (strlen($word) > 0) {
880 $message .= $part . sprintf("=%s", $this->LE);
887 $buf .= ($e == 0) ? $word : (' ' . $word);
889 if (strlen($buf) > $length and $buf_o != '') {
890 $message .= $buf_o . $soft_break;
895 $message .= $buf . $this->LE;
902 * Finds last character boundary prior to maxLength in a utf-8
903 * quoted (printable) encoded string.
904 * Original written by Colin Brown.
906 * @param string $encodedText utf-8 QP text
907 * @param int $maxLength find last character boundary prior to this length
910 public function UTF8CharBoundary($encodedText, $maxLength) {
911 $foundSplitPos = false;
913 while (!$foundSplitPos) {
914 $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
915 $encodedCharPos = strpos($lastChunk, "=");
916 if ($encodedCharPos !== false) {
917 // Found start of encoded character byte within $lookBack block.
918 // Check the encoded byte value (the 2 chars after the '=')
919 $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
921 if ($dec < 128) { // Single byte character.
922 // If the encoded char was found at pos 0, it will fit
923 // otherwise reduce maxLength to start of the encoded char
924 $maxLength = ($encodedCharPos == 0) ? $maxLength :
925 $maxLength - ($lookBack - $encodedCharPos);
926 $foundSplitPos = true;
927 } elseif ($dec >= 192) { // First byte of a multi byte character
928 // Reduce maxLength to split at start of character
929 $maxLength = $maxLength - ($lookBack - $encodedCharPos);
930 $foundSplitPos = true;
931 } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back
935 // No encoded character found
936 $foundSplitPos = true;
944 * Set the body wrapping.
948 public function SetWordWrap() {
949 if($this->WordWrap < 1) {
953 switch($this->message_type) {
956 case 'alt_attachments':
957 $this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
960 $this->Body = $this->WrapText($this->Body, $this->WordWrap);
966 * Assembles message header.
970 public function CreateHeader() {
973 /* Set the boundaries */
974 $uniq_id = md5(uniqid(time()));
975 $this->boundary[1] = 'b1_' . $uniq_id;
976 $this->boundary[2] = 'b2_' . $uniq_id;
978 $result .= $this->HeaderLine('Date', $this->RFCDate());
979 if($this->Sender == '') {
980 $result .= $this->HeaderLine('Return-Path', trim($this->From));
982 $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
985 /* To be created automatically by mail() */
986 if($this->Mailer != 'mail') {
987 if(count($this->to) > 0) {
988 $result .= $this->AddrAppend('To', $this->to);
989 } elseif (count($this->cc) == 0) {
990 $result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
995 $from[0][0] = trim($this->From);
996 $from[0][1] = $this->FromName;
997 $result .= $this->AddrAppend('From', $from);
999 /* sendmail and mail() extract Cc from the header before sending */
1000 if(count($this->cc) > 0) {
1001 $result .= $this->AddrAppend('Cc', $this->cc);
1004 /* sendmail and mail() extract Bcc from the header before sending */
1005 if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
1006 $result .= $this->AddrAppend('Bcc', $this->bcc);
1009 if(count($this->ReplyTo) > 0) {
1010 $result .= $this->AddrAppend('Reply-to', $this->ReplyTo);
1013 /* mail() sets the subject itself */
1014 if($this->Mailer != 'mail') {
1015 $result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
1018 if($this->MessageID != '') {
1019 $result .= $this->HeaderLine('Message-ID',$this->MessageID);
1021 $result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
1023 $result .= $this->HeaderLine('X-Priority', $this->Priority);
1024 $result .= $this->HeaderLine('X-Mailer', 'PHPMailer (phpmailer.codeworxtech.com) [version ' . $this->Version . ']');
1026 if($this->ConfirmReadingTo != '') {
1027 $result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
1030 // Add custom headers
1031 for($index = 0; $index < count($this->CustomHeader); $index++) {
1032 $result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
1034 if (!$this->sign_key_file) {
1035 $result .= $this->HeaderLine('MIME-Version', '1.0');
1036 $result .= $this->GetMailMIME();
1043 * Returns the message MIME.
1047 public function GetMailMIME() {
1049 switch($this->message_type) {
1051 $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
1052 $result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet);
1056 case 'alt_attachments':
1057 if($this->InlineImageExists()){
1058 $result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE);
1060 $result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
1061 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
1065 $result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
1066 $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
1070 if($this->Mailer != 'mail') {
1071 $result .= $this->LE.$this->LE;
1078 * Assembles the message body. Returns an empty string on failure.
1082 public function CreateBody() {
1085 if ($this->sign_key_file) {
1086 $result .= $this->GetMailMIME();
1089 $this->SetWordWrap();
1091 switch($this->message_type) {
1093 $result .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
1094 $result .= $this->EncodeString($this->AltBody, $this->Encoding);
1095 $result .= $this->LE.$this->LE;
1096 $result .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
1097 $result .= $this->EncodeString($this->Body, $this->Encoding);
1098 $result .= $this->LE.$this->LE;
1099 $result .= $this->EndBoundary($this->boundary[1]);
1102 $result .= $this->EncodeString($this->Body, $this->Encoding);
1105 $result .= $this->GetBoundary($this->boundary[1], '', '', '');
1106 $result .= $this->EncodeString($this->Body, $this->Encoding);
1107 $result .= $this->LE;
1108 $result .= $this->AttachAll();
1110 case 'alt_attachments':
1111 $result .= sprintf("--%s%s", $this->boundary[1], $this->LE);
1112 $result .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE);
1113 $result .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body
1114 $result .= $this->EncodeString($this->AltBody, $this->Encoding);
1115 $result .= $this->LE.$this->LE;
1116 $result .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body
1117 $result .= $this->EncodeString($this->Body, $this->Encoding);
1118 $result .= $this->LE.$this->LE;
1119 $result .= $this->EndBoundary($this->boundary[2]);
1120 $result .= $this->AttachAll();
1124 if($this->IsError()) {
1126 } else if ($this->sign_key_file) {
1127 $file = tempnam("", "mail");
1128 $fp = fopen($file, "w");
1129 fwrite($fp, $result);
1131 $signed = tempnam("", "signed");
1133 if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), null)) {
1134 $fp = fopen($signed, "r");
1137 $result = $result . fread($fp, 1024);
1141 $this->SetError($this->Lang("signing").openssl_error_string());
1153 * Returns the start of a message boundary.
1156 public function GetBoundary($boundary, $charSet, $contentType, $encoding) {
1158 if($charSet == '') {
1159 $charSet = $this->CharSet;
1161 if($contentType == '') {
1162 $contentType = $this->ContentType;
1164 if($encoding == '') {
1165 $encoding = $this->Encoding;
1167 $result .= $this->TextLine('--' . $boundary);
1168 $result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet);
1169 $result .= $this->LE;
1170 $result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
1171 $result .= $this->LE;
1177 * Returns the end of a message boundary.
1180 public function EndBoundary($boundary) {
1181 return $this->LE . '--' . $boundary . '--' . $this->LE;
1185 * Sets the message type.
1189 public function SetMessageType() {
1190 if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) {
1191 $this->message_type = 'plain';
1193 if(count($this->attachment) > 0) {
1194 $this->message_type = 'attachments';
1196 if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) {
1197 $this->message_type = 'alt';
1199 if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) {
1200 $this->message_type = 'alt_attachments';
1205 /* Returns a formatted header line.
1209 public function HeaderLine($name, $value) {
1210 return $name . ': ' . $value . $this->LE;
1214 * Returns a formatted mail line.
1218 public function TextLine($value) {
1219 return $value . $this->LE;
1222 /////////////////////////////////////////////////
1223 // CLASS METHODS, ATTACHMENTS
1224 /////////////////////////////////////////////////
1227 * Adds an attachment from a path on the filesystem.
1228 * Returns false if the file could not be found
1230 * @param string $path Path to the attachment.
1231 * @param string $name Overrides the attachment name.
1232 * @param string $encoding File encoding (see $Encoding).
1233 * @param string $type File extension (MIME) type.
1236 public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
1237 if(!@is_file($path)) {
1238 $this->SetError($this->Lang('file_access') . $path);
1242 $filename = basename($path);
1247 $cur = count($this->attachment);
1248 $this->attachment[$cur][0] = $path;
1249 $this->attachment[$cur][1] = $filename;
1250 $this->attachment[$cur][2] = $name;
1251 $this->attachment[$cur][3] = $encoding;
1252 $this->attachment[$cur][4] = $type;
1253 $this->attachment[$cur][5] = false; // isStringAttachment
1254 $this->attachment[$cur][6] = 'attachment';
1255 $this->attachment[$cur][7] = 0;
1261 * Attaches all fs, string, and binary attachments to the message.
1262 * Returns an empty string on failure.
1266 public function AttachAll() {
1267 /* Return text of body */
1270 /* Add all attachments */
1271 for($i = 0; $i < count($this->attachment); $i++) {
1272 /* Check for string attachment */
1273 $bString = $this->attachment[$i][5];
1275 $string = $this->attachment[$i][0];
1277 $path = $this->attachment[$i][0];
1280 $filename = $this->attachment[$i][1];
1281 $name = $this->attachment[$i][2];
1282 $encoding = $this->attachment[$i][3];
1283 $type = $this->attachment[$i][4];
1284 $disposition = $this->attachment[$i][6];
1285 $cid = $this->attachment[$i][7];
1287 $mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
1288 //$mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $name, $this->LE);
1289 $mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE);
1290 $mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
1292 if($disposition == 'inline') {
1293 $mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
1296 //$mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $name, $this->LE.$this->LE);
1297 $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
1299 /* Encode as string attachment */
1301 $mime[] = $this->EncodeString($string, $encoding);
1302 if($this->IsError()) {
1305 $mime[] = $this->LE.$this->LE;
1307 $mime[] = $this->EncodeFile($path, $encoding);
1308 if($this->IsError()) {
1311 $mime[] = $this->LE.$this->LE;
1315 $mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);
1317 return join('', $mime);
1321 * Encodes attachment in requested format. Returns an
1322 * empty string on failure.
1326 public function EncodeFile ($path, $encoding = 'base64') {
1327 if(!@$fd = fopen($path, 'rb')) {
1328 $this->SetError($this->Lang('file_open') . $path);
1331 if (function_exists('get_magic_quotes')) {
1332 function get_magic_quotes() {
1336 if (version_compare(PHP_VERSION, '5.3.0', '<')) {
1337 $magic_quotes = get_magic_quotes_runtime();
1338 set_magic_quotes_runtime(0);
1340 $file_buffer = file_get_contents($path);
1341 $file_buffer = $this->EncodeString($file_buffer, $encoding);
1343 if (version_compare(PHP_VERSION, '5.3.0', '<')) { set_magic_quotes_runtime($magic_quotes); }
1344 return $file_buffer;
1348 * Encodes string to requested format. Returns an
1349 * empty string on failure.
1353 public function EncodeString ($str, $encoding = 'base64') {
1355 switch(strtolower($encoding)) {
1357 $encoded = chunk_split(base64_encode($str), 76, $this->LE);
1361 $encoded = $this->FixEOL($str);
1362 if (substr($encoded, -(strlen($this->LE))) != $this->LE)
1363 $encoded .= $this->LE;
1368 case 'quoted-printable':
1369 $encoded = $this->EncodeQP($str);
1372 $this->SetError($this->Lang('encoding') . $encoding);
1379 * Encode a header string to best of Q, B, quoted or none.
1383 public function EncodeHeader ($str, $position = 'text') {
1386 switch (strtolower($position)) {
1388 if (!preg_match('/[\200-\377]/', $str)) {
1389 /* Can't use addslashes as we don't know what value has magic_quotes_sybase. */
1390 $encoded = addcslashes($str, "\0..\37\177\\\"");
1391 if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
1394 return ("\"$encoded\"");
1397 $x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
1400 $x = preg_match_all('/[()"]/', $str, $matches);
1404 $x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
1412 $maxlen = 75 - 7 - strlen($this->CharSet);
1413 /* Try to select the encoding which should produce the shortest output */
1414 if (strlen($str)/3 < $x) {
1416 if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {
1417 // Use a custom function which correctly encodes and wraps long
1418 // multibyte strings without breaking lines within a character
1419 $encoded = $this->Base64EncodeWrapMB($str);
1420 // Bug 39171 - Need to change the passed back line-ending to \n, since that's what the
1421 // regex below expects.
1422 $encoded = str_replace($this->LE, "\n", trim($encoded));
1424 $encoded = base64_encode($str);
1425 $maxlen -= $maxlen % 4;
1426 $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
1430 $encoded = $this->EncodeQ($str, $position);
1431 $encoded = $this->WrapText($encoded, $maxlen, true);
1432 $encoded = str_replace('='.$this->LE, "\n", trim($encoded));
1435 $encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
1436 $encoded = trim(str_replace("\n", $this->LE, $encoded));
1442 * Checks if a string contains multibyte characters.
1444 * @param string $str multi-byte text to wrap encode
1447 public function HasMultiBytes($str) {
1448 if (function_exists('mb_strlen')) {
1449 return (strlen($str) > mb_strlen($str, $this->CharSet));
1450 } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
1456 * Correctly encodes and wraps long multibyte strings for mail headers
1457 * without breaking lines within a character.
1458 * Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php
1460 * @param string $str multi-byte text to wrap encode
1463 public function Base64EncodeWrapMB($str) {
1464 $start = "=?".$this->CharSet."?B?";
1468 $mb_length = mb_strlen($str, $this->CharSet);
1469 // Each line must have length <= 75, including $start and $end
1470 $length = 75 - strlen($start) - strlen($end);
1471 // Average multi-byte ratio
1472 $ratio = $mb_length / strlen($str);
1473 // Base64 has a 4:3 ratio
1474 $offset = $avgLength = floor($length * $ratio * .75);
1476 for ($i = 0; $i < $mb_length; $i += $offset) {
1480 $offset = $avgLength - $lookBack;
1481 $chunk = mb_substr($str, $i, $offset, $this->CharSet);
1482 $chunk = base64_encode($chunk);
1485 while (strlen($chunk) > $length);
1487 $encoded .= $chunk . $this->LE;
1490 // Chomp the last linefeed
1491 $encoded = substr($encoded, 0, -strlen($this->LE));
1496 * Encode string to quoted-printable.
1498 * @param string $string the text to encode
1499 * @param integer $line_max Number of chars allowed on a line before wrapping
1502 public function EncodeQP( $input = '', $line_max = 76, $space_conv = false ) {
1503 $hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
1504 $lines = preg_split('/(?:\r\n|\r|\n)/', $input);
1508 while( list(, $line) = each($lines) ) {
1509 $linlen = strlen($line);
1511 for($i = 0; $i < $linlen; $i++) {
1512 $c = substr( $line, $i, 1 );
1514 if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E
1518 if ( $i == ( $linlen - 1 ) ) { // convert space at eol only
1520 } else if ( $space_conv ) {
1523 } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
1524 $h2 = floor($dec/16);
1525 $h1 = floor($dec%16);
1526 $c = $escape.$hex[$h2].$hex[$h1];
1528 if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
1529 $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
1531 // check if newline first character will be point or not
1538 $output .= $newline.$eol;
1544 * Encode string to q encoding.
1548 public function EncodeQ ($str, $position = 'text') {
1549 /* There should not be any EOL in the string */
1550 $encoded = preg_replace("[\r\n]", '', $str);
1552 switch (strtolower($position)) {
1554 $encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
1557 $encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
1560 /* Replace every high ascii, control =, ? and _ characters */
1561 $encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
1562 "'='.sprintf('%02X', ord('\\1'))", $encoded);
1566 /* Replace every spaces to _ (more readable than =20) */
1567 $encoded = str_replace(' ', '_', $encoded);
1573 * Adds a string or binary attachment (non-filesystem) to the list.
1574 * This method can be used to attach ascii or binary data,
1575 * such as a BLOB record from a database.
1576 * @param string $string String attachment data.
1577 * @param string $filename Name of the attachment.
1578 * @param string $encoding File encoding (see $Encoding).
1579 * @param string $type File extension (MIME) type.
1582 public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
1583 /* Append to $attachment array */
1584 $cur = count($this->attachment);
1585 $this->attachment[$cur][0] = $string;
1586 $this->attachment[$cur][1] = $filename;
1587 $this->attachment[$cur][2] = $filename;
1588 $this->attachment[$cur][3] = $encoding;
1589 $this->attachment[$cur][4] = $type;
1590 $this->attachment[$cur][5] = true; // isString
1591 $this->attachment[$cur][6] = 'attachment';
1592 $this->attachment[$cur][7] = 0;
1596 * Adds an embedded attachment. This can include images, sounds, and
1597 * just about any other document. Make sure to set the $type to an
1598 * image type. For JPEG images use "image/jpeg" and for GIF images
1600 * @param string $path Path to the attachment.
1601 * @param string $cid Content ID of the attachment. Use this to identify
1602 * the Id for accessing the image in an HTML form.
1603 * @param string $name Overrides the attachment name.
1604 * @param string $encoding File encoding (see $Encoding).
1605 * @param string $type File extension (MIME) type.
1608 public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
1610 if(!@is_file($path)) {
1611 $this->SetError($this->Lang('file_access') . $path);
1615 $filename = basename($path);
1620 /* Append to $attachment array */
1621 $cur = count($this->attachment);
1622 $this->attachment[$cur][0] = $path;
1623 $this->attachment[$cur][1] = $filename;
1624 $this->attachment[$cur][2] = $name;
1625 $this->attachment[$cur][3] = $encoding;
1626 $this->attachment[$cur][4] = $type;
1627 $this->attachment[$cur][5] = false;
1628 $this->attachment[$cur][6] = 'inline';
1629 $this->attachment[$cur][7] = $cid;
1635 * Returns true if an inline attachment is present.
1639 public function InlineImageExists() {
1641 for($i = 0; $i < count($this->attachment); $i++) {
1642 if($this->attachment[$i][6] == 'inline') {
1651 /////////////////////////////////////////////////
1652 // CLASS METHODS, MESSAGE RESET
1653 /////////////////////////////////////////////////
1656 * Clears all recipients assigned in the TO array. Returns void.
1659 public function ClearAddresses() {
1660 $this->to = array();
1664 * Clears all recipients assigned in the CC array. Returns void.
1667 public function ClearCCs() {
1668 $this->cc = array();
1672 * Clears all recipients assigned in the BCC array. Returns void.
1675 public function ClearBCCs() {
1676 $this->bcc = array();
1680 * Clears all recipients assigned in the ReplyTo array. Returns void.
1683 public function ClearReplyTos() {
1684 $this->ReplyTo = array();
1688 * Clears all recipients assigned in the TO, CC and BCC
1689 * array. Returns void.
1692 public function ClearAllRecipients() {
1693 $this->to = array();
1694 $this->cc = array();
1695 $this->bcc = array();
1699 * Clears all previously set filesystem, string, and binary
1700 * attachments. Returns void.
1703 public function ClearAttachments() {
1704 $this->attachment = array();
1708 * Clears all custom headers. Returns void.
1711 public function ClearCustomHeaders() {
1712 $this->CustomHeader = array();
1715 /////////////////////////////////////////////////
1716 // CLASS METHODS, MISCELLANEOUS
1717 /////////////////////////////////////////////////
1720 * Adds the error message to the error container.
1725 public function SetError($msg) {
1726 $this->error_count++;
1727 $this->ErrorInfo = $msg;
1731 * Returns the proper RFC 822 formatted date.
1735 private static function RFCDate() {
1737 $tzs = ($tz < 0) ? '-' : '+';
1739 $tz = (int)($tz/3600)*100 + ($tz%3600)/60;
1740 $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);
1746 * Returns the server hostname or 'localhost.localdomain' if unknown.
1750 public function ServerHostname() {
1751 if (!empty($this->Hostname)) {
1752 $result = $this->Hostname;
1753 } elseif (isset($_SERVER['SERVER_NAME'])) {
1754 $result = $_SERVER['SERVER_NAME'];
1756 $result = "localhost.localdomain";
1763 * Returns a message in the appropriate language.
1767 public function Lang($key) {
1768 if(count($this->language) < 1) {
1769 $this->SetLanguage('en'); // set the default language
1772 if(isset($this->language[$key])) {
1773 return $this->language[$key];
1775 return 'Language string failed to load: ' . $key;
1780 * Returns true if an error occurred.
1784 public function IsError() {
1785 return ($this->error_count > 0);
1789 * Changes every end of line from CR or LF to CRLF.
1793 private function FixEOL($str) {
1794 $str = str_replace("\r\n", "\n", $str);
1795 $str = str_replace("\r", "\n", $str);
1796 $str = str_replace("\n", $this->LE, $str);
1801 * Adds a custom header.
1805 public function AddCustomHeader($custom_header) {
1806 $this->CustomHeader[] = explode(':', $custom_header, 2);
1810 * Evaluates the message and returns modifications for inline images and backgrounds
1814 public function MsgHTML($message,$basedir='') {
1815 preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images);
1816 if(isset($images[2])) {
1817 foreach($images[2] as $i => $url) {
1818 // do not change urls for absolute images (thanks to corvuscorax)
1819 if (!preg_match('/^[A-z][A-z]*:\/\//',$url)) {
1820 $filename = basename($url);
1821 $directory = dirname($url);
1822 ($directory == '.')?$directory='':'';
1823 $cid = 'cid:' . md5($filename);
1824 $fileParts = preg_split("\.", $filename);
1825 $ext = $fileParts[1];
1826 $mimeType = $this->_mime_types($ext);
1827 if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; }
1828 if ( strlen($directory) > 1 && substr($directory,-1) != '/') { $directory .= '/'; }
1829 if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) {
1830 $message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message);
1835 $this->IsHTML(true);
1836 $this->Body = $message;
1837 $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message)));
1838 if ( !empty($textMsg) && empty($this->AltBody) ) {
1839 $this->AltBody = html_entity_decode($textMsg);
1841 if ( empty($this->AltBody) ) {
1842 $this->AltBody = 'To view this email message, open the email in with HTML compatibility!' . "\n\n";
1847 * Gets the mime type of the embedded or inline image
1849 * @return mime type of ext
1851 public function _mime_types($ext = '') {
1853 'hqx' => 'application/mac-binhex40',
1854 'cpt' => 'application/mac-compactpro',
1855 'doc' => 'application/msword',
1856 'bin' => 'application/macbinary',
1857 'dms' => 'application/octet-stream',
1858 'lha' => 'application/octet-stream',
1859 'lzh' => 'application/octet-stream',
1860 'exe' => 'application/octet-stream',
1861 'class' => 'application/octet-stream',
1862 'psd' => 'application/octet-stream',
1863 'so' => 'application/octet-stream',
1864 'sea' => 'application/octet-stream',
1865 'dll' => 'application/octet-stream',
1866 'oda' => 'application/oda',
1867 'pdf' => 'application/pdf',
1868 'ai' => 'application/postscript',
1869 'eps' => 'application/postscript',
1870 'ps' => 'application/postscript',
1871 'smi' => 'application/smil',
1872 'smil' => 'application/smil',
1873 'mif' => 'application/vnd.mif',
1874 'xls' => 'application/vnd.ms-excel',
1875 'ppt' => 'application/vnd.ms-powerpoint',
1876 'wbxml' => 'application/vnd.wap.wbxml',
1877 'wmlc' => 'application/vnd.wap.wmlc',
1878 'dcr' => 'application/x-director',
1879 'dir' => 'application/x-director',
1880 'dxr' => 'application/x-director',
1881 'dvi' => 'application/x-dvi',
1882 'gtar' => 'application/x-gtar',
1883 'php' => 'application/x-httpd-php',
1884 'php4' => 'application/x-httpd-php',
1885 'php3' => 'application/x-httpd-php',
1886 'phtml' => 'application/x-httpd-php',
1887 'phps' => 'application/x-httpd-php-source',
1888 'js' => 'application/x-javascript',
1889 'swf' => 'application/x-shockwave-flash',
1890 'sit' => 'application/x-stuffit',
1891 'tar' => 'application/x-tar',
1892 'tgz' => 'application/x-tar',
1893 'xhtml' => 'application/xhtml+xml',
1894 'xht' => 'application/xhtml+xml',
1895 'zip' => 'application/zip',
1896 'mid' => 'audio/midi',
1897 'midi' => 'audio/midi',
1898 'mpga' => 'audio/mpeg',
1899 'mp2' => 'audio/mpeg',
1900 'mp3' => 'audio/mpeg',
1901 'aif' => 'audio/x-aiff',
1902 'aiff' => 'audio/x-aiff',
1903 'aifc' => 'audio/x-aiff',
1904 'ram' => 'audio/x-pn-realaudio',
1905 'rm' => 'audio/x-pn-realaudio',
1906 'rpm' => 'audio/x-pn-realaudio-plugin',
1907 'ra' => 'audio/x-realaudio',
1908 'rv' => 'video/vnd.rn-realvideo',
1909 'wav' => 'audio/x-wav',
1910 'bmp' => 'image/bmp',
1911 'gif' => 'image/gif',
1912 'jpeg' => 'image/jpeg',
1913 'jpg' => 'image/jpeg',
1914 'jpe' => 'image/jpeg',
1915 'png' => 'image/png',
1916 'tiff' => 'image/tiff',
1917 'tif' => 'image/tiff',
1918 'css' => 'text/css',
1919 'html' => 'text/html',
1920 'htm' => 'text/html',
1921 'shtml' => 'text/html',
1922 'txt' => 'text/plain',
1923 'text' => 'text/plain',
1924 'log' => 'text/plain',
1925 'rtx' => 'text/richtext',
1926 'rtf' => 'text/rtf',
1927 'xml' => 'text/xml',
1928 'xsl' => 'text/xml',
1929 'mpeg' => 'video/mpeg',
1930 'mpg' => 'video/mpeg',
1931 'mpe' => 'video/mpeg',
1932 'qt' => 'video/quicktime',
1933 'mov' => 'video/quicktime',
1934 'avi' => 'video/x-msvideo',
1935 'movie' => 'video/x-sgi-movie',
1936 'doc' => 'application/msword',
1937 'word' => 'application/msword',
1938 'xl' => 'application/excel',
1939 'eml' => 'message/rfc822'
1941 return ( ! isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
1945 * Set (or reset) Class Objects (variables)
1948 * $page->set('X-Priority', '3');
1951 * @param string $name Parameter Name
1952 * @param mixed $value Parameter Value
1953 * NOTE: will not work with arrays, there are no arrays to set/reset
1955 public function set ( $name, $value = '' ) {
1956 if ( isset($this->$name) ) {
1957 $this->$name = $value;
1959 $this->SetError('Cannot set or reset variable ' . $name);
1965 * Read a file from a supplied filename and return it.
1968 * @param string $filename Parameter File Name
1970 public function getFile($filename) {
1972 if ($fp = fopen($filename, 'rb')) {
1973 while (!feof($fp)) {
1974 $return .= fread($fp, 1024);
1984 * Strips newlines to prevent header injection.
1986 * @param string $str String
1989 public function SecureHeader($str) {
1991 $str = str_replace("\r", "", $str);
1992 $str = str_replace("\n", "", $str);
1997 * Set the private key file and password to sign the message.
2000 * @param string $key_filename Parameter File Name
2001 * @param string $key_pass Password for private key
2003 public function Sign($cert_filename, $key_filename, $key_pass) {
2004 $this->sign_cert_file = $cert_filename;
2005 $this->sign_key_file = $key_filename;
2006 $this->sign_key_pass = $key_pass;