diff --git a/libraries/PHPMailer/PHPMailer.php b/libraries/PHPMailer/PHPMailer.php
index f76ecac..5df9730 100644
--- a/libraries/PHPMailer/PHPMailer.php
+++ b/libraries/PHPMailer/PHPMailer.php
@@ -2,12 +2,13 @@
/*~ class.phpmailer.php
.---------------------------------------------------------------------------.
| Software: PHPMailer - PHP email class |
-| Version: 5.2.4 |
-| Site: https://code.google.com/a/apache-extras.org/p/phpmailer/ |
+| Version: 5.2.6 |
+| Site: https://github.com/PHPMailer/PHPMailer/ |
| ------------------------------------------------------------------------- |
-| Admin: Jim Jagielski (project admininistrator) |
+| Admins: Marcus Bointon |
+| Admins: Jim Jagielski |
| Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
-| : Marcus Bointon (coolbru) coolbru@users.sourceforge.net |
+| : Marcus Bointon (coolbru) phpmailer@synchromedia.co.uk |
| : Jim Jagielski (jimjag) jimjag@gmail.com |
| Founder: Brent R. Matzelle (original founder) |
| Copyright (c) 2010-2012, Jim Jagielski. All Rights Reserved. |
@@ -34,14 +35,16 @@
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
-if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n");
+if (version_compare(PHP_VERSION, '5.0.0', '<') ) {
+ exit("Sorry, PHPMailer will only run on PHP version 5 or greater!\n");
+}
/**
* PHP email creation and transport class
* @package PHPMailer
*/
-class PHPMailer
-{
+class PHPMailer {
+
/////////////////////////////////////////////////
// PROPERTIES, PUBLIC
/////////////////////////////////////////////////
@@ -90,8 +93,8 @@ class PHPMailer
public $FromName = 'Root User';
/**
- * Sets the Sender email (Return-Path) of the message. If not empty,
- * will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
+ * Sets the Sender email (Return-Path) of the message.
+ * If not empty, will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
* @var string
*/
public $Sender = '';
@@ -110,21 +113,31 @@ class PHPMailer
public $Subject = '';
/**
- * Sets the Body of the message. This can be either an HTML or text body.
- * If HTML then run IsHTML(true).
+ * An HTML or plain text message body.
+ * If HTML then call IsHTML(true).
* @var string
*/
public $Body = '';
/**
- * Sets the text-only body of the message. This automatically sets the
- * email to multipart/alternative. This body can be read by mail
- * clients that do not have HTML email capability such as mutt. Clients
- * that can read HTML will view the normal Body.
+ * The plain-text message body.
+ * This body can be read by mail clients that do not have HTML email
+ * capability such as mutt & Eudora.
+ * Clients that can read HTML will view the normal Body.
* @var string
*/
public $AltBody = '';
+ /**
+ * An iCal message part body
+ * Only supported in simple alt or alt_inline message types
+ * To generate iCal events, use the bundled extras/EasyPeasyICS.php class or iCalcreator
+ * @link http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/
+ * @link http://kigkonsult.se/iCalcreator/
+ * @var string
+ */
+ public $Ical = '';
+
/**
* Stores the complete compiled MIME message body.
* @var string
@@ -143,7 +156,7 @@ class PHPMailer
* Stores the extra header list which CreateHeader() doesn't fold in
* @var string
* @access protected
- */
+ */
protected $mailHeader = '';
/**
@@ -260,7 +273,7 @@ class PHPMailer
public $Password = '';
/**
- * Sets SMTP auth type. Options are LOGIN | PLAIN | NTLM (default LOGIN)
+ * Sets SMTP auth type. Options are LOGIN | PLAIN | NTLM | CRAM-MD5 (default LOGIN)
* @var string
*/
public $AuthType = '';
@@ -312,13 +325,26 @@ class PHPMailer
*/
public $SingleTo = false;
- /**
+ /**
+ * Should we generate VERP addresses when sending via SMTP?
+ * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path
+ * @var bool
+ */
+ public $do_verp = false;
+
+ /**
* If SingleTo is true, this provides the array to hold the email addresses
* @var bool
*/
public $SingleToArray = array();
- /**
+ /**
+ * Should we allow sending messages with empty body?
+ * @var bool
+ */
+ public $AllowEmpty = false;
+
+ /**
* Provides the ability to change the generic line ending
* NOTE: The default remains '\n'. We force CRLF where we KNOW
* it must be used via self::CRLF
@@ -390,7 +416,7 @@ class PHPMailer
* Sets the PHPMailer Version number
* @var string
*/
- public $Version = '5.2.4';
+ public $Version = '5.2.6';
/**
* What to use in the X-Mailer header
@@ -406,82 +432,82 @@ class PHPMailer
* @var SMTP An instance of the SMTP sender class
* @access protected
*/
- protected $smtp = null;
+ protected $smtp = null;
/**
* @var array An array of 'to' addresses
* @access protected
*/
- protected $to = array();
+ protected $to = array();
/**
* @var array An array of 'cc' addresses
* @access protected
*/
- protected $cc = array();
+ protected $cc = array();
/**
* @var array An array of 'bcc' addresses
* @access protected
*/
- protected $bcc = array();
+ protected $bcc = array();
/**
* @var array An array of reply-to name and address
* @access protected
*/
- protected $ReplyTo = array();
+ protected $ReplyTo = array();
/**
* @var array An array of all kinds of addresses: to, cc, bcc, replyto
* @access protected
*/
- protected $all_recipients = array();
+ protected $all_recipients = array();
/**
* @var array An array of attachments
* @access protected
*/
- protected $attachment = array();
+ protected $attachment = array();
/**
* @var array An array of custom headers
* @access protected
*/
- protected $CustomHeader = array();
+ protected $CustomHeader = array();
/**
* @var string The message's MIME type
* @access protected
*/
- protected $message_type = '';
+ protected $message_type = '';
/**
* @var array An array of MIME boundary strings
* @access protected
*/
- protected $boundary = array();
+ protected $boundary = array();
/**
* @var array An array of available languages
* @access protected
*/
- protected $language = array();
+ protected $language = array();
/**
* @var integer The number of errors encountered
* @access protected
*/
- protected $error_count = 0;
+ protected $error_count = 0;
/**
* @var string The filename of a DKIM certificate file
* @access protected
*/
- protected $sign_cert_file = '';
+ protected $sign_cert_file = '';
/**
* @var string The filename of a DKIM key file
* @access protected
*/
- protected $sign_key_file = '';
+ protected $sign_key_file = '';
/**
* @var string The password of a DKIM key
* @access protected
*/
- protected $sign_key_pass = '';
+ protected $sign_key_pass = '';
/**
* @var boolean Whether to throw exceptions for errors
* @access protected
*/
- protected $exceptions = false;
+ protected $exceptions = false;
/////////////////////////////////////////////////
// CONSTANTS
@@ -509,14 +535,12 @@ class PHPMailer
* @access private
* @return bool
*/
- private function mail_passthru($to, $subject, $body, $header, $params)
- {
+ private function mail_passthru($to, $subject, $body, $header, $params) {
if ( ini_get('safe_mode') || !($this->UseSendmailOptions) ) {
$rt = @mail($to, $this->EncodeHeader($this->SecureHeader($subject)), $body, $header);
} else {
$rt = @mail($to, $this->EncodeHeader($this->SecureHeader($subject)), $body, $header, $params);
}
-
return $rt;
}
@@ -524,11 +548,18 @@ class PHPMailer
* Outputs debugging info via user-defined method
* @param string $str
*/
- private function edebug($str)
- {
- if ($this->Debugoutput == "error_log") {
+ protected function edebug($str) {
+ switch ($this->Debugoutput) {
+ case 'error_log':
error_log($str);
- } else {
+ break;
+ case 'html':
+ //Cleans up output a bit for a better looking display that's HTML-safe
+ echo htmlentities(preg_replace('/[\r\n]+/', '', $str), ENT_QUOTES, $this->CharSet)."
\n";
+ break;
+ case 'echo':
+ default:
+ //Just echoes exactly what was received
echo $str;
}
}
@@ -537,18 +568,25 @@ class PHPMailer
* Constructor
* @param boolean $exceptions Should we throw external exceptions?
*/
- public function __construct($exceptions = false)
- {
+ public function __construct($exceptions = false) {
$this->exceptions = ($exceptions == true);
}
+ /**
+ * Destructor
+ */
+ public function __destruct() {
+ if ($this->Mailer == 'smtp') { //Close any open SMTP connection nicely
+ $this->SmtpClose();
+ }
+ }
+
/**
* Sets message type to HTML.
* @param bool $ishtml
* @return void
*/
- public function IsHTML($ishtml = true)
- {
+ public function IsHTML($ishtml = true) {
if ($ishtml) {
$this->ContentType = 'text/html';
} else {
@@ -560,8 +598,7 @@ class PHPMailer
* Sets Mailer to send message using SMTP.
* @return void
*/
- public function IsSMTP()
- {
+ public function IsSMTP() {
$this->Mailer = 'smtp';
}
@@ -569,8 +606,7 @@ class PHPMailer
* Sets Mailer to send message using PHP mail() function.
* @return void
*/
- public function IsMail()
- {
+ public function IsMail() {
$this->Mailer = 'mail';
}
@@ -578,8 +614,7 @@ class PHPMailer
* Sets Mailer to send message using the $Sendmail program.
* @return void
*/
- public function IsSendmail()
- {
+ public function IsSendmail() {
if (!stristr(ini_get('sendmail_path'), 'sendmail')) {
$this->Sendmail = '/var/qmail/bin/sendmail';
}
@@ -590,8 +625,7 @@ class PHPMailer
* Sets Mailer to send message using the qmail MTA.
* @return void
*/
- public function IsQmail()
- {
+ public function IsQmail() {
if (stristr(ini_get('sendmail_path'), 'qmail')) {
$this->Sendmail = '/var/qmail/bin/sendmail';
}
@@ -608,8 +642,7 @@ class PHPMailer
* @param string $name
* @return boolean true on success, false if address already used
*/
- public function AddAddress($address, $name = '')
- {
+ public function AddAddress($address, $name = '') {
return $this->AddAnAddress('to', $address, $name);
}
@@ -620,8 +653,7 @@ class PHPMailer
* @param string $name
* @return boolean true on success, false if address already used
*/
- public function AddCC($address, $name = '')
- {
+ public function AddCC($address, $name = '') {
return $this->AddAnAddress('cc', $address, $name);
}
@@ -632,8 +664,7 @@ class PHPMailer
* @param string $name
* @return boolean true on success, false if address already used
*/
- public function AddBCC($address, $name = '')
- {
+ public function AddBCC($address, $name = '') {
return $this->AddAnAddress('bcc', $address, $name);
}
@@ -643,8 +674,7 @@ class PHPMailer
* @param string $name
* @return boolean
*/
- public function AddReplyTo($address, $name = '')
- {
+ public function AddReplyTo($address, $name = '') {
return $this->AddAnAddress('Reply-To', $address, $name);
}
@@ -658,8 +688,7 @@ class PHPMailer
* @return boolean true on success, false if address already used or invalid in some way
* @access protected
*/
- protected function AddAnAddress($kind, $address, $name = '')
- {
+ protected function AddAnAddress($kind, $address, $name = '') {
if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) {
$this->SetError($this->Lang('Invalid recipient array').': '.$kind);
if ($this->exceptions) {
@@ -668,7 +697,6 @@ class PHPMailer
if ($this->SMTPDebug) {
$this->edebug($this->Lang('Invalid recipient array').': '.$kind);
}
-
return false;
}
$address = trim($address);
@@ -681,37 +709,32 @@ class PHPMailer
if ($this->SMTPDebug) {
$this->edebug($this->Lang('invalid_address').': '.$address);
}
-
return false;
}
if ($kind != 'Reply-To') {
if (!isset($this->all_recipients[strtolower($address)])) {
array_push($this->$kind, array($address, $name));
$this->all_recipients[strtolower($address)] = true;
-
return true;
}
} else {
if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
$this->ReplyTo[strtolower($address)] = array($address, $name);
-
return true;
}
}
-
return false;
}
-/**
- * Set the From and FromName properties
- * @param string $address
- * @param string $name
- * @param int $auto Also set Reply-To and Sender
+ /**
+ * Set the From and FromName properties
+ * @param string $address
+ * @param string $name
+ * @param boolean $auto Whether to also set the Sender address, defaults to true
* @throws phpmailerException
- * @return boolean
- */
- public function SetFrom($address, $name = '', $auto = 1)
- {
+ * @return boolean
+ */
+ public function SetFrom($address, $name = '', $auto = true) {
$address = trim($address);
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
if (!$this->ValidateAddress($address)) {
@@ -722,20 +745,15 @@ class PHPMailer
if ($this->SMTPDebug) {
$this->edebug($this->Lang('invalid_address').': '.$address);
}
-
return false;
}
$this->From = $address;
$this->FromName = $name;
if ($auto) {
- if (empty($this->ReplyTo)) {
- $this->AddAnAddress('Reply-To', $address, $name);
- }
if (empty($this->Sender)) {
$this->Sender = $address;
}
}
-
return true;
}
@@ -745,8 +763,6 @@ class PHPMailer
* Conforms to RFC5322: Uses *correct* regex on which FILTER_VALIDATE_EMAIL is
* based; So why not use FILTER_VALIDATE_EMAIL? Because it was broken to
* not allow a@b type valid addresses :(
- * Some Versions of PHP break on the regex though, likely due to PCRE, so use
- * the older validation method for those users. (http://php.net/manual/en/pcre.installation.php)
* @link http://squiloople.com/2009/12/20/email-address-validation/
* @copyright regex Copyright Michael Rushton 2009-10 | http://squiloople.com/ | Feel free to use and redistribute this code. But please keep this copyright notice.
* @param string $address The email address to check
@@ -754,19 +770,19 @@ class PHPMailer
* @static
* @access public
*/
- public static function ValidateAddress($address)
- {
- if ((defined('PCRE_VERSION')) && (version_compare(PCRE_VERSION, '8.0') >= 0)) {
- return preg_match('/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)((?>(?>(?>((?>(?>(?>\x0D\x0A)?[ ])+|(?>[ ]*\x0D\x0A)?[ ]+)?)(\((?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}|(?!(?:.*[a-f0-9][:\]]){7,})((?6)(?>:(?6)){0,5})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:|(?!(?:.*[a-f0-9]:){5,})(?8)?::(?>((?6)(?>:(?6)){0,3}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD', $address);
- } elseif (function_exists('filter_var')) { //Introduced in PHP 5.2
- if (filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) {
- return false;
- } else {
- return true;
- }
- } else {
- return preg_match('/^(?:[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+\.)*[\w\!\#\$\%\&\'\*\+\-\/\=\?\^\`\{\|\}\~]+@(?:(?:(?:[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!\.)){0,61}[a-zA-Z0-9_-]?\.)+[a-zA-Z0-9_](?:[a-zA-Z0-9_\-](?!$)){0,61}[a-zA-Z0-9_]?)|(?:\[(?:(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\.){3}(?:[01]?\d{1,2}|2[0-4]\d|25[0-5])\]))$/', $address);
- }
+ public static function ValidateAddress($address) {
+ if (defined('PCRE_VERSION')) { //Check this instead of extension_loaded so it works when that function is disabled
+ if (version_compare(PCRE_VERSION, '8.0') >= 0) {
+ return (boolean)preg_match('/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD', $address);
+ } else {
+ //Fall back to an older regex that doesn't need a recent PCRE
+ return (boolean)preg_match('/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD', $address);
+ }
+ } else {
+ //No PCRE! Do something _very_ approximate!
+ //Check the address is 3 chars or longer and contains an @ that's not the first or last char
+ return (strlen($address) >= 3 and strpos($address, '@') >= 1 and strpos($address, '@') != strlen($address) - 1);
+ }
}
/////////////////////////////////////////////////
@@ -780,11 +796,9 @@ class PHPMailer
* @throws phpmailerException
* @return bool
*/
- public function Send()
- {
+ public function Send() {
try {
if(!$this->PreSend()) return false;
-
return $this->PostSend();
} catch (phpmailerException $e) {
$this->mailHeader = '';
@@ -792,7 +806,6 @@ class PHPMailer
if ($this->exceptions) {
throw $e;
}
-
return false;
}
}
@@ -802,8 +815,7 @@ class PHPMailer
* @throws phpmailerException
* @return bool
*/
- public function PreSend()
- {
+ public function PreSend() {
try {
$this->mailHeader = "";
if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
@@ -811,14 +823,14 @@ class PHPMailer
}
// Set whether the message is multipart/alternative
- if (!empty($this->AltBody)) {
+ if(!empty($this->AltBody)) {
$this->ContentType = 'multipart/alternative';
}
$this->error_count = 0; // reset errors
$this->SetMessageType();
- //Refuse to send an empty message
- if (empty($this->Body)) {
+ //Refuse to send an empty message unless we are specifically allowing it
+ if (!$this->AllowEmpty and empty($this->Body)) {
throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL);
}
@@ -834,14 +846,11 @@ class PHPMailer
$this->mailHeader .= $this->HeaderLine("To", "undisclosed-recipients:;");
}
$this->mailHeader .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader(trim($this->Subject))));
- // if (count($this->cc) > 0) {
- // $this->mailHeader .= $this->AddrAppend("Cc", $this->cc);
- // }
}
// digitally sign with DKIM if enabled
if (!empty($this->DKIM_domain) && !empty($this->DKIM_private) && !empty($this->DKIM_selector) && !empty($this->DKIM_domain) && file_exists($this->DKIM_private)) {
- $header_dkim = $this->DKIM_Add($this->MIMEHeader, $this->EncodeHeader($this->SecureHeader($this->Subject)), $this->MIMEBody);
+ $header_dkim = $this->DKIM_Add($this->MIMEHeader . $this->mailHeader, $this->EncodeHeader($this->SecureHeader($this->Subject)), $this->MIMEBody);
$this->MIMEHeader = str_replace("\r\n", "\n", $header_dkim) . $this->MIMEHeader;
}
@@ -852,7 +861,6 @@ class PHPMailer
if ($this->exceptions) {
throw $e;
}
-
return false;
}
}
@@ -863,11 +871,10 @@ class PHPMailer
* @throws phpmailerException
* @return bool
*/
- public function PostSend()
- {
+ public function PostSend() {
try {
// Choose the mailer and send through it
- switch ($this->Mailer) {
+ switch($this->Mailer) {
case 'sendmail':
return $this->SendmailSend($this->MIMEHeader, $this->MIMEBody);
case 'smtp':
@@ -886,7 +893,6 @@ class PHPMailer
$this->edebug($e->getMessage()."\n");
}
}
-
return false;
}
@@ -898,8 +904,7 @@ class PHPMailer
* @access protected
* @return bool
*/
- protected function SendmailSend($header, $body)
- {
+ protected function SendmailSend($header, $body) {
if ($this->Sender != '') {
$sendmail = sprintf("%s -oi -f%s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
} else {
@@ -907,7 +912,7 @@ class PHPMailer
}
if ($this->SingleTo === true) {
foreach ($this->SingleToArray as $val) {
- if (!@$mail = popen($sendmail, 'w')) {
+ if(!@$mail = popen($sendmail, 'w')) {
throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
}
fputs($mail, "To: " . $val . "\n");
@@ -917,12 +922,12 @@ class PHPMailer
// implement call back function if it exists
$isSent = ($result == 0) ? 1 : 0;
$this->doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
- if ($result != 0) {
+ if($result != 0) {
throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
}
}
} else {
- if (!@$mail = popen($sendmail, 'w')) {
+ if(!@$mail = popen($sendmail, 'w')) {
throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
}
fputs($mail, $header);
@@ -931,11 +936,10 @@ class PHPMailer
// implement call back function if it exists
$isSent = ($result == 0) ? 1 : 0;
$this->doCallback($isSent, $this->to, $this->cc, $this->bcc, $this->Subject, $body);
- if ($result != 0) {
+ if($result != 0) {
throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
}
}
-
return true;
}
@@ -943,22 +947,21 @@ class PHPMailer
* Sends mail using the PHP mail() function.
* @param string $header The message headers
* @param string $body The message body
- * @throws phpmailerException
+ * @throws phpmailerException
* @access protected
* @return bool
*/
- protected function MailSend($header, $body)
- {
+ protected function MailSend($header, $body) {
$toArr = array();
- foreach ($this->to as $t) {
+ foreach($this->to as $t) {
$toArr[] = $this->AddrFormat($t);
}
$to = implode(', ', $toArr);
if (empty($this->Sender)) {
- $params = "-oi ";
+ $params = " ";
} else {
- $params = sprintf("-oi -f%s", $this->Sender);
+ $params = sprintf("-f%s", $this->Sender);
}
if ($this->Sender != '' and !ini_get('safe_mode')) {
$old_from = ini_get('sendmail_from');
@@ -981,10 +984,9 @@ class PHPMailer
if (isset($old_from)) {
ini_set('sendmail_from', $old_from);
}
- if (!$rt) {
+ if(!$rt) {
throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL);
}
-
return true;
}
@@ -998,22 +1000,21 @@ class PHPMailer
* @access protected
* @return bool
*/
- protected function SmtpSend($header, $body)
- {
+ protected function SmtpSend($header, $body) {
require_once $this->PluginDir . 'class.smtp.php';
$bad_rcpt = array();
- if (!$this->SmtpConnect()) {
+ if(!$this->SmtpConnect()) {
throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL);
}
$smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
- if (!$this->smtp->Mail($smtp_from)) {
- $this->SetError($this->Lang('from_failed') . $smtp_from . " : " . implode(",",$this->smtp->getError())) ;
+ if(!$this->smtp->Mail($smtp_from)) {
+ $this->SetError($this->Lang('from_failed') . $smtp_from . ' : ' .implode(',', $this->smtp->getError()));
throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL);
}
// Attempt to send attach all recipients
- foreach ($this->to as $to) {
+ foreach($this->to as $to) {
if (!$this->smtp->Recipient($to[0])) {
$bad_rcpt[] = $to[0];
// implement call back function if it exists
@@ -1025,7 +1026,7 @@ class PHPMailer
$this->doCallback($isSent, $to[0], '', '', $this->Subject, $body);
}
}
- foreach ($this->cc as $cc) {
+ foreach($this->cc as $cc) {
if (!$this->smtp->Recipient($cc[0])) {
$bad_rcpt[] = $cc[0];
// implement call back function if it exists
@@ -1037,7 +1038,7 @@ class PHPMailer
$this->doCallback($isSent, '', $cc[0], '', $this->Subject, $body);
}
}
- foreach ($this->bcc as $bcc) {
+ foreach($this->bcc as $bcc) {
if (!$this->smtp->Recipient($bcc[0])) {
$bad_rcpt[] = $bcc[0];
// implement call back function if it exists
@@ -1055,99 +1056,100 @@ class PHPMailer
$badaddresses = implode(', ', $bad_rcpt);
throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses);
}
- if (!$this->smtp->Data($header . $body)) {
+ if(!$this->smtp->Data($header . $body)) {
throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL);
}
- if ($this->SMTPKeepAlive == true) {
+ if($this->SMTPKeepAlive == true) {
$this->smtp->Reset();
} else {
$this->smtp->Quit();
$this->smtp->Close();
}
-
return true;
}
/**
* Initiates a connection to an SMTP server.
* Returns false if the operation failed.
+ * @param array $options An array of options compatible with stream_context_create()
* @uses SMTP
* @access public
* @throws phpmailerException
* @return bool
*/
- public function SmtpConnect()
- {
- if (is_null($this->smtp)) {
+ public function SmtpConnect($options = array()) {
+ if(is_null($this->smtp)) {
$this->smtp = new SMTP;
}
+ //Already connected?
+ if ($this->smtp->Connected()) {
+ return true;
+ }
+
$this->smtp->Timeout = $this->Timeout;
$this->smtp->do_debug = $this->SMTPDebug;
- $hosts = explode(';', $this->Host);
+ $this->smtp->Debugoutput = $this->Debugoutput;
+ $this->smtp->do_verp = $this->do_verp;
$index = 0;
- $connection = $this->smtp->Connected();
+ $tls = ($this->SMTPSecure == 'tls');
+ $ssl = ($this->SMTPSecure == 'ssl');
+ $hosts = explode(';', $this->Host);
+ $lastexception = null;
- // Retry while there is no connection
- try {
- while ($index < count($hosts) && !$connection) {
- $hostinfo = array();
- if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {
- $host = $hostinfo[1];
- $port = $hostinfo[2];
- } else {
- $host = $hosts[$index];
- $port = $this->Port;
- }
-
- $tls = ($this->SMTPSecure == 'tls');
- $ssl = ($this->SMTPSecure == 'ssl');
-
- if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) {
-
- $hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname());
+ foreach ($hosts as $hostentry) {
+ $hostinfo = array();
+ $host = $hostentry;
+ $port = $this->Port;
+ if (preg_match('/^(.+):([0-9]+)$/', $hostentry, $hostinfo)) { //If $hostentry contains 'address:port', override default
+ $host = $hostinfo[1];
+ $port = $hostinfo[2];
+ }
+ if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout, $options)) {
+ try {
+ if ($this->Helo) {
+ $hello = $this->Helo;
+ } else {
+ $hello = $this->ServerHostname();
+ }
$this->smtp->Hello($hello);
if ($tls) {
if (!$this->smtp->StartTLS()) {
throw new phpmailerException($this->Lang('connect_host'));
}
-
//We must resend HELO after tls negotiation
$this->smtp->Hello($hello);
}
-
- $connection = true;
if ($this->SMTPAuth) {
- if (!$this->smtp->Authenticate($this->Username, $this->Password, $this->AuthType,
- $this->Realm, $this->Workstation)) {
+ if (!$this->smtp->Authenticate($this->Username, $this->Password, $this->AuthType, $this->Realm, $this->Workstation)) {
throw new phpmailerException($this->Lang('authenticate'));
}
}
+ return true;
+ } catch (phpmailerException $e) {
+ $lastexception = $e;
+ //We must have connected, but then failed TLS or Auth, so close connection nicely
+ $this->smtp->Quit();
}
- $index++;
- if (!$connection) {
- throw new phpmailerException($this->Lang('connect_host'));
- }
- }
- } catch (phpmailerException $e) {
- $this->smtp->Reset();
- if ($this->exceptions) {
- throw $e;
}
}
-
- return true;
+ //If we get here, all connection attempts have failed, so close connection hard
+ $this->smtp->Close();
+ //As we've caught all exceptions, just report whatever the last one was
+ if ($this->exceptions and !is_null($lastexception)) {
+ throw $lastexception;
+ }
+ return false;
}
/**
* Closes the active SMTP session if one exists.
* @return void
*/
- public function SmtpClose()
- {
+ public function SmtpClose() {
if ($this->smtp !== null) {
- if ($this->smtp->Connected()) {
+ if($this->smtp->Connected()) {
$this->smtp->Quit();
$this->smtp->Close();
}
@@ -1155,15 +1157,14 @@ class PHPMailer
}
/**
- * Sets the language for all class error messages.
- * Returns false if it cannot load the language file. The default language is English.
- * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br")
- * @param string $lang_path Path to the language file directory
+ * Sets the language for all class error messages.
+ * Returns false if it cannot load the language file. The default language is English.
+ * @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br")
+ * @param string $lang_path Path to the language file directory
* @return bool
- * @access public
- */
- public function SetLanguage($langcode = 'en', $lang_path = 'language/')
- {
+ * @access public
+ */
+ function SetLanguage($langcode = 'en', $lang_path = 'language/') {
//Define full set of translatable strings
$PHPMAILER_LANG = array(
'authenticate' => 'SMTP Error: Could not authenticate.',
@@ -1191,7 +1192,6 @@ class PHPMailer
$l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php';
}
$this->language = $PHPMAILER_LANG;
-
return ($l == true); //Returns false if language not found
}
@@ -1199,8 +1199,7 @@ class PHPMailer
* Return the current array of language strings
* @return array
*/
- public function GetTranslations()
- {
+ public function GetTranslations() {
return $this->language;
}
@@ -1215,8 +1214,7 @@ class PHPMailer
* @param array $addr
* @return string
*/
- public function AddrAppend($type, $addr)
- {
+ public function AddrAppend($type, $addr) {
$addr_str = $type . ': ';
$addresses = array();
foreach ($addr as $a) {
@@ -1234,8 +1232,7 @@ class PHPMailer
* @param string $addr
* @return string
*/
- public function AddrFormat($addr)
- {
+ public function AddrFormat($addr) {
if (empty($addr[1])) {
return $this->SecureHeader($addr[0]);
} else {
@@ -1253,8 +1250,7 @@ class PHPMailer
* @access public
* @return string
*/
- public function WrapText($message, $length, $qp_mode = false)
- {
+ public function WrapText($message, $length, $qp_mode = false) {
$soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
// If utf-8 encoding is used, we will need to make sure we don't
// split multibyte characters when we wrap
@@ -1296,6 +1292,9 @@ class PHPMailer
$buf = '';
}
while (strlen($word) > 0) {
+ if ($length <= 0) {
+ break;
+ }
$len = $length;
if ($is_utf8) {
$len = $this->UTF8CharBoundary($word, $len);
@@ -1338,8 +1337,7 @@ class PHPMailer
* @param int $maxLength find last character boundary prior to this length
* @return int
*/
- public function UTF8CharBoundary($encodedText, $maxLength)
- {
+ public function UTF8CharBoundary($encodedText, $maxLength) {
$foundSplitPos = false;
$lookBack = 3;
while (!$foundSplitPos) {
@@ -1368,7 +1366,6 @@ class PHPMailer
$foundSplitPos = true;
}
}
-
return $maxLength;
}
@@ -1378,13 +1375,12 @@ class PHPMailer
* @access public
* @return void
*/
- public function SetWordWrap()
- {
- if ($this->WordWrap < 1) {
+ public function SetWordWrap() {
+ if($this->WordWrap < 1) {
return;
}
- switch ($this->message_type) {
+ switch($this->message_type) {
case 'alt':
case 'alt_inline':
case 'alt_attach':
@@ -1402,8 +1398,7 @@ class PHPMailer
* @access public
* @return string The assembled header
*/
- public function CreateHeader()
- {
+ public function CreateHeader() {
$result = '';
// Set the boundaries
@@ -1419,21 +1414,21 @@ class PHPMailer
}
if ($this->ReturnPath) {
- $result .= $this->HeaderLine('Return-Path', trim($this->ReturnPath));
+ $result .= $this->HeaderLine('Return-Path', '<'.trim($this->ReturnPath).'>');
} elseif ($this->Sender == '') {
- $result .= $this->HeaderLine('Return-Path', trim($this->From));
+ $result .= $this->HeaderLine('Return-Path', '<'.trim($this->From).'>');
} else {
- $result .= $this->HeaderLine('Return-Path', trim($this->Sender));
+ $result .= $this->HeaderLine('Return-Path', '<'.trim($this->Sender).'>');
}
// To be created automatically by mail()
- if ($this->Mailer != 'mail') {
+ if($this->Mailer != 'mail') {
if ($this->SingleTo === true) {
- foreach ($this->to as $t) {
+ foreach($this->to as $t) {
$this->SingleToArray[] = $this->AddrFormat($t);
}
} else {
- if (count($this->to) > 0) {
+ if(count($this->to) > 0) {
$result .= $this->AddrAppend('To', $this->to);
} elseif (count($this->cc) == 0) {
$result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
@@ -1447,32 +1442,32 @@ class PHPMailer
$result .= $this->AddrAppend('From', $from);
// sendmail and mail() extract Cc from the header before sending
- if (count($this->cc) > 0) {
+ if(count($this->cc) > 0) {
$result .= $this->AddrAppend('Cc', $this->cc);
}
// sendmail and mail() extract Bcc from the header before sending
- if ((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
+ if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
$result .= $this->AddrAppend('Bcc', $this->bcc);
}
- if (count($this->ReplyTo) > 0) {
+ if(count($this->ReplyTo) > 0) {
$result .= $this->AddrAppend('Reply-To', $this->ReplyTo);
}
// mail() sets the subject itself
- if ($this->Mailer != 'mail') {
+ if($this->Mailer != 'mail') {
$result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
}
- if ($this->MessageID != '') {
+ if($this->MessageID != '') {
$result .= $this->HeaderLine('Message-ID', $this->MessageID);
} else {
$result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
}
$result .= $this->HeaderLine('X-Priority', $this->Priority);
if ($this->XMailer == '') {
- $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (http://code.google.com/a/apache-extras.org/p/phpmailer/)');
+ $result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (https://github.com/PHPMailer/PHPMailer/)');
} else {
$myXmailer = trim($this->XMailer);
if ($myXmailer) {
@@ -1480,12 +1475,12 @@ class PHPMailer
}
}
- if ($this->ConfirmReadingTo != '') {
+ if($this->ConfirmReadingTo != '') {
$result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
}
// Add custom headers
- for ($index = 0; $index < count($this->CustomHeader); $index++) {
+ for($index = 0; $index < count($this->CustomHeader); $index++) {
$result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
}
if (!$this->sign_key_file) {
@@ -1501,34 +1496,36 @@ class PHPMailer
* @access public
* @return string
*/
- public function GetMailMIME()
- {
+ public function GetMailMIME() {
$result = '';
- switch ($this->message_type) {
+ switch($this->message_type) {
case 'inline':
$result .= $this->HeaderLine('Content-Type', 'multipart/related;');
- $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
+ $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1].'"');
break;
case 'attach':
case 'inline_attach':
case 'alt_attach':
case 'alt_inline_attach':
$result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
- $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
+ $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1].'"');
break;
case 'alt':
case 'alt_inline':
$result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
- $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
+ $result .= $this->TextLine("\tboundary=\"" . $this->boundary[1].'"');
break;
default:
// Catches case 'plain': and case '':
- $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
$result .= $this->TextLine('Content-Type: '.$this->ContentType.'; charset='.$this->CharSet);
break;
}
+ //RFC1341 part 5 says 7bit is assumed if not specified
+ if ($this->Encoding != '7bit') {
+ $result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
+ }
- if ($this->Mailer != 'mail') {
+ if($this->Mailer != 'mail') {
$result .= $this->LE;
}
@@ -1540,19 +1537,18 @@ class PHPMailer
* @access public
* @return string
*/
- public function GetSentMIMEMessage()
- {
+ public function GetSentMIMEMessage() {
return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody;
}
+
/**
* Assembles the message body. Returns an empty string on failure.
* @access public
* @throws phpmailerException
* @return string The assembled message body
*/
- public function CreateBody()
- {
+ public function CreateBody() {
$body = '';
if ($this->sign_key_file) {
@@ -1561,30 +1557,30 @@ class PHPMailer
$this->SetWordWrap();
- switch ($this->message_type) {
+ switch($this->message_type) {
case 'inline':
$body .= $this->GetBoundary($this->boundary[1], '', '', '');
$body .= $this->EncodeString($this->Body, $this->Encoding);
$body .= $this->LE.$this->LE;
- $body .= $this->AttachAll("inline", $this->boundary[1]);
+ $body .= $this->AttachAll('inline', $this->boundary[1]);
break;
case 'attach':
$body .= $this->GetBoundary($this->boundary[1], '', '', '');
$body .= $this->EncodeString($this->Body, $this->Encoding);
$body .= $this->LE.$this->LE;
- $body .= $this->AttachAll("attachment", $this->boundary[1]);
+ $body .= $this->AttachAll('attachment', $this->boundary[1]);
break;
case 'inline_attach':
- $body .= $this->TextLine("--" . $this->boundary[1]);
+ $body .= $this->TextLine('--' . $this->boundary[1]);
$body .= $this->HeaderLine('Content-Type', 'multipart/related;');
- $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
+ $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"');
$body .= $this->LE;
$body .= $this->GetBoundary($this->boundary[2], '', '', '');
$body .= $this->EncodeString($this->Body, $this->Encoding);
$body .= $this->LE.$this->LE;
- $body .= $this->AttachAll("inline", $this->boundary[2]);
+ $body .= $this->AttachAll('inline', $this->boundary[2]);
$body .= $this->LE;
- $body .= $this->AttachAll("attachment", $this->boundary[1]);
+ $body .= $this->AttachAll('attachment', $this->boundary[1]);
break;
case 'alt':
$body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
@@ -1593,27 +1589,32 @@ class PHPMailer
$body .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
$body .= $this->EncodeString($this->Body, $this->Encoding);
$body .= $this->LE.$this->LE;
+ if(!empty($this->Ical)) {
+ $body .= $this->GetBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', '');
+ $body .= $this->EncodeString($this->Ical, $this->Encoding);
+ $body .= $this->LE.$this->LE;
+ }
$body .= $this->EndBoundary($this->boundary[1]);
break;
case 'alt_inline':
$body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
$body .= $this->EncodeString($this->AltBody, $this->Encoding);
$body .= $this->LE.$this->LE;
- $body .= $this->TextLine("--" . $this->boundary[1]);
+ $body .= $this->TextLine('--' . $this->boundary[1]);
$body .= $this->HeaderLine('Content-Type', 'multipart/related;');
- $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
+ $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"');
$body .= $this->LE;
$body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '');
$body .= $this->EncodeString($this->Body, $this->Encoding);
$body .= $this->LE.$this->LE;
- $body .= $this->AttachAll("inline", $this->boundary[2]);
+ $body .= $this->AttachAll('inline', $this->boundary[2]);
$body .= $this->LE;
$body .= $this->EndBoundary($this->boundary[1]);
break;
case 'alt_attach':
- $body .= $this->TextLine("--" . $this->boundary[1]);
+ $body .= $this->TextLine('--' . $this->boundary[1]);
$body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
- $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
+ $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"');
$body .= $this->LE;
$body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');
$body .= $this->EncodeString($this->AltBody, $this->Encoding);
@@ -1623,28 +1624,28 @@ class PHPMailer
$body .= $this->LE.$this->LE;
$body .= $this->EndBoundary($this->boundary[2]);
$body .= $this->LE;
- $body .= $this->AttachAll("attachment", $this->boundary[1]);
+ $body .= $this->AttachAll('attachment', $this->boundary[1]);
break;
case 'alt_inline_attach':
- $body .= $this->TextLine("--" . $this->boundary[1]);
+ $body .= $this->TextLine('--' . $this->boundary[1]);
$body .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
- $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2] . '"');
+ $body .= $this->TextLine("\tboundary=\"" . $this->boundary[2].'"');
$body .= $this->LE;
$body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '');
$body .= $this->EncodeString($this->AltBody, $this->Encoding);
$body .= $this->LE.$this->LE;
- $body .= $this->TextLine("--" . $this->boundary[2]);
+ $body .= $this->TextLine('--' . $this->boundary[2]);
$body .= $this->HeaderLine('Content-Type', 'multipart/related;');
- $body .= $this->TextLine("\tboundary=\"" . $this->boundary[3] . '"');
+ $body .= $this->TextLine("\tboundary=\"" . $this->boundary[3].'"');
$body .= $this->LE;
$body .= $this->GetBoundary($this->boundary[3], '', 'text/html', '');
$body .= $this->EncodeString($this->Body, $this->Encoding);
$body .= $this->LE.$this->LE;
- $body .= $this->AttachAll("inline", $this->boundary[3]);
+ $body .= $this->AttachAll('inline', $this->boundary[3]);
$body .= $this->LE;
$body .= $this->EndBoundary($this->boundary[2]);
$body .= $this->LE;
- $body .= $this->AttachAll("attachment", $this->boundary[1]);
+ $body .= $this->AttachAll('attachment', $this->boundary[1]);
break;
default:
// catch case 'plain' and case ''
@@ -1656,17 +1657,20 @@ class PHPMailer
$body = '';
} elseif ($this->sign_key_file) {
try {
- $file = tempnam('', 'mail');
+ if (!defined('PKCS7_TEXT')) {
+ throw new phpmailerException($this->Lang('signing').' OpenSSL extension missing.');
+ }
+ $file = tempnam(sys_get_temp_dir(), 'mail');
file_put_contents($file, $body); //TODO check this worked
- $signed = tempnam("", "signed");
- if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) {
+ $signed = tempnam(sys_get_temp_dir(), 'signed');
+ if (@openssl_pkcs7_sign($file, $signed, 'file://'.realpath($this->sign_cert_file), array('file://'.realpath($this->sign_key_file), $this->sign_key_pass), null)) {
@unlink($file);
$body = file_get_contents($signed);
@unlink($signed);
} else {
@unlink($file);
@unlink($signed);
- throw new phpmailerException($this->Lang("signing").openssl_error_string());
+ throw new phpmailerException($this->Lang('signing').openssl_error_string());
}
} catch (phpmailerException $e) {
$body = '';
@@ -1675,7 +1679,6 @@ class PHPMailer
}
}
}
-
return $body;
}
@@ -1688,16 +1691,15 @@ class PHPMailer
* @param string $encoding
* @return string
*/
- protected function GetBoundary($boundary, $charSet, $contentType, $encoding)
- {
+ protected function GetBoundary($boundary, $charSet, $contentType, $encoding) {
$result = '';
- if ($charSet == '') {
+ if($charSet == '') {
$charSet = $this->CharSet;
}
- if ($contentType == '') {
+ if($contentType == '') {
$contentType = $this->ContentType;
}
- if ($encoding == '') {
+ if($encoding == '') {
$encoding = $this->Encoding;
}
$result .= $this->TextLine('--' . $boundary);
@@ -1715,8 +1717,7 @@ class PHPMailer
* @param string $boundary
* @return string
*/
- protected function EndBoundary($boundary)
- {
+ protected function EndBoundary($boundary) {
return $this->LE . '--' . $boundary . '--' . $this->LE;
}
@@ -1725,8 +1726,7 @@ class PHPMailer
* @access protected
* @return void
*/
- protected function SetMessageType()
- {
+ protected function SetMessageType() {
$this->message_type = array();
if($this->AlternativeExists()) $this->message_type[] = "alt";
if($this->InlineImageExists()) $this->message_type[] = "inline";
@@ -1736,14 +1736,13 @@ class PHPMailer
}
/**
- * Returns a formatted header line.
+ * Returns a formatted header line.
* @access public
* @param string $name
* @param string $value
* @return string
*/
- public function HeaderLine($name, $value)
- {
+ public function HeaderLine($name, $value) {
return $name . ': ' . $value . $this->LE;
}
@@ -1753,8 +1752,7 @@ class PHPMailer
* @param string $value
* @return string
*/
- public function TextLine($value)
- {
+ public function TextLine($value) {
return $value . $this->LE;
}
@@ -1773,14 +1771,19 @@ class PHPMailer
* @throws phpmailerException
* @return bool
*/
- public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream')
- {
+ public function AddAttachment($path, $name = '', $encoding = 'base64', $type = '') {
try {
if ( !@is_file($path) ) {
throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE);
}
+
+ //If a MIME type is not specified, try to work it out from the file name
+ if ($type == '') {
+ $type = self::filenameToType($path);
+ }
+
$filename = basename($path);
- if ($name == '') {
+ if ( $name == '' ) {
$name = $filename;
}
@@ -1803,11 +1806,8 @@ class PHPMailer
if ($this->SMTPDebug) {
$this->edebug($e->getMessage()."\n");
}
- if ( $e->getCode() == self::STOP_CRITICAL ) {
- return false;
- }
+ return false;
}
-
return true;
}
@@ -1815,8 +1815,7 @@ class PHPMailer
* Return the current array of attachments
* @return array
*/
- public function GetAttachments()
- {
+ public function GetAttachments() {
return $this->attachment;
}
@@ -1828,8 +1827,7 @@ class PHPMailer
* @param string $boundary
* @return string
*/
- protected function AttachAll($disposition_type, $boundary)
- {
+ protected function AttachAll($disposition_type, $boundary) {
// Return text of body
$mime = array();
$cidUniq = array();
@@ -1838,7 +1836,7 @@ class PHPMailer
// Add all attachments
foreach ($this->attachment as $attachment) {
// CHECK IF IT IS A VALID DISPOSITION_FILTER
- if ($attachment[6] == $disposition_type) {
+ if($attachment[6] == $disposition_type) {
// Check for string attachment
$string = '';
$path = '';
@@ -1865,22 +1863,28 @@ class PHPMailer
$mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE);
$mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
- if ($disposition == 'inline') {
+ if($disposition == 'inline') {
$mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
}
- $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
+ //If a filename contains any of these chars, it should be quoted, but not otherwise: RFC2183 & RFC2045 5.1
+ //Fixes a warning in IETF's msglint MIME checker
+ if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $name)) {
+ $mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
+ } else {
+ $mime[] = sprintf("Content-Disposition: %s; filename=%s%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
+ }
// Encode as string attachment
- if ($bString) {
+ if($bString) {
$mime[] = $this->EncodeString($string, $encoding);
- if ($this->IsError()) {
+ if($this->IsError()) {
return '';
}
$mime[] = $this->LE.$this->LE;
} else {
$mime[] = $this->EncodeFile($path, $encoding);
- if ($this->IsError()) {
+ if($this->IsError()) {
return '';
}
$mime[] = $this->LE.$this->LE;
@@ -1903,17 +1907,11 @@ class PHPMailer
* @access protected
* @return string
*/
- protected function EncodeFile($path, $encoding = 'base64')
- {
+ protected function EncodeFile($path, $encoding = 'base64') {
try {
if (!is_readable($path)) {
throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE);
}
- // if (!function_exists('get_magic_quotes')) {
- // function get_magic_quotes() {
- // return false;
- // }
- // }
$magic_quotes = get_magic_quotes_runtime();
if ($magic_quotes) {
if (version_compare(PHP_VERSION, '5.3.0', '<')) {
@@ -1931,11 +1929,9 @@ class PHPMailer
ini_set('magic_quotes_runtime', $magic_quotes);
}
}
-
return $file_buffer;
} catch (Exception $e) {
$this->SetError($e->getMessage());
-
return '';
}
}
@@ -1948,10 +1944,9 @@ class PHPMailer
* @access public
* @return string
*/
- public function EncodeString($str, $encoding = 'base64')
- {
+ public function EncodeString($str, $encoding = 'base64') {
$encoded = '';
- switch (strtolower($encoding)) {
+ switch(strtolower($encoding)) {
case 'base64':
$encoded = chunk_split(base64_encode($str), 76, $this->LE);
break;
@@ -1972,7 +1967,6 @@ class PHPMailer
$this->SetError($this->Lang('encoding') . $encoding);
break;
}
-
return $encoded;
}
@@ -1983,8 +1977,7 @@ class PHPMailer
* @param string $position
* @return string
*/
- public function EncodeHeader($str, $position = 'text')
- {
+ public function EncodeHeader($str, $position = 'text') {
$x = 0;
switch (strtolower($position)) {
@@ -2009,13 +2002,13 @@ class PHPMailer
break;
}
- if ($x == 0) {
+ if ($x == 0) { //There are no chars that need encoding
return ($str);
}
$maxlen = 75 - 7 - strlen($this->CharSet);
// Try to select the encoding which should produce the shortest output
- if (strlen($str)/3 < $x) {
+ if ($x > strlen($str)/3) { //More than a third of the content will need encoding, so B encoding will be most efficient
$encoding = 'B';
if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {
// Use a custom function which correctly encodes and wraps long
@@ -2045,12 +2038,10 @@ class PHPMailer
* @param string $str multi-byte text to wrap encode
* @return bool
*/
- public function HasMultiBytes($str)
- {
+ public function HasMultiBytes($str) {
if (function_exists('mb_strlen')) {
return (strlen($str) > mb_strlen($str, $this->CharSet));
} else { // Assume no multibytes (we can't handle without mbstring functions anyway)
-
return false;
}
}
@@ -2064,8 +2055,7 @@ class PHPMailer
* @param string $lf string to use as linefeed/end-of-line
* @return string
*/
- public function Base64EncodeWrapMB($str, $lf=null)
- {
+ public function Base64EncodeWrapMB($str, $lf=null) {
$start = "=?".$this->CharSet."?B?";
$end = "?=";
$encoded = "";
@@ -2089,105 +2079,46 @@ class PHPMailer
$chunk = mb_substr($str, $i, $offset, $this->CharSet);
$chunk = base64_encode($chunk);
$lookBack++;
- } while (strlen($chunk) > $length);
+ }
+ while (strlen($chunk) > $length);
$encoded .= $chunk . $lf;
}
// Chomp the last linefeed
$encoded = substr($encoded, 0, -strlen($lf));
-
return $encoded;
}
/**
- * Encode string to quoted-printable.
- * Only uses standard PHP, slow, but will always work
- * @access public
- * @param string $input
- * @param integer $line_max Number of chars allowed on a line before wrapping
- * @param bool $space_conv
- * @internal param string $string the text to encode
- * @return string
- */
- public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false)
- {
- $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) ) {
- $linlen = strlen($line);
- $newline = '';
- for ($i = 0; $i < $linlen; $i++) {
- $c = substr( $line, $i, 1 );
- $dec = ord( $c );
- if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E
- $c = '=2E';
- }
- if ($dec == 32) {
- if ( $i == ( $linlen - 1 ) ) { // convert space at eol only
- $c = '=20';
- } elseif ($space_conv) {
- $c = '=20';
- }
- } elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
- $h2 = (integer) floor($dec/16);
- $h1 = (integer) floor($dec%16);
- $c = $escape.$hex[$h2].$hex[$h1];
- }
- if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
- $output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
- $newline = '';
- // check if newline first character will be point or not
- if ($dec == 46) {
- $c = '=2E';
- }
- }
- $newline .= $c;
- } // end of for
- $output .= $newline.$eol;
- } // end of while
-
- return $output;
+ * Encode string to RFC2045 (6.7) quoted-printable format
+ * @access public
+ * @param string $string The text to encode
+ * @param integer $line_max Number of chars allowed on a line before wrapping
+ * @return string
+ * @link PHP version adapted from http://www.php.net/manual/en/function.quoted-printable-decode.php#89417
+ */
+ public function EncodeQP($string, $line_max = 76) {
+ if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3)
+ return quoted_printable_encode($string);
+ }
+ //Fall back to a pure PHP implementation
+ $string = str_replace(array('%20', '%0D%0A.', '%0D%0A', '%'), array(' ', "\r\n=2E", "\r\n", '='), rawurlencode($string));
+ $string = preg_replace('/[^\r\n]{'.($line_max - 3).'}[^=\r\n]{2}/', "$0=\r\n", $string);
+ return $string;
}
/**
- * Encode string to RFC2045 (6.7) quoted-printable format
- * Uses a PHP5 stream filter to do the encoding about 64x faster than the old version
- * Also results in same content as you started with after decoding
- * @see EncodeQPphp()
- * @access public
- * @param string $string the text to encode
- * @param integer $line_max Number of chars allowed on a line before wrapping
- * @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function
- * @return string
- * @author Marcus Bointon
- */
- public function EncodeQP($string, $line_max = 76, $space_conv = false)
- {
- if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3)
-
- return quoted_printable_encode($string);
- }
- $filters = stream_get_filters();
- if (!in_array('convert.*', $filters)) { //Got convert stream filter?
-
- return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation
- }
- $fp = fopen('php://temp/', 'r+');
- $string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks
- $params = array('line-length' => $line_max, 'line-break-chars' => $this->LE);
- $s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params);
- fputs($fp, $string);
- rewind($fp);
- $out = stream_get_contents($fp);
- stream_filter_remove($s);
- $out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange
- fclose($fp);
-
- return $out;
+ * Wrapper to preserve BC for old QP encoding function that was removed
+ * @see EncodeQP()
+ * @access public
+ * @param string $string
+ * @param integer $line_max
+ * @param bool $space_conv
+ * @return string
+ */
+ public function EncodeQPphp($string, $line_max = 76, $space_conv = false) {
+ return $this->EncodeQP($string, $line_max);
}
/**
@@ -2198,10 +2129,9 @@ class PHPMailer
* @access public
* @return string
*/
- public function EncodeQ($str, $position = 'text')
- {
+ public function EncodeQ($str, $position = 'text') {
//There should not be any EOL in the string
- $pattern="";
+ $pattern = '';
$encoded = str_replace(array("\r", "\n"), '', $str);
switch (strtolower($position)) {
case 'phrase':
@@ -2210,8 +2140,8 @@ class PHPMailer
case 'comment':
$pattern = '\(\)"';
- //note that we dont break here!
- //for this reason we build the $pattern withoud including delimiters and []
+ //note that we don't break here!
+ //for this reason we build the $pattern without including delimiters and []
case 'text':
default:
@@ -2242,8 +2172,11 @@ class PHPMailer
* @param string $type File extension (MIME) type.
* @return void
*/
- public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream')
- {
+ public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = '') {
+ //If a MIME type is not specified, try to work it out from the file name
+ if ($type == '') {
+ $type = self::filenameToType($filename);
+ }
// Append to $attachment array
$this->attachment[] = array(
0 => $string,
@@ -2258,28 +2191,29 @@ class PHPMailer
}
/**
- * Adds an embedded attachment. This can include images, sounds, and
- * just about any other document. Make sure to set the $type to an
- * image type. For JPEG images use "image/jpeg" and for GIF images
- * use "image/gif".
+ * Add an embedded attachment from a file.
+ * This can include images, sounds, and just about any other document type.
* @param string $path Path to the attachment.
- * @param string $cid Content ID of the attachment. Use this to identify
- * the Id for accessing the image in an HTML form.
+ * @param string $cid Content ID of the attachment; Use this to reference
+ * the content when using an embedded image in HTML.
* @param string $name Overrides the attachment name.
* @param string $encoding File encoding (see $Encoding).
- * @param string $type File extension (MIME) type.
- * @return bool
+ * @param string $type File MIME type.
+ * @return bool True on successfully adding an attachment
*/
- public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream')
- {
+ public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '') {
if ( !@is_file($path) ) {
$this->SetError($this->Lang('file_access') . $path);
-
return false;
}
+ //If a MIME type is not specified, try to work it out from the file name
+ if ($type == '') {
+ $type = self::filenameToType($path);
+ }
+
$filename = basename($path);
- if ($name == '') {
+ if ( $name == '' ) {
$name = $filename;
}
@@ -2294,25 +2228,29 @@ class PHPMailer
6 => 'inline',
7 => $cid
);
-
return true;
}
+
/**
- * Adds an embedded stringified attachment. This can include images, sounds, and
- * just about any other document. Make sure to set the $type to an
- * image type. For JPEG images use "image/jpeg" and for GIF images
- * use "image/gif".
- * @param string $string The attachment.
- * @param string $cid Content ID of the attachment. Use this to identify
- * the Id for accessing the image in an HTML form.
- * @param string $name Overrides the attachment name.
+ * Add an embedded stringified attachment.
+ * This can include images, sounds, and just about any other document type.
+ * Be sure to set the $type to an image type for images:
+ * JPEG images use 'image/jpeg', GIF uses 'image/gif', PNG uses 'image/png'.
+ * @param string $string The attachment binary data.
+ * @param string $cid Content ID of the attachment; Use this to reference
+ * the content when using an embedded image in HTML.
+ * @param string $name
* @param string $encoding File encoding (see $Encoding).
- * @param string $type File extension (MIME) type.
- * @return bool
+ * @param string $type MIME type.
+ * @return bool True on successfully adding an attachment
*/
- public function AddStringEmbeddedImage($string, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream')
- {
+ public function AddStringEmbeddedImage($string, $cid, $name = '', $encoding = 'base64', $type = '') {
+ //If a MIME type is not specified, try to work it out from the name
+ if ($type == '') {
+ $type = self::filenameToType($name);
+ }
+
// Append to $attachment array
$this->attachment[] = array(
0 => $string,
@@ -2324,6 +2262,7 @@ class PHPMailer
6 => 'inline',
7 => $cid
);
+ return true;
}
/**
@@ -2331,14 +2270,12 @@ class PHPMailer
* @access public
* @return bool
*/
- public function InlineImageExists()
- {
- foreach ($this->attachment as $attachment) {
+ public function InlineImageExists() {
+ foreach($this->attachment as $attachment) {
if ($attachment[6] == 'inline') {
return true;
}
}
-
return false;
}
@@ -2346,14 +2283,12 @@ class PHPMailer
* Returns true if an attachment (non-inline) is present.
* @return bool
*/
- public function AttachmentExists()
- {
- foreach ($this->attachment as $attachment) {
+ public function AttachmentExists() {
+ foreach($this->attachment as $attachment) {
if ($attachment[6] == 'attachment') {
return true;
}
}
-
return false;
}
@@ -2361,8 +2296,7 @@ class PHPMailer
* Does this message have an alternative body set?
* @return bool
*/
- public function AlternativeExists()
- {
+ public function AlternativeExists() {
return !empty($this->AltBody);
}
@@ -2374,9 +2308,8 @@ class PHPMailer
* Clears all recipients assigned in the TO array. Returns void.
* @return void
*/
- public function ClearAddresses()
- {
- foreach ($this->to as $to) {
+ public function ClearAddresses() {
+ foreach($this->to as $to) {
unset($this->all_recipients[strtolower($to[0])]);
}
$this->to = array();
@@ -2386,9 +2319,8 @@ class PHPMailer
* Clears all recipients assigned in the CC array. Returns void.
* @return void
*/
- public function ClearCCs()
- {
- foreach ($this->cc as $cc) {
+ public function ClearCCs() {
+ foreach($this->cc as $cc) {
unset($this->all_recipients[strtolower($cc[0])]);
}
$this->cc = array();
@@ -2398,9 +2330,8 @@ class PHPMailer
* Clears all recipients assigned in the BCC array. Returns void.
* @return void
*/
- public function ClearBCCs()
- {
- foreach ($this->bcc as $bcc) {
+ public function ClearBCCs() {
+ foreach($this->bcc as $bcc) {
unset($this->all_recipients[strtolower($bcc[0])]);
}
$this->bcc = array();
@@ -2410,8 +2341,7 @@ class PHPMailer
* Clears all recipients assigned in the ReplyTo array. Returns void.
* @return void
*/
- public function ClearReplyTos()
- {
+ public function ClearReplyTos() {
$this->ReplyTo = array();
}
@@ -2420,8 +2350,7 @@ class PHPMailer
* array. Returns void.
* @return void
*/
- public function ClearAllRecipients()
- {
+ public function ClearAllRecipients() {
$this->to = array();
$this->cc = array();
$this->bcc = array();
@@ -2433,8 +2362,7 @@ class PHPMailer
* attachments. Returns void.
* @return void
*/
- public function ClearAttachments()
- {
+ public function ClearAttachments() {
$this->attachment = array();
}
@@ -2442,8 +2370,7 @@ class PHPMailer
* Clears all custom headers. Returns void.
* @return void
*/
- public function ClearCustomHeaders()
- {
+ public function ClearCustomHeaders() {
$this->CustomHeader = array();
}
@@ -2457,8 +2384,7 @@ class PHPMailer
* @param string $msg
* @return void
*/
- protected function SetError($msg)
- {
+ protected function SetError($msg) {
$this->error_count++;
if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
$lasterror = $this->smtp->getError();
@@ -2475,15 +2401,11 @@ class PHPMailer
* @return string
* @static
*/
- public static function RFCDate()
- {
- $tz = date('Z');
- $tzs = ($tz < 0) ? '-' : '+';
- $tz = abs($tz);
- $tz = (int) ($tz/3600)*100 + ($tz%3600)/60;
- $result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);
-
- return $result;
+ public static function RFCDate() {
+ //Set the time zone to whatever the default is to avoid 500 errors
+ //Will default to UTC if it's not set properly in php.ini
+ date_default_timezone_set(@date_default_timezone_get());
+ return date('D, j M Y H:i:s O');
}
/**
@@ -2491,8 +2413,7 @@ class PHPMailer
* @access protected
* @return string
*/
- protected function ServerHostname()
- {
+ protected function ServerHostname() {
if (!empty($this->Hostname)) {
$result = $this->Hostname;
} elseif (isset($_SERVER['SERVER_NAME'])) {
@@ -2510,13 +2431,12 @@ class PHPMailer
* @param string $key
* @return string
*/
- protected function Lang($key)
- {
- if (count($this->language) < 1) {
+ protected function Lang($key) {
+ if(count($this->language) < 1) {
$this->SetLanguage('en'); // set the default language
}
- if (isset($this->language[$key])) {
+ if(isset($this->language[$key])) {
return $this->language[$key];
} else {
return 'Language string failed to load: ' . $key;
@@ -2528,8 +2448,7 @@ class PHPMailer
* @access public
* @return bool
*/
- public function IsError()
- {
+ public function IsError() {
return ($this->error_count > 0);
}
@@ -2539,15 +2458,13 @@ class PHPMailer
* @param string $str String to FixEOL
* @return string
*/
- public function FixEOL($str)
- {
- // condense down to \n
- $nstr = str_replace(array("\r\n", "\r"), "\n", $str);
- // Now convert LE as needed
- if ($this->LE !== "\n") {
- $nstr = str_replace("\n", $this->LE, $nstr);
- }
-
+ public function FixEOL($str) {
+ // condense down to \n
+ $nstr = str_replace(array("\r\n", "\r"), "\n", $str);
+ // Now convert LE as needed
+ if ($this->LE !== "\n") {
+ $nstr = str_replace("\n", $this->LE, $nstr);
+ }
return $nstr;
}
@@ -2559,25 +2476,26 @@ class PHPMailer
* @param string $value header value
* @return void
*/
- public function AddCustomHeader($name, $value=null)
- {
- if ($value === null) {
- // Value passed in as name:value
- $this->CustomHeader[] = explode(':', $name, 2);
- } else {
- $this->CustomHeader[] = array($name, $value);
- }
+ public function AddCustomHeader($name, $value=null) {
+ if ($value === null) {
+ // Value passed in as name:value
+ $this->CustomHeader[] = explode(':', $name, 2);
+ } else {
+ $this->CustomHeader[] = array($name, $value);
+ }
}
/**
- * Evaluates the message and returns modifications for inline images and backgrounds
+ * Creates a message from an HTML string, making modifications for inline images and backgrounds
+ * and creates a plain-text version by converting the HTML
+ * Overwrites any existing values in $this->Body and $this->AltBody
* @access public
- * @param string $message Text to be HTML modified
+ * @param string $message HTML message string
* @param string $basedir baseline directory for path
+ * @param bool $advanced Whether to use the advanced HTML to text converter
* @return string $message
*/
- public function MsgHTML($message, $basedir = '')
- {
+ public function MsgHTML($message, $basedir = '', $advanced = false) {
preg_match_all("/(src|background)=[\"'](.*)[\"']/Ui", $message, $images);
if (isset($images[2])) {
foreach ($images[2] as $i => $url) {
@@ -2588,30 +2506,42 @@ class PHPMailer
if ($directory == '.') {
$directory = '';
}
- $cid = 'cid:' . md5($url);
- $ext = pathinfo($filename, PATHINFO_EXTENSION);
- $mimeType = self::_mime_types($ext);
- if ( strlen($basedir) > 1 && substr($basedir, -1) != '/') { $basedir .= '/'; }
- if ( strlen($directory) > 1 && substr($directory, -1) != '/') { $directory .= '/'; }
- if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($url), $filename, 'base64', $mimeType) ) {
- $message = preg_replace("/".$images[1][$i]."=[\"']".preg_quote($url, '/')."[\"']/Ui", $images[1][$i]."=\"".$cid."\"", $message);
+ $cid = md5($url).'@phpmailer.0'; //RFC2392 S 2
+ if (strlen($basedir) > 1 && substr($basedir, -1) != '/') {
+ $basedir .= '/';
+ }
+ if (strlen($directory) > 1 && substr($directory, -1) != '/') {
+ $directory .= '/';
+ }
+ if ($this->AddEmbeddedImage($basedir.$directory.$filename, $cid, $filename, 'base64', self::_mime_types(self::mb_pathinfo($filename, PATHINFO_EXTENSION)))) {
+ $message = preg_replace("/".$images[1][$i]."=[\"']".preg_quote($url, '/')."[\"']/Ui", $images[1][$i]."=\"cid:".$cid."\"", $message);
}
}
}
}
$this->IsHTML(true);
- $this->Body = $message;
- if (empty($this->AltBody)) {
- $textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s', '', $message)));
- if (!empty($textMsg)) {
- $this->AltBody = html_entity_decode($textMsg, ENT_QUOTES, $this->CharSet);
- }
- }
if (empty($this->AltBody)) {
$this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n";
}
+ //Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better
+ $this->Body = $this->NormalizeBreaks($message);
+ $this->AltBody = $this->NormalizeBreaks($this->html2text($message, $advanced));
+ return $this->Body;
+ }
- return $message;
+ /**
+ * Convert an HTML string into a plain text version
+ * @param string $html The HTML text to convert
+ * @param bool $advanced Should this use the more complex html2text converter or just a simple one?
+ * @return string
+ */
+ public function html2text($html, $advanced = false) {
+ if ($advanced) {
+ require_once 'extras/class.html2text.php';
+ $h = new html2text($html);
+ return $h->get_text();
+ }
+ return html_entity_decode(trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))), ENT_QUOTES, $this->CharSet);
}
/**
@@ -2621,8 +2551,7 @@ class PHPMailer
* @return string MIME type of ext
* @static
*/
- public static function _mime_types($ext = '')
- {
+ public static function _mime_types($ext = '') {
$mimes = array(
'xl' => 'application/excel',
'hqx' => 'application/mac-binhex40',
@@ -2711,26 +2640,87 @@ class PHPMailer
'avi' => 'video/x-msvideo',
'movie' => 'video/x-sgi-movie'
);
-
return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
}
/**
- * Set (or reset) Class Objects (variables)
- *
- * Usage Example:
- * $page->set('X-Priority', '3');
- *
- * @access public
- * @param string $name Parameter Name
- * @param mixed $value Parameter Value
- * NOTE: will not work with arrays, there are no arrays to set/reset
+ * Try to map a file name to a MIME type, default to application/octet-stream
+ * @param string $filename A file name or full path, does not need to exist as a file
+ * @return string
+ * @static
+ */
+ public static function filenameToType($filename) {
+ //In case the path is a URL, strip any query string before getting extension
+ $qpos = strpos($filename, '?');
+ if ($qpos !== false) {
+ $filename = substr($filename, 0, $qpos);
+ }
+ $pathinfo = self::mb_pathinfo($filename);
+ return self::_mime_types($pathinfo['extension']);
+ }
+
+ /**
+ * Drop-in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe.
+ * Works similarly to the one in PHP >= 5.2.0
+ * @link http://www.php.net/manual/en/function.pathinfo.php#107461
+ * @param string $path A filename or path, does not need to exist as a file
+ * @param integer|string $options Either a PATHINFO_* constant, or a string name to return only the specified piece, allows 'filename' to work on PHP < 5.2
+ * @return string|array
+ * @static
+ */
+ public static function mb_pathinfo($path, $options = null) {
+ $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');
+ $m = array();
+ preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $m);
+ if(array_key_exists(1, $m)) {
+ $ret['dirname'] = $m[1];
+ }
+ if(array_key_exists(2, $m)) {
+ $ret['basename'] = $m[2];
+ }
+ if(array_key_exists(5, $m)) {
+ $ret['extension'] = $m[5];
+ }
+ if(array_key_exists(3, $m)) {
+ $ret['filename'] = $m[3];
+ }
+ switch($options) {
+ case PATHINFO_DIRNAME:
+ case 'dirname':
+ return $ret['dirname'];
+ break;
+ case PATHINFO_BASENAME:
+ case 'basename':
+ return $ret['basename'];
+ break;
+ case PATHINFO_EXTENSION:
+ case 'extension':
+ return $ret['extension'];
+ break;
+ case PATHINFO_FILENAME:
+ case 'filename':
+ return $ret['filename'];
+ break;
+ default:
+ return $ret;
+ }
+ }
+
+ /**
+ * Set (or reset) Class Objects (variables)
+ *
+ * Usage Example:
+ * $page->set('X-Priority', '3');
+ *
+ * @access public
+ * @param string $name
+ * @param mixed $value
+ * NOTE: will not work with arrays, there are no arrays to set/reset
* @throws phpmailerException
* @return bool
- * @todo Should this not be using __set() magic function?
- */
- public function set($name, $value = '')
- {
+ * @todo Should this not be using __set() magic function?
+ */
+ public function set($name, $value = '') {
try {
if (isset($this->$name) ) {
$this->$name = $value;
@@ -2743,31 +2733,42 @@ class PHPMailer
return false;
}
}
-
return true;
}
/**
* Strips newlines to prevent header injection.
* @access public
- * @param string $str String
+ * @param string $str
* @return string
*/
- public function SecureHeader($str)
- {
+ public function SecureHeader($str) {
return trim(str_replace(array("\r", "\n"), '', $str));
}
/**
+ * Normalize UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format
+ * Defaults to CRLF (for message bodies) and preserves consecutive breaks
+ * @param string $text
+ * @param string $breaktype What kind of line break to use, defaults to CRLF
+ * @return string
+ * @access public
+ * @static
+ */
+ public static function NormalizeBreaks($text, $breaktype = "\r\n") {
+ return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text);
+ }
+
+
+ /**
* Set the private key file and password to sign the message.
*
* @access public
- * @param $cert_filename
- * @param string $key_filename Parameter File Name
+ * @param string $cert_filename
+ * @param string $key_filename
* @param string $key_pass Password for private key
*/
- public function Sign($cert_filename, $key_filename, $key_pass)
- {
+ public function Sign($cert_filename, $key_filename, $key_pass) {
$this->sign_cert_file = $cert_filename;
$this->sign_key_file = $key_filename;
$this->sign_key_pass = $key_pass;
@@ -2780,8 +2781,7 @@ class PHPMailer
* @param string $txt
* @return string
*/
- public function DKIM_QP($txt)
- {
+ public function DKIM_QP($txt) {
$line = '';
for ($i = 0; $i < strlen($txt); $i++) {
$ord = ord($txt[$i]);
@@ -2791,7 +2791,6 @@ class PHPMailer
$line .= "=".sprintf("%02X", $ord);
}
}
-
return $line;
}
@@ -2800,10 +2799,16 @@ class PHPMailer
*
* @access public
* @param string $s Header
+ * @throws phpmailerException
* @return string
*/
- public function DKIM_Sign($s)
- {
+ public function DKIM_Sign($s) {
+ if (!defined('PKCS7_TEXT')) {
+ if ($this->exceptions) {
+ throw new phpmailerException($this->Lang("signing").' OpenSSL extension missing.');
+ }
+ return '';
+ }
$privKeyStr = file_get_contents($this->DKIM_private);
if ($this->DKIM_passphrase != '') {
$privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
@@ -2813,7 +2818,6 @@ class PHPMailer
if (openssl_sign($s, $signature, $privKey)) {
return base64_encode($signature);
}
-
return '';
}
@@ -2824,8 +2828,7 @@ class PHPMailer
* @param string $s Header
* @return string
*/
- public function DKIM_HeaderC($s)
- {
+ public function DKIM_HeaderC($s) {
$s = preg_replace("/\r\n\s+/", " ", $s);
$lines = explode("\r\n", $s);
foreach ($lines as $key => $line) {
@@ -2835,7 +2838,6 @@ class PHPMailer
$lines[$key] = $heading.":".trim($value) ; // Don't forget to remove WSP around the value
}
$s = implode("\r\n", $lines);
-
return $s;
}
@@ -2846,8 +2848,7 @@ class PHPMailer
* @param string $body Message Body
* @return string
*/
- public function DKIM_BodyC($body)
- {
+ public function DKIM_BodyC($body) {
if ($body == '') return "\r\n";
// stabilize line endings
$body = str_replace("\r\n", "\n", $body);
@@ -2856,7 +2857,6 @@ class PHPMailer
while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") {
$body = substr($body, 0, strlen($body) - 2);
}
-
return $body;
}
@@ -2869,21 +2869,29 @@ class PHPMailer
* @param string $body Body
* @return string
*/
- public function DKIM_Add($headers_line, $subject, $body)
- {
+ public function DKIM_Add($headers_line, $subject, $body) {
$DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms
$DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
$DKIMquery = 'dns/txt'; // Query method
$DKIMtime = time() ; // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
$subject_header = "Subject: $subject";
$headers = explode($this->LE, $headers_line);
- $from_header = "";
- $to_header = "";
- foreach ($headers as $header) {
+ $from_header = '';
+ $to_header = '';
+ $current = '';
+ foreach($headers as $header) {
if (strpos($header, 'From:') === 0) {
$from_header = $header;
+ $current = 'from_header';
} elseif (strpos($header, 'To:') === 0) {
$to_header = $header;
+ $current = 'to_header';
+ } else {
+ if($current && strpos($header, ' =?') === 0){
+ $current .= $header;
+ } else {
+ $current = '';
+ }
}
}
$from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
@@ -2904,8 +2912,7 @@ class PHPMailer
"\tb=";
$toSign = $this->DKIM_HeaderC($from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs);
$signed = $this->DKIM_Sign($toSign);
-
- return "X-PHPMAILER-DKIM: code.google.com/a/apache-extras.org/p/phpmailer/\r\n".$dkimhdrs.$signed."\r\n";
+ return $dkimhdrs.$signed."\r\n";
}
/**
@@ -2918,8 +2925,7 @@ class PHPMailer
* @param string $body
* @param string $from
*/
- protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from=null)
- {
+ protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from = null) {
if (!empty($this->action_function) && is_callable($this->action_function)) {
$params = array($isSent, $to, $cc, $bcc, $subject, $body, $from);
call_user_func_array($this->action_function, $params);
@@ -2931,16 +2937,13 @@ class PHPMailer
* Exception handler for PHPMailer
* @package PHPMailer
*/
-class phpmailerException extends Exception
-{
+class phpmailerException extends Exception {
/**
* Prettify error message output
* @return string
*/
- public function errorMessage()
- {
+ public function errorMessage() {
$errorMsg = '' . $this->getMessage() . "
\n";
-
return $errorMsg;
}
}