2
/*~ class.phpmailer.php
3
.---------------------------------------------------------------------------.
4
| Software: PHPMailer - PHP email class |
6
| Contact: via sourceforge.net support pages (also www.codeworxtech.com) |
7
| Info: http://phpmailer.sourceforge.net |
8
| Support: http://sourceforge.net/projects/phpmailer/ |
9
| ------------------------------------------------------------------------- |
10
| Admin: Andy Prevost (project admininistrator) |
11
| Authors: Andy Prevost (codeworxtech) codeworxtech@users.sourceforge.net |
12
| : Marcus Bointon (coolbru) coolbru@users.sourceforge.net |
13
| Founder: Brent R. Matzelle (original founder) |
14
| Copyright (c) 2004-2009, Andy Prevost. All Rights Reserved. |
15
| Copyright (c) 2001-2003, Brent R. Matzelle |
16
| ------------------------------------------------------------------------- |
17
| License: Distributed under the Lesser General Public License (LGPL) |
18
| http://www.gnu.org/copyleft/lesser.html |
19
| This program is distributed in the hope that it will be useful - WITHOUT |
20
| ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
21
| FITNESS FOR A PARTICULAR PURPOSE. |
22
| ------------------------------------------------------------------------- |
23
| We offer a number of paid services (www.codeworxtech.com): |
24
| - Web Hosting on highly optimized fast and secure servers |
25
| - Technology Consulting |
26
| - Oursourcing (highly qualified programmers and graphic designers) |
27
'---------------------------------------------------------------------------'
31
* PHPMailer - PHP email transport class
32
* NOTE: Requires PHP version 5 or later
34
* @author Andy Prevost
35
* @author Marcus Bointon
36
* @copyright 2004 - 2009 Andy Prevost
37
* @version $Id: class.phpmailer.php 447 2009-05-25 01:36:38Z codeworxtech $
38
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
41
if (version_compare(PHP_VERSION, '5.0.0', '<') ) exit("Sorry, this version of PHPMailer will only run on PHP version 5 or greater!\n");
45
/////////////////////////////////////////////////
47
/////////////////////////////////////////////////
50
* Email priority (1 = High, 3 = Normal, 5 = low).
56
* Sets the CharSet of the message.
59
public $CharSet = 'iso-8859-1';
62
* Sets the Content-type of the message.
65
public $ContentType = 'text/plain';
68
* Sets the Encoding of the message. Options for this are
69
* "8bit", "7bit", "binary", "base64", and "quoted-printable".
72
public $Encoding = '8bit';
75
* Holds the most recent mailer error message.
78
public $ErrorInfo = '';
81
* Sets the From email address for the message.
87
* Sets the From name of the message.
90
public $FromName = '';
93
* Sets the Sender email (Return-Path) of the message. If not empty,
94
* will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
100
* Sets the Subject of the message.
103
public $Subject = '';
106
* Sets the Body of the message. This can be either an HTML or text body.
107
* If HTML then run IsHTML(true).
113
* Sets the text-only body of the message. This automatically sets the
114
* email to multipart/alternative. This body can be read by mail
115
* clients that do not have HTML email capability such as mutt. Clients
116
* that can read HTML will view the normal Body.
119
public $AltBody = '';
122
* Sets word wrapping on the body of the message to a given number of
126
public $WordWrap = 0;
129
* Method to send mail: ("mail", "sendmail", or "smtp").
132
public $Mailer = 'mail';
135
* Sets the path of the sendmail program.
138
public $Sendmail = '/usr/sbin/sendmail';
141
* Path to PHPMailer plugins. Useful if the SMTP class
142
* is in a different directory than the PHP include path.
145
public $PluginDir = '';
148
* Sets the email address that a reading confirmation will be sent.
151
public $ConfirmReadingTo = '';
154
* Sets the hostname to use in Message-Id and Received headers
155
* and as default HELO string. If empty, the value returned
156
* by SERVER_NAME is used or 'localhost.localdomain'.
159
public $Hostname = '';
162
* Sets the message ID to be used in the Message-Id header.
163
* If empty, a unique id will be generated.
166
public $MessageID = '';
168
/////////////////////////////////////////////////
169
// PROPERTIES FOR SMTP
170
/////////////////////////////////////////////////
173
* Sets the SMTP hosts. All hosts must be separated by a
174
* semicolon. You can also specify a different port
175
* for each host by using this format: [hostname:port]
176
* (e.g. "smtp1.example.com:25;smtp2.example.com").
177
* Hosts will be tried in order.
180
public $Host = 'localhost';
183
* Sets the default SMTP server port.
189
* Sets the SMTP HELO of the message (Default is $Hostname).
195
* Sets connection prefix.
196
* Options are "", "ssl" or "tls"
199
public $SMTPSecure = '';
202
* Sets SMTP authentication. Utilizes the Username and Password variables.
205
public $SMTPAuth = false;
208
* Sets SMTP username.
211
public $Username = '';
214
* Sets SMTP password.
217
public $Password = '';
220
* Sets the SMTP server timeout in seconds.
221
* This function will not work with the win32 version.
224
public $Timeout = 10;
227
* Sets SMTP class debugging on or off.
230
public $SMTPDebug = false;
233
* Prevents the SMTP connection from being closed after each mail
234
* sending. If this is set to true then to close the connection
235
* requires an explicit call to SmtpClose().
238
public $SMTPKeepAlive = false;
241
* Provides the ability to have the TO field process individual
242
* emails, instead of sending to entire TO addresses
245
public $SingleTo = false;
248
* Provides the ability to change the line ending
254
* Sets the PHPMailer Version number
257
public $Version = '5.0.2';
259
/////////////////////////////////////////////////
260
// PROPERTIES, PRIVATE AND PROTECTED
261
/////////////////////////////////////////////////
263
private $smtp = NULL;
264
private $to = array();
265
private $cc = array();
266
private $bcc = array();
267
private $ReplyTo = array();
268
private $all_recipients = array();
269
private $attachment = array();
270
private $CustomHeader = array();
271
private $message_type = '';
272
private $boundary = array();
273
protected $language = array();
274
private $error_count = 0;
275
private $sign_cert_file = "";
276
private $sign_key_file = "";
277
private $sign_key_pass = "";
278
private $exceptions = false;
280
/////////////////////////////////////////////////
282
/////////////////////////////////////////////////
284
const STOP_MESSAGE = 0; // message only, continue processing
285
const STOP_CONTINUE = 1; // message?, likely ok to continue processing
286
const STOP_CRITICAL = 2; // message, plus full stop, critical error reached
288
/////////////////////////////////////////////////
289
// METHODS, VARIABLES
290
/////////////////////////////////////////////////
294
* @param boolean $exceptions Should we throw external exceptions?
296
public function __construct($exceptions = true) {
297
$this->exceptions = ($exceptions == true);
301
* Sets message type to HTML.
302
* @param bool $ishtml
305
public function IsHTML($ishtml = true) {
307
$this->ContentType = 'text/html';
309
$this->ContentType = 'text/plain';
314
* Sets Mailer to send message using SMTP.
317
public function IsSMTP() {
318
$this->Mailer = 'smtp';
322
* Sets Mailer to send message using PHP mail() function.
325
public function IsMail() {
326
$this->Mailer = 'mail';
330
* Sets Mailer to send message using the $Sendmail program.
333
public function IsSendmail() {
334
if (!stristr(ini_get('sendmail_path'), 'sendmail')) {
335
$this->Sendmail = '/var/qmail/bin/sendmail';
337
$this->Mailer = 'sendmail';
341
* Sets Mailer to send message using the qmail MTA.
344
public function IsQmail() {
345
if (stristr(ini_get('sendmail_path'), 'qmail')) {
346
$this->Sendmail = '/var/qmail/bin/sendmail';
348
$this->Mailer = 'sendmail';
351
/////////////////////////////////////////////////
352
// METHODS, RECIPIENTS
353
/////////////////////////////////////////////////
356
* Adds a "To" address.
357
* @param string $address
358
* @param string $name
359
* @return boolean true on success, false if address already used
361
public function AddAddress($address, $name = '') {
362
return $this->AddAnAddress('to', $address, $name);
366
* Adds a "Cc" address.
367
* Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
368
* @param string $address
369
* @param string $name
370
* @return boolean true on success, false if address already used
372
public function AddCC($address, $name = '') {
373
return $this->AddAnAddress('cc', $address, $name);
377
* Adds a "Bcc" address.
378
* Note: this function works with the SMTP mailer on win32, not with the "mail" mailer.
379
* @param string $address
380
* @param string $name
381
* @return boolean true on success, false if address already used
383
public function AddBCC($address, $name = '') {
384
return $this->AddAnAddress('bcc', $address, $name);
388
* Adds a "Reply-to" address.
389
* @param string $address
390
* @param string $name
393
public function AddReplyTo($address, $name = '') {
394
return $this->AddAnAddress('ReplyTo', $address, $name);
398
* Adds an address to one of the recipient arrays
399
* Addresses that have been added already return false, but do not throw exceptions
400
* @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo'
401
* @param string $address The email address to send to
402
* @param string $name
403
* @return boolean true on success, false if address already used or invalid in some way
406
private function AddAnAddress($kind, $address, $name = '') {
407
if (!preg_match('/^(to|cc|bcc|ReplyTo)$/', $kind)) {
408
echo 'Invalid recipient array: ' . kind;
411
$address = trim($address);
412
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
413
if (!self::ValidateAddress($address)) {
414
$this->SetError($this->Lang('invalid_address').': '. $address);
415
if ($this->exceptions) {
416
throw new phpmailerException($this->Lang('invalid_address').': '.$address);
418
echo $this->Lang('invalid_address').': '.$address;
421
if ($kind != 'ReplyTo') {
422
if (!isset($this->all_recipients[strtolower($address)])) {
423
array_push($this->$kind, array($address, $name));
424
$this->all_recipients[strtolower($address)] = true;
428
if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
429
$this->ReplyTo[strtolower($address)] = array($address, $name);
437
* Set the From and FromName properties
438
* @param string $address
439
* @param string $name
442
public function SetFrom($address, $name = '') {
443
$address = trim($address);
444
$name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
445
if (!self::ValidateAddress($address)) {
446
$this->SetError($this->Lang('invalid_address').': '. $address);
447
if ($this->exceptions) {
448
throw new phpmailerException($this->Lang('invalid_address').': '.$address);
450
echo $this->Lang('invalid_address').': '.$address;
453
$this->From = $address;
454
$this->FromName = $name;
459
* Check that a string looks roughly like an email address should
460
* Static so it can be used without instantiation
461
* Tries to use PHP built-in validator in the filter extension (from PHP 5.2), falls back to a reasonably competent regex validator
462
* Conforms approximately to RFC2822
463
* @link http://www.hexillion.com/samples/#Regex Original pattern found here
464
* @param string $address The email address to check
469
public static function ValidateAddress($address) {
470
if (function_exists('filter_var')) { //Introduced in PHP 5.2
471
if(filter_var($address, FILTER_VALIDATE_EMAIL) === FALSE) {
477
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);
481
/////////////////////////////////////////////////
482
// METHODS, MAIL SENDING
483
/////////////////////////////////////////////////
486
* Creates message and assigns Mailer. If the message is
487
* not sent successfully then it returns false. Use the ErrorInfo
488
* variable to view description of the error.
491
public function Send() {
493
if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
494
throw new phpmailerException($this->Lang('provide_address'), self::STOP_CRITICAL);
497
// Set whether the message is multipart/alternative
498
if(!empty($this->AltBody)) {
499
$this->ContentType = 'multipart/alternative';
502
$this->error_count = 0; // reset errors
503
$this->SetMessageType();
504
$header = $this->CreateHeader();
505
$body = $this->CreateBody();
507
if (empty($this->Body)) {
508
throw new phpmailerException($this->Lang('empty_message'), self::STOP_CRITICAL);
511
// Choose the mailer and send through it
512
switch($this->Mailer) {
514
return $this->SendmailSend($header, $body);
516
return $this->SmtpSend($header, $body);
519
return $this->MailSend($header, $body);
522
} catch (phpmailerException $e) {
523
$this->SetError($e->getMessage());
524
if ($this->exceptions) {
527
echo $e->getMessage()."\n";
533
* Sends mail using the $Sendmail program.
534
* @param string $header The message headers
535
* @param string $body The message body
539
protected function SendmailSend($header, $body) {
540
if ($this->Sender != '') {
541
$sendmail = sprintf("%s -oi -f %s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
543
$sendmail = sprintf("%s -oi -t", escapeshellcmd($this->Sendmail));
545
if(!@$mail = popen($sendmail, 'w')) {
546
throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
548
fputs($mail, $header);
550
$result = pclose($mail);
552
throw new phpmailerException($this->Lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
558
* Sends mail using the PHP mail() function.
559
* @param string $header The message headers
560
* @param string $body The message body
564
protected function MailSend($header, $body) {
566
foreach($this->to as $t) {
567
$toArr[] = $this->AddrFormat($t);
569
$to = implode(', ', $toArr);
571
$params = sprintf("-oi -f %s", $this->Sender);
572
if ($this->Sender != '' && strlen(ini_get('safe_mode'))< 1) {
573
$old_from = ini_get('sendmail_from');
574
ini_set('sendmail_from', $this->Sender);
575
if ($this->SingleTo === true && count($toArr) > 1) {
576
foreach ($toArr as $key => $val) {
577
$rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
580
$rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
583
if ($this->SingleTo === true && count($toArr) > 1) {
584
foreach ($toArr as $key => $val) {
585
$rt = @mail($val, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header, $params);
588
$rt = @mail($to, $this->EncodeHeader($this->SecureHeader($this->Subject)), $body, $header);
591
if (isset($old_from)) {
592
ini_set('sendmail_from', $old_from);
595
throw new phpmailerException($this->Lang('instantiate'), self::STOP_CRITICAL);
601
* Sends mail via SMTP using PhpSMTP
602
* Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
603
* @param string $header The message headers
604
* @param string $body The message body
609
protected function SmtpSend($header, $body) {
610
require_once $this->PluginDir . 'class.smtp.php';
613
if(!$this->SmtpConnect()) {
614
throw new phpmailerException($this->Lang('smtp_connect_failed'), self::STOP_CRITICAL);
616
$smtp_from = ($this->Sender == '') ? $this->From : $this->Sender;
617
if(!$this->smtp->Mail($smtp_from)) {
618
throw new phpmailerException($this->Lang('from_failed') . $smtp_from, self::STOP_CRITICAL);
621
// Attempt to send attach all recipients
622
foreach($this->to as $to) {
623
if (!$this->smtp->Recipient($to[0])) {
624
$bad_rcpt[] = $to[0];
627
foreach($this->cc as $cc) {
628
if (!$this->smtp->Recipient($cc[0])) {
629
$bad_rcpt[] = $cc[0];
632
foreach($this->bcc as $bcc) {
633
if (!$this->smtp->Recipient($bcc[0])) {
634
$bad_rcpt[] = $bcc[0];
637
if (count($bad_rcpt) > 0 ) { //Create error message for any bad addresses
638
$badaddresses = implode(', ', $bad_rcpt);
639
throw new phpmailerException($this->Lang('recipients_failed') . $badaddresses);
641
if(!$this->smtp->Data($header . $body)) {
642
throw new phpmailerException($this->Lang('data_not_accepted'), self::STOP_CRITICAL);
644
if($this->SMTPKeepAlive == true) {
645
$this->smtp->Reset();
651
* Initiates a connection to an SMTP server.
652
* Returns false if the operation failed.
657
public function SmtpConnect() {
658
if(is_null($this->smtp)) {
659
$this->smtp = new SMTP();
662
$this->smtp->do_debug = $this->SMTPDebug;
663
$hosts = explode(';', $this->Host);
665
$connection = $this->smtp->Connected();
667
// Retry while there is no connection
669
while($index < count($hosts) && !$connection) {
671
if (preg_match('/^(.+):([0-9]+)$/', $hosts[$index], $hostinfo)) {
672
$host = $hostinfo[1];
673
$port = $hostinfo[2];
675
$host = $hosts[$index];
679
$tls = ($this->SMTPSecure == 'tls');
680
$ssl = ($this->SMTPSecure == 'ssl');
682
if ($this->smtp->Connect(($ssl ? 'ssl://':'').$host, $port, $this->Timeout)) {
684
$hello = ($this->Helo != '' ? $this->Helo : $this->ServerHostname());
685
$this->smtp->Hello($hello);
688
if (!$this->smtp->StartTLS()) {
689
throw new phpmailerException($this->Lang('tls'));
692
//We must resend HELO after tls negotiation
693
$this->smtp->Hello($hello);
697
if ($this->SMTPAuth) {
698
if (!$this->smtp->Authenticate($this->Username, $this->Password)) {
699
throw new phpmailerException($this->Lang('authenticate'));
705
throw new phpmailerException($this->Lang('connect_host'));
708
} catch (phpmailerException $e) {
709
$this->smtp->Reset();
716
* Closes the active SMTP session if one exists.
719
public function SmtpClose() {
720
if(!is_null($this->smtp)) {
721
if($this->smtp->Connected()) {
723
$this->smtp->Close();
729
* Sets the language for all class error messages.
730
* Returns false if it cannot load the language file. The default language is English.
731
* @param string $langcode ISO 639-1 2-character language code (e.g. Portuguese: "br")
732
* @param string $lang_path Path to the language file directory
735
function SetLanguage($langcode = 'en', $lang_path = 'language/') {
736
//Define full set of translatable strings
737
$PHPMAILER_LANG = array(
738
'provide_address' => 'You must provide at least one recipient email address.',
739
'mailer_not_supported' => ' mailer is not supported.',
740
'execute' => 'Could not execute: ',
741
'instantiate' => 'Could not instantiate mail function.',
742
'authenticate' => 'SMTP Error: Could not authenticate.',
743
'from_failed' => 'The following From address failed: ',
744
'recipients_failed' => 'SMTP Error: The following recipients failed: ',
745
'data_not_accepted' => 'SMTP Error: Data not accepted.',
746
'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
747
'file_access' => 'Could not access file: ',
748
'file_open' => 'File Error: Could not open file: ',
749
'encoding' => 'Unknown encoding: ',
750
'signing' => 'Signing Error: ',
751
'smtp_error' => 'SMTP server error: ',
752
'empty_message' => 'Message body empty',
753
'invalid_address' => 'Invalid address',
754
'variable_set' => 'Cannot set or reset variable: '
756
//Overwrite language-specific strings. This way we'll never have missing translations - no more "language string failed to load"!
758
if ($langcode != 'en') { //There is no English translation file
759
$l = @include $lang_path.'phpmailer.lang-'.$langcode.'.php';
761
$this->language = $PHPMAILER_LANG;
762
return ($l == true); //Returns false if language not found
766
* Return the current array of language strings
769
public function GetTranslations() {
770
return $this->language;
773
/////////////////////////////////////////////////
774
// METHODS, MESSAGE CREATION
775
/////////////////////////////////////////////////
778
* Creates recipient headers.
782
public function AddrAppend($type, $addr) {
783
$addr_str = $type . ': ';
784
$addresses = array();
785
foreach ($addr as $a) {
786
$addresses[] = $this->AddrFormat($a);
788
$addr_str .= implode(', ', $addresses);
789
$addr_str .= $this->LE;
795
* Formats an address correctly.
799
public function AddrFormat($addr) {
800
if (empty($addr[1])) {
801
return $this->SecureHeader($addr[0]);
803
return $this->EncodeHeader($this->SecureHeader($addr[1]), 'phrase') . " <" . $this->SecureHeader($addr[0]) . ">";
808
* Wraps message for use with mailers that do not
809
* automatically perform wrapping and for quoted-printable.
810
* Original written by philippe.
811
* @param string $message The message to wrap
812
* @param integer $length The line length to wrap to
813
* @param boolean $qp_mode Whether to run in Quoted-Printable mode
817
public function WrapText($message, $length, $qp_mode = false) {
818
$soft_break = ($qp_mode) ? sprintf(" =%s", $this->LE) : $this->LE;
819
// If utf-8 encoding is used, we will need to make sure we don't
820
// split multibyte characters when we wrap
821
$is_utf8 = (strtolower($this->CharSet) == "utf-8");
823
$message = $this->FixEOL($message);
824
if (substr($message, -1) == $this->LE) {
825
$message = substr($message, 0, -1);
828
$line = explode($this->LE, $message);
830
for ($i=0 ;$i < count($line); $i++) {
831
$line_part = explode(' ', $line[$i]);
833
for ($e = 0; $e<count($line_part); $e++) {
834
$word = $line_part[$e];
835
if ($qp_mode and (strlen($word) > $length)) {
836
$space_left = $length - strlen($buf) - 1;
838
if ($space_left > 20) {
841
$len = $this->UTF8CharBoundary($word, $len);
842
} elseif (substr($word, $len - 1, 1) == "=") {
844
} elseif (substr($word, $len - 2, 1) == "=") {
847
$part = substr($word, 0, $len);
848
$word = substr($word, $len);
850
$message .= $buf . sprintf("=%s", $this->LE);
852
$message .= $buf . $soft_break;
856
while (strlen($word) > 0) {
859
$len = $this->UTF8CharBoundary($word, $len);
860
} elseif (substr($word, $len - 1, 1) == "=") {
862
} elseif (substr($word, $len - 2, 1) == "=") {
865
$part = substr($word, 0, $len);
866
$word = substr($word, $len);
868
if (strlen($word) > 0) {
869
$message .= $part . sprintf("=%s", $this->LE);
876
$buf .= ($e == 0) ? $word : (' ' . $word);
878
if (strlen($buf) > $length and $buf_o != '') {
879
$message .= $buf_o . $soft_break;
884
$message .= $buf . $this->LE;
891
* Finds last character boundary prior to maxLength in a utf-8
892
* quoted (printable) encoded string.
893
* Original written by Colin Brown.
895
* @param string $encodedText utf-8 QP text
896
* @param int $maxLength find last character boundary prior to this length
899
public function UTF8CharBoundary($encodedText, $maxLength) {
900
$foundSplitPos = false;
902
while (!$foundSplitPos) {
903
$lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
904
$encodedCharPos = strpos($lastChunk, "=");
905
if ($encodedCharPos !== false) {
906
// Found start of encoded character byte within $lookBack block.
907
// Check the encoded byte value (the 2 chars after the '=')
908
$hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
910
if ($dec < 128) { // Single byte character.
911
// If the encoded char was found at pos 0, it will fit
912
// otherwise reduce maxLength to start of the encoded char
913
$maxLength = ($encodedCharPos == 0) ? $maxLength :
914
$maxLength - ($lookBack - $encodedCharPos);
915
$foundSplitPos = true;
916
} elseif ($dec >= 192) { // First byte of a multi byte character
917
// Reduce maxLength to split at start of character
918
$maxLength = $maxLength - ($lookBack - $encodedCharPos);
919
$foundSplitPos = true;
920
} elseif ($dec < 192) { // Middle byte of a multi byte character, look further back
924
// No encoded character found
925
$foundSplitPos = true;
933
* Set the body wrapping.
937
public function SetWordWrap() {
938
if($this->WordWrap < 1) {
942
switch($this->message_type) {
944
case 'alt_attachments':
945
$this->AltBody = $this->WrapText($this->AltBody, $this->WordWrap);
948
$this->Body = $this->WrapText($this->Body, $this->WordWrap);
954
* Assembles message header.
956
* @return string The assembled header
958
public function CreateHeader() {
961
// Set the boundaries
962
$uniq_id = md5(uniqid(time()));
963
$this->boundary[1] = 'b1_' . $uniq_id;
964
$this->boundary[2] = 'b2_' . $uniq_id;
966
$result .= $this->HeaderLine('Date', self::RFCDate());
967
if($this->Sender == '') {
968
$result .= $this->HeaderLine('Return-Path', trim($this->From));
970
$result .= $this->HeaderLine('Return-Path', trim($this->Sender));
973
// To be created automatically by mail()
974
if($this->Mailer != 'mail') {
975
if(count($this->to) > 0) {
976
$result .= $this->AddrAppend('To', $this->to);
977
} elseif (count($this->cc) == 0) {
978
$result .= $this->HeaderLine('To', 'undisclosed-recipients:;');
983
$from[0][0] = trim($this->From);
984
$from[0][1] = $this->FromName;
985
$result .= $this->AddrAppend('From', $from);
987
// sendmail and mail() extract Cc from the header before sending
988
if(count($this->cc) > 0) {
989
$result .= $this->AddrAppend('Cc', $this->cc);
992
// sendmail and mail() extract Bcc from the header before sending
993
if((($this->Mailer == 'sendmail') || ($this->Mailer == 'mail')) && (count($this->bcc) > 0)) {
994
$result .= $this->AddrAppend('Bcc', $this->bcc);
997
if(count($this->ReplyTo) > 0) {
998
$result .= $this->AddrAppend('Reply-to', $this->ReplyTo);
1001
// mail() sets the subject itself
1002
if($this->Mailer != 'mail') {
1003
$result .= $this->HeaderLine('Subject', $this->EncodeHeader($this->SecureHeader($this->Subject)));
1006
if($this->MessageID != '') {
1007
$result .= $this->HeaderLine('Message-ID',$this->MessageID);
1009
$result .= sprintf("Message-ID: <%s@%s>%s", $uniq_id, $this->ServerHostname(), $this->LE);
1011
$result .= $this->HeaderLine('X-Priority', $this->Priority);
1012
$result .= $this->HeaderLine('X-Mailer', 'PHPMailer '.$this->Version.' (phpmailer.codeworxtech.com)');
1014
if($this->ConfirmReadingTo != '') {
1015
$result .= $this->HeaderLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
1018
// Add custom headers
1019
for($index = 0; $index < count($this->CustomHeader); $index++) {
1020
$result .= $this->HeaderLine(trim($this->CustomHeader[$index][0]), $this->EncodeHeader(trim($this->CustomHeader[$index][1])));
1022
if (!$this->sign_key_file) {
1023
$result .= $this->HeaderLine('MIME-Version', '1.0');
1024
$result .= $this->GetMailMIME();
1031
* Returns the message MIME.
1035
public function GetMailMIME() {
1037
switch($this->message_type) {
1039
$result .= $this->HeaderLine('Content-Transfer-Encoding', $this->Encoding);
1040
$result .= sprintf("Content-Type: %s; charset=\"%s\"", $this->ContentType, $this->CharSet);
1043
case 'alt_attachments':
1044
if($this->InlineImageExists()){
1045
$result .= sprintf("Content-Type: %s;%s\ttype=\"text/html\";%s\tboundary=\"%s\"%s", 'multipart/related', $this->LE, $this->LE, $this->boundary[1], $this->LE);
1047
$result .= $this->HeaderLine('Content-Type', 'multipart/mixed;');
1048
$result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
1052
$result .= $this->HeaderLine('Content-Type', 'multipart/alternative;');
1053
$result .= $this->TextLine("\tboundary=\"" . $this->boundary[1] . '"');
1057
if($this->Mailer != 'mail') {
1058
$result .= $this->LE.$this->LE;
1065
* Assembles the message body. Returns an empty string on failure.
1067
* @return string The assembled message body
1069
public function CreateBody() {
1072
if ($this->sign_key_file) {
1073
$body .= $this->GetMailMIME();
1076
$this->SetWordWrap();
1078
switch($this->message_type) {
1080
$body .= $this->GetBoundary($this->boundary[1], '', 'text/plain', '');
1081
$body .= $this->EncodeString($this->AltBody, $this->Encoding);
1082
$body .= $this->LE.$this->LE;
1083
$body .= $this->GetBoundary($this->boundary[1], '', 'text/html', '');
1084
$body .= $this->EncodeString($this->Body, $this->Encoding);
1085
$body .= $this->LE.$this->LE;
1086
$body .= $this->EndBoundary($this->boundary[1]);
1089
$body .= $this->EncodeString($this->Body, $this->Encoding);
1092
$body .= $this->GetBoundary($this->boundary[1], '', '', '');
1093
$body .= $this->EncodeString($this->Body, $this->Encoding);
1095
$body .= $this->AttachAll();
1097
case 'alt_attachments':
1098
$body .= sprintf("--%s%s", $this->boundary[1], $this->LE);
1099
$body .= sprintf("Content-Type: %s;%s" . "\tboundary=\"%s\"%s", 'multipart/alternative', $this->LE, $this->boundary[2], $this->LE.$this->LE);
1100
$body .= $this->GetBoundary($this->boundary[2], '', 'text/plain', '') . $this->LE; // Create text body
1101
$body .= $this->EncodeString($this->AltBody, $this->Encoding);
1102
$body .= $this->LE.$this->LE;
1103
$body .= $this->GetBoundary($this->boundary[2], '', 'text/html', '') . $this->LE; // Create the HTML body
1104
$body .= $this->EncodeString($this->Body, $this->Encoding);
1105
$body .= $this->LE.$this->LE;
1106
$body .= $this->EndBoundary($this->boundary[2]);
1107
$body .= $this->AttachAll();
1111
if ($this->IsError()) {
1113
} elseif ($this->sign_key_file) {
1115
$file = tempnam('', 'mail');
1116
file_put_contents($file, $body); //TODO check this worked
1117
$signed = tempnam("", "signed");
1118
if (@openssl_pkcs7_sign($file, $signed, "file://".$this->sign_cert_file, array("file://".$this->sign_key_file, $this->sign_key_pass), NULL)) {
1121
$body = file_get_contents($signed);
1125
throw new phpmailerException($this->Lang("signing").openssl_error_string());
1127
} catch (phpmailerException $e) {
1129
if ($this->exceptions) {
1139
* Returns the start of a message boundary.
1142
private function GetBoundary($boundary, $charSet, $contentType, $encoding) {
1144
if($charSet == '') {
1145
$charSet = $this->CharSet;
1147
if($contentType == '') {
1148
$contentType = $this->ContentType;
1150
if($encoding == '') {
1151
$encoding = $this->Encoding;
1153
$result .= $this->TextLine('--' . $boundary);
1154
$result .= sprintf("Content-Type: %s; charset = \"%s\"", $contentType, $charSet);
1155
$result .= $this->LE;
1156
$result .= $this->HeaderLine('Content-Transfer-Encoding', $encoding);
1157
$result .= $this->LE;
1163
* Returns the end of a message boundary.
1166
private function EndBoundary($boundary) {
1167
return $this->LE . '--' . $boundary . '--' . $this->LE;
1171
* Sets the message type.
1175
private function SetMessageType() {
1176
if(count($this->attachment) < 1 && strlen($this->AltBody) < 1) {
1177
$this->message_type = 'plain';
1179
if(count($this->attachment) > 0) {
1180
$this->message_type = 'attachments';
1182
if(strlen($this->AltBody) > 0 && count($this->attachment) < 1) {
1183
$this->message_type = 'alt';
1185
if(strlen($this->AltBody) > 0 && count($this->attachment) > 0) {
1186
$this->message_type = 'alt_attachments';
1192
* Returns a formatted header line.
1196
public function HeaderLine($name, $value) {
1197
return $name . ': ' . $value . $this->LE;
1201
* Returns a formatted mail line.
1205
public function TextLine($value) {
1206
return $value . $this->LE;
1209
/////////////////////////////////////////////////
1210
// CLASS METHODS, ATTACHMENTS
1211
/////////////////////////////////////////////////
1214
* Adds an attachment from a path on the filesystem.
1215
* Returns false if the file could not be found
1217
* @param string $path Path to the attachment.
1218
* @param string $name Overrides the attachment name.
1219
* @param string $encoding File encoding (see $Encoding).
1220
* @param string $type File extension (MIME) type.
1223
public function AddAttachment($path, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
1225
if ( !@is_file($path) ) {
1226
throw new phpmailerException($this->Lang('file_access') . $path, self::STOP_CONTINUE);
1228
$filename = basename($path);
1229
if ( $name == '' ) {
1233
$this->attachment[] = array(
1239
5 => false, // isStringAttachment
1244
} catch (phpmailerException $e) {
1245
$this->SetError($e->getMessage());
1246
if ($this->exceptions) {
1249
echo $e->getMessage()."\n";
1250
if ( $e->getCode() == self::STOP_CRITICAL ) {
1258
* Return the current array of attachments
1261
public function GetAttachments() {
1262
return $this->attachment;
1266
* Attaches all fs, string, and binary attachments to the message.
1267
* Returns an empty string on failure.
1271
private function AttachAll() {
1272
// Return text of body
1277
// Add all attachments
1278
foreach ($this->attachment as $attachment) {
1279
// Check for string attachment
1280
$bString = $attachment[5];
1282
$string = $attachment[0];
1284
$path = $attachment[0];
1287
if (in_array($attachment[0], $incl)) { continue; }
1288
$filename = $attachment[1];
1289
$name = $attachment[2];
1290
$encoding = $attachment[3];
1291
$type = $attachment[4];
1292
$disposition = $attachment[6];
1293
$cid = $attachment[7];
1294
$incl[] = $attachment[0];
1295
if ( $disposition == 'inline' && isset($cidUniq[$cid]) ) { continue; }
1296
$cidUniq[$cid] = true;
1298
$mime[] = sprintf("--%s%s", $this->boundary[1], $this->LE);
1299
$mime[] = sprintf("Content-Type: %s; name=\"%s\"%s", $type, $this->EncodeHeader($this->SecureHeader($name)), $this->LE);
1300
$mime[] = sprintf("Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
1302
if($disposition == 'inline') {
1303
$mime[] = sprintf("Content-ID: <%s>%s", $cid, $this->LE);
1306
$mime[] = sprintf("Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->EncodeHeader($this->SecureHeader($name)), $this->LE.$this->LE);
1308
// Encode as string attachment
1310
$mime[] = $this->EncodeString($string, $encoding);
1311
if($this->IsError()) {
1314
$mime[] = $this->LE.$this->LE;
1316
$mime[] = $this->EncodeFile($path, $encoding);
1317
if($this->IsError()) {
1320
$mime[] = $this->LE.$this->LE;
1324
$mime[] = sprintf("--%s--%s", $this->boundary[1], $this->LE);
1326
return join('', $mime);
1330
* Encodes attachment in requested format.
1331
* Returns an empty string on failure.
1332
* @param string $path The full path to the file
1333
* @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
1338
private function EncodeFile($path, $encoding = 'base64') {
1340
if (!is_readable($path)) {
1341
throw new phpmailerException($this->Lang('file_open') . $path, self::STOP_CONTINUE);
1343
if (function_exists('get_magic_quotes')) {
1344
function get_magic_quotes() {
1348
if (PHP_VERSION < 6) {
1349
$magic_quotes = get_magic_quotes_runtime();
1350
set_magic_quotes_runtime(0);
1352
$file_buffer = file_get_contents($path);
1353
$file_buffer = $this->EncodeString($file_buffer, $encoding);
1354
if (PHP_VERSION < 6) { set_magic_quotes_runtime($magic_quotes); }
1355
return $file_buffer;
1356
} catch (Exception $e) {
1357
$this->SetError($e->getMessage());
1363
* Encodes string to requested format.
1364
* Returns an empty string on failure.
1365
* @param string $str The text to encode
1366
* @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
1370
public function EncodeString ($str, $encoding = 'base64') {
1372
switch(strtolower($encoding)) {
1374
$encoded = chunk_split(base64_encode($str), 76, $this->LE);
1378
$encoded = $this->FixEOL($str);
1379
//Make sure it ends with a line break
1380
if (substr($encoded, -(strlen($this->LE))) != $this->LE)
1381
$encoded .= $this->LE;
1386
case 'quoted-printable':
1387
$encoded = $this->EncodeQP($str);
1390
$this->SetError($this->Lang('encoding') . $encoding);
1397
* Encode a header string to best (shortest) of Q, B, quoted or none.
1401
public function EncodeHeader($str, $position = 'text') {
1404
switch (strtolower($position)) {
1406
if (!preg_match('/[\200-\377]/', $str)) {
1407
// Can't use addslashes as we don't know what value has magic_quotes_sybase
1408
$encoded = addcslashes($str, "\0..\37\177\\\"");
1409
if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
1412
return ("\"$encoded\"");
1415
$x = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
1418
$x = preg_match_all('/[()"]/', $str, $matches);
1422
$x += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
1430
$maxlen = 75 - 7 - strlen($this->CharSet);
1431
// Try to select the encoding which should produce the shortest output
1432
if (strlen($str)/3 < $x) {
1434
if (function_exists('mb_strlen') && $this->HasMultiBytes($str)) {
1435
// Use a custom function which correctly encodes and wraps long
1436
// multibyte strings without breaking lines within a character
1437
$encoded = $this->Base64EncodeWrapMB($str);
1439
$encoded = base64_encode($str);
1440
$maxlen -= $maxlen % 4;
1441
$encoded = trim(chunk_split($encoded, $maxlen, "\n"));
1445
$encoded = $this->EncodeQ($str, $position);
1446
$encoded = $this->WrapText($encoded, $maxlen, true);
1447
$encoded = str_replace('='.$this->LE, "\n", trim($encoded));
1450
$encoded = preg_replace('/^(.*)$/m', " =?".$this->CharSet."?$encoding?\\1?=", $encoded);
1451
$encoded = trim(str_replace("\n", $this->LE, $encoded));
1457
* Checks if a string contains multibyte characters.
1459
* @param string $str multi-byte text to wrap encode
1462
public function HasMultiBytes($str) {
1463
if (function_exists('mb_strlen')) {
1464
return (strlen($str) > mb_strlen($str, $this->CharSet));
1465
} else { // Assume no multibytes (we can't handle without mbstring functions anyway)
1471
* Correctly encodes and wraps long multibyte strings for mail headers
1472
* without breaking lines within a character.
1473
* Adapted from a function by paravoid at http://uk.php.net/manual/en/function.mb-encode-mimeheader.php
1475
* @param string $str multi-byte text to wrap encode
1478
public function Base64EncodeWrapMB($str) {
1479
$start = "=?".$this->CharSet."?B?";
1483
$mb_length = mb_strlen($str, $this->CharSet);
1484
// Each line must have length <= 75, including $start and $end
1485
$length = 75 - strlen($start) - strlen($end);
1486
// Average multi-byte ratio
1487
$ratio = $mb_length / strlen($str);
1488
// Base64 has a 4:3 ratio
1489
$offset = $avgLength = floor($length * $ratio * .75);
1491
for ($i = 0; $i < $mb_length; $i += $offset) {
1495
$offset = $avgLength - $lookBack;
1496
$chunk = mb_substr($str, $i, $offset, $this->CharSet);
1497
$chunk = base64_encode($chunk);
1500
while (strlen($chunk) > $length);
1502
$encoded .= $chunk . $this->LE;
1505
// Chomp the last linefeed
1506
$encoded = substr($encoded, 0, -strlen($this->LE));
1511
* Encode string to quoted-printable.
1512
* Only uses standard PHP, slow, but will always work
1514
* @param string $string the text to encode
1515
* @param integer $line_max Number of chars allowed on a line before wrapping
1518
public function EncodeQPphp( $input = '', $line_max = 76, $space_conv = false) {
1519
$hex = array('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F');
1520
$lines = preg_split('/(?:\r\n|\r|\n)/', $input);
1524
while( list(, $line) = each($lines) ) {
1525
$linlen = strlen($line);
1527
for($i = 0; $i < $linlen; $i++) {
1528
$c = substr( $line, $i, 1 );
1530
if ( ( $i == 0 ) && ( $dec == 46 ) ) { // convert first point in the line into =2E
1534
if ( $i == ( $linlen - 1 ) ) { // convert space at eol only
1536
} else if ( $space_conv ) {
1539
} elseif ( ($dec == 61) || ($dec < 32 ) || ($dec > 126) ) { // always encode "\t", which is *not* required
1540
$h2 = floor($dec/16);
1541
$h1 = floor($dec%16);
1542
$c = $escape.$hex[$h2].$hex[$h1];
1544
if ( (strlen($newline) + strlen($c)) >= $line_max ) { // CRLF is not counted
1545
$output .= $newline.$escape.$eol; // soft line break; " =\r\n" is okay
1547
// check if newline first character will be point or not
1554
$output .= $newline.$eol;
1560
* Encode string to RFC2045 (6.7) quoted-printable format
1561
* Uses a PHP5 stream filter to do the encoding about 64x faster than the old version
1562
* Also results in same content as you started with after decoding
1563
* @see EncodeQPphp()
1565
* @param string $string the text to encode
1566
* @param integer $line_max Number of chars allowed on a line before wrapping
1567
* @param boolean $space_conv Dummy param for compatibility with existing EncodeQP function
1569
* @author Marcus Bointon
1571
public function EncodeQP($string, $line_max = 76, $space_conv = false) {
1572
if (function_exists('quoted_printable_encode')) { //Use native function if it's available (>= PHP5.3)
1573
return quoted_printable_encode($string);
1575
$filters = stream_get_filters();
1576
if (!in_array('convert.*', $filters)) { //Got convert stream filter?
1577
return $this->EncodeQPphp($string, $line_max, $space_conv); //Fall back to old implementation
1579
$fp = fopen('php://temp/', 'r+');
1580
$string = preg_replace('/\r\n?/', $this->LE, $string); //Normalise line breaks
1581
$params = array('line-length' => $line_max, 'line-break-chars' => $this->LE);
1582
$s = stream_filter_append($fp, 'convert.quoted-printable-encode', STREAM_FILTER_READ, $params);
1583
fputs($fp, $string);
1585
$out = stream_get_contents($fp);
1586
stream_filter_remove($s);
1587
$out = preg_replace('/^\./m', '=2E', $out); //Encode . if it is first char on a line, workaround for bug in Exchange
1593
* Encode string to q encoding.
1594
* @link http://tools.ietf.org/html/rfc2047
1595
* @param string $str the text to encode
1596
* @param string $position Where the text is going to be used, see the RFC for what that means
1600
public function EncodeQ ($str, $position = 'text') {
1601
// There should not be any EOL in the string
1602
$encoded = preg_replace('/[\r\n]*/', '', $str);
1604
switch (strtolower($position)) {
1606
$encoded = preg_replace("/([^A-Za-z0-9!*+\/ -])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
1609
$encoded = preg_replace("/([\(\)\"])/e", "'='.sprintf('%02X', ord('\\1'))", $encoded);
1612
// Replace every high ascii, control =, ? and _ characters
1613
//TODO using /e (equivalent to eval()) is probably not a good idea
1614
$encoded = preg_replace('/([\000-\011\013\014\016-\037\075\077\137\177-\377])/e',
1615
"'='.sprintf('%02X', ord('\\1'))", $encoded);
1619
// Replace every spaces to _ (more readable than =20)
1620
$encoded = str_replace(' ', '_', $encoded);
1626
* Adds a string or binary attachment (non-filesystem) to the list.
1627
* This method can be used to attach ascii or binary data,
1628
* such as a BLOB record from a database.
1629
* @param string $string String attachment data.
1630
* @param string $filename Name of the attachment.
1631
* @param string $encoding File encoding (see $Encoding).
1632
* @param string $type File extension (MIME) type.
1635
public function AddStringAttachment($string, $filename, $encoding = 'base64', $type = 'application/octet-stream') {
1636
// Append to $attachment array
1637
$this->attachment[] = array(
1643
5 => true, // isStringAttachment
1650
* Adds an embedded attachment. This can include images, sounds, and
1651
* just about any other document. Make sure to set the $type to an
1652
* image type. For JPEG images use "image/jpeg" and for GIF images
1654
* @param string $path Path to the attachment.
1655
* @param string $cid Content ID of the attachment. Use this to identify
1656
* the Id for accessing the image in an HTML form.
1657
* @param string $name Overrides the attachment name.
1658
* @param string $encoding File encoding (see $Encoding).
1659
* @param string $type File extension (MIME) type.
1662
public function AddEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = 'application/octet-stream') {
1664
if ( !@is_file($path) ) {
1665
$this->SetError($this->Lang('file_access') . $path);
1669
$filename = basename($path);
1670
if ( $name == '' ) {
1674
// Append to $attachment array
1675
$this->attachment[] = array(
1681
5 => false, // isStringAttachment
1690
* Returns true if an inline attachment is present.
1694
public function InlineImageExists() {
1695
foreach($this->attachment as $attachment) {
1696
if ($attachment[6] == 'inline') {
1703
/////////////////////////////////////////////////
1704
// CLASS METHODS, MESSAGE RESET
1705
/////////////////////////////////////////////////
1708
* Clears all recipients assigned in the TO array. Returns void.
1711
public function ClearAddresses() {
1712
foreach($this->to as $to) {
1713
unset($this->all_recipients[strtolower($to[0])]);
1715
$this->to = array();
1719
* Clears all recipients assigned in the CC array. Returns void.
1722
public function ClearCCs() {
1723
foreach($this->cc as $cc) {
1724
unset($this->all_recipients[strtolower($cc[0])]);
1726
$this->cc = array();
1730
* Clears all recipients assigned in the BCC array. Returns void.
1733
public function ClearBCCs() {
1734
foreach($this->bcc as $bcc) {
1735
unset($this->all_recipients[strtolower($bcc[0])]);
1737
$this->bcc = array();
1741
* Clears all recipients assigned in the ReplyTo array. Returns void.
1744
public function ClearReplyTos() {
1745
$this->ReplyTo = array();
1749
* Clears all recipients assigned in the TO, CC and BCC
1750
* array. Returns void.
1753
public function ClearAllRecipients() {
1754
$this->to = array();
1755
$this->cc = array();
1756
$this->bcc = array();
1757
$this->all_recipients = array();
1761
* Clears all previously set filesystem, string, and binary
1762
* attachments. Returns void.
1765
public function ClearAttachments() {
1766
$this->attachment = array();
1770
* Clears all custom headers. Returns void.
1773
public function ClearCustomHeaders() {
1774
$this->CustomHeader = array();
1777
/////////////////////////////////////////////////
1778
// CLASS METHODS, MISCELLANEOUS
1779
/////////////////////////////////////////////////
1782
* Adds the error message to the error container.
1786
protected function SetError($msg) {
1787
$this->error_count++;
1788
if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
1789
$lasterror = $this->smtp->getError();
1790
if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
1791
$msg .= '<p>' . $this->Lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n";
1794
$this->ErrorInfo = $msg;
1798
* Returns the proper RFC 822 formatted date.
1803
public static function RFCDate() {
1805
$tzs = ($tz < 0) ? '-' : '+';
1807
$tz = (int)($tz/3600)*100 + ($tz%3600)/60;
1808
$result = sprintf("%s %s%04d", date('D, j M Y H:i:s'), $tzs, $tz);
1814
* Returns the server hostname or 'localhost.localdomain' if unknown.
1818
private function ServerHostname() {
1819
if (!empty($this->Hostname)) {
1820
$result = $this->Hostname;
1821
} elseif (isset($_SERVER['SERVER_NAME'])) {
1822
$result = $_SERVER['SERVER_NAME'];
1824
$result = 'localhost.localdomain';
1831
* Returns a message in the appropriate language.
1835
private function Lang($key) {
1836
if(count($this->language) < 1) {
1837
$this->SetLanguage('en'); // set the default language
1840
if(isset($this->language[$key])) {
1841
return $this->language[$key];
1843
return 'Language string failed to load: ' . $key;
1848
* Returns true if an error occurred.
1852
public function IsError() {
1853
return ($this->error_count > 0);
1857
* Changes every end of line from CR or LF to CRLF.
1861
private function FixEOL($str) {
1862
$str = str_replace("\r\n", "\n", $str);
1863
$str = str_replace("\r", "\n", $str);
1864
$str = str_replace("\n", $this->LE, $str);
1869
* Adds a custom header.
1873
public function AddCustomHeader($custom_header) {
1874
$this->CustomHeader[] = explode(':', $custom_header, 2);
1878
* Evaluates the message and returns modifications for inline images and backgrounds
1882
public function MsgHTML($message, $basedir = '') {
1883
preg_match_all("/(src|background)=\"(.*)\"/Ui", $message, $images);
1884
if(isset($images[2])) {
1885
foreach($images[2] as $i => $url) {
1886
// do not change urls for absolute images (thanks to corvuscorax)
1887
if (!preg_match('#^[A-z]+://#',$url)) {
1888
$filename = basename($url);
1889
$directory = dirname($url);
1890
($directory == '.')?$directory='':'';
1891
$cid = 'cid:' . md5($filename);
1892
$ext = pathinfo($filename, PATHINFO_EXTENSION);
1893
$mimeType = self::_mime_types($ext);
1894
if ( strlen($basedir) > 1 && substr($basedir,-1) != '/') { $basedir .= '/'; }
1895
if ( strlen($directory) > 1 && substr($directory,-1) != '/') { $directory .= '/'; }
1896
if ( $this->AddEmbeddedImage($basedir.$directory.$filename, md5($filename), $filename, 'base64',$mimeType) ) {
1897
$message = preg_replace("/".$images[1][$i]."=\"".preg_quote($url, '/')."\"/Ui", $images[1][$i]."=\"".$cid."\"", $message);
1902
$this->IsHTML(true);
1903
$this->Body = $message;
1904
$textMsg = trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/s','',$message)));
1905
if (!empty($textMsg) && empty($this->AltBody)) {
1906
$this->AltBody = html_entity_decode($textMsg);
1908
if (empty($this->AltBody)) {
1909
$this->AltBody = 'To view this email message, open it in a program that understands HTML!' . "\n\n";
1914
* Gets the MIME type of the embedded or inline image
1915
* @param string File extension
1917
* @return string MIME type of ext
1920
public static function _mime_types($ext = '') {
1922
'hqx' => 'application/mac-binhex40',
1923
'cpt' => 'application/mac-compactpro',
1924
'doc' => 'application/msword',
1925
'bin' => 'application/macbinary',
1926
'dms' => 'application/octet-stream',
1927
'lha' => 'application/octet-stream',
1928
'lzh' => 'application/octet-stream',
1929
'exe' => 'application/octet-stream',
1930
'class' => 'application/octet-stream',
1931
'psd' => 'application/octet-stream',
1932
'so' => 'application/octet-stream',
1933
'sea' => 'application/octet-stream',
1934
'dll' => 'application/octet-stream',
1935
'oda' => 'application/oda',
1936
'pdf' => 'application/pdf',
1937
'ai' => 'application/postscript',
1938
'eps' => 'application/postscript',
1939
'ps' => 'application/postscript',
1940
'smi' => 'application/smil',
1941
'smil' => 'application/smil',
1942
'mif' => 'application/vnd.mif',
1943
'xls' => 'application/vnd.ms-excel',
1944
'ppt' => 'application/vnd.ms-powerpoint',
1945
'wbxml' => 'application/vnd.wap.wbxml',
1946
'wmlc' => 'application/vnd.wap.wmlc',
1947
'dcr' => 'application/x-director',
1948
'dir' => 'application/x-director',
1949
'dxr' => 'application/x-director',
1950
'dvi' => 'application/x-dvi',
1951
'gtar' => 'application/x-gtar',
1952
'php' => 'application/x-httpd-php',
1953
'php4' => 'application/x-httpd-php',
1954
'php3' => 'application/x-httpd-php',
1955
'phtml' => 'application/x-httpd-php',
1956
'phps' => 'application/x-httpd-php-source',
1957
'js' => 'application/x-javascript',
1958
'swf' => 'application/x-shockwave-flash',
1959
'sit' => 'application/x-stuffit',
1960
'tar' => 'application/x-tar',
1961
'tgz' => 'application/x-tar',
1962
'xhtml' => 'application/xhtml+xml',
1963
'xht' => 'application/xhtml+xml',
1964
'zip' => 'application/zip',
1965
'mid' => 'audio/midi',
1966
'midi' => 'audio/midi',
1967
'mpga' => 'audio/mpeg',
1968
'mp2' => 'audio/mpeg',
1969
'mp3' => 'audio/mpeg',
1970
'aif' => 'audio/x-aiff',
1971
'aiff' => 'audio/x-aiff',
1972
'aifc' => 'audio/x-aiff',
1973
'ram' => 'audio/x-pn-realaudio',
1974
'rm' => 'audio/x-pn-realaudio',
1975
'rpm' => 'audio/x-pn-realaudio-plugin',
1976
'ra' => 'audio/x-realaudio',
1977
'rv' => 'video/vnd.rn-realvideo',
1978
'wav' => 'audio/x-wav',
1979
'bmp' => 'image/bmp',
1980
'gif' => 'image/gif',
1981
'jpeg' => 'image/jpeg',
1982
'jpg' => 'image/jpeg',
1983
'jpe' => 'image/jpeg',
1984
'png' => 'image/png',
1985
'tiff' => 'image/tiff',
1986
'tif' => 'image/tiff',
1987
'css' => 'text/css',
1988
'html' => 'text/html',
1989
'htm' => 'text/html',
1990
'shtml' => 'text/html',
1991
'txt' => 'text/plain',
1992
'text' => 'text/plain',
1993
'log' => 'text/plain',
1994
'rtx' => 'text/richtext',
1995
'rtf' => 'text/rtf',
1996
'xml' => 'text/xml',
1997
'xsl' => 'text/xml',
1998
'mpeg' => 'video/mpeg',
1999
'mpg' => 'video/mpeg',
2000
'mpe' => 'video/mpeg',
2001
'qt' => 'video/quicktime',
2002
'mov' => 'video/quicktime',
2003
'avi' => 'video/x-msvideo',
2004
'movie' => 'video/x-sgi-movie',
2005
'doc' => 'application/msword',
2006
'word' => 'application/msword',
2007
'xl' => 'application/excel',
2008
'eml' => 'message/rfc822'
2010
return (!isset($mimes[strtolower($ext)])) ? 'application/octet-stream' : $mimes[strtolower($ext)];
2014
* Set (or reset) Class Objects (variables)
2017
* $page->set('X-Priority', '3');
2020
* @param string $name Parameter Name
2021
* @param mixed $value Parameter Value
2022
* NOTE: will not work with arrays, there are no arrays to set/reset
2023
* @todo Should this not be using __set() magic function?
2025
public function set($name, $value = '') {
2027
if (isset($this->$name) ) {
2028
$this->$name = $value;
2030
throw new phpmailerException($this->Lang('variable_set') . $name, self::STOP_CRITICAL);
2032
} catch (Exception $e) {
2033
$this->SetError($e->getMessage());
2034
if ($e->getCode() == self::STOP_CRITICAL) {
2042
* Strips newlines to prevent header injection.
2044
* @param string $str String
2047
public function SecureHeader($str) {
2048
$str = str_replace("\r", '', $str);
2049
$str = str_replace("\n", '', $str);
2054
* Set the private key file and password to sign the message.
2057
* @param string $key_filename Parameter File Name
2058
* @param string $key_pass Password for private key
2060
public function Sign($cert_filename, $key_filename, $key_pass) {
2061
$this->sign_cert_file = $cert_filename;
2062
$this->sign_key_file = $key_filename;
2063
$this->sign_key_pass = $key_pass;
2067
class phpmailerException extends Exception {
2068
public function errorMessage() {
2069
$errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
b'\\ No newline at end of file'