38 if (version_compare(PHP_VERSION,
'5.0.0',
'<') ) {
39 exit(
"Sorry, PHPMailer will only run on PHP version 5 or greater!\n");
87 public $From =
'root@localhost';
539 if ( ini_get(
'safe_mode') || !($this->UseSendmailOptions) ) {
552 switch ($this->Debugoutput) {
558 echo htmlentities(preg_replace(
'/[\r\n]+/',
'', $str), ENT_QUOTES, $this->CharSet).
"<br>\n";
579 if ($this->Mailer ==
'smtp') {
591 $this->ContentType =
'text/html';
593 $this->ContentType =
'text/plain';
602 $this->Mailer =
'smtp';
610 $this->Mailer =
'mail';
618 if (!stristr(ini_get(
'sendmail_path'),
'sendmail')) {
619 $this->Sendmail =
'/var/qmail/bin/sendmail';
621 $this->Mailer =
'sendmail';
629 if (stristr(ini_get(
'sendmail_path'),
'qmail')) {
630 $this->Sendmail =
'/var/qmail/bin/sendmail';
632 $this->Mailer =
'sendmail';
656 public function AddCC($address, $name =
'') {
667 public function AddBCC($address, $name =
'') {
678 return $this->
AddAnAddress(
'Reply-To', $address, $name);
692 if (!preg_match(
'/^(to|cc|bcc|Reply-To)$/', $kind)) {
693 $this->
SetError($this->
Lang(
'Invalid recipient array').
': '.$kind);
694 if ($this->exceptions) {
697 if ($this->SMTPDebug) {
698 $this->
edebug($this->
Lang(
'Invalid recipient array').
': '.$kind);
702 $address = trim($address);
703 $name = trim(preg_replace(
'/[\r\n]+/',
'', $name));
705 $this->
SetError($this->
Lang(
'invalid_address').
': '. $address);
706 if ($this->exceptions) {
709 if ($this->SMTPDebug) {
710 $this->
edebug($this->
Lang(
'invalid_address').
': '.$address);
714 if ($kind !=
'Reply-To') {
715 if (!isset($this->all_recipients[strtolower($address)])) {
716 array_push($this->$kind, array($address, $name));
717 $this->all_recipients[strtolower($address)] =
true;
721 if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
722 $this->ReplyTo[strtolower($address)] = array($address, $name);
737 public function SetFrom($address, $name =
'', $auto =
true) {
738 $address = trim($address);
739 $name = trim(preg_replace(
'/[\r\n]+/',
'', $name));
741 $this->
SetError($this->
Lang(
'invalid_address').
': '. $address);
742 if ($this->exceptions) {
745 if ($this->SMTPDebug) {
746 $this->
edebug($this->
Lang(
'invalid_address').
': '.$address);
750 $this->From = $address;
751 $this->FromName = $name;
753 if (empty($this->Sender)) {
754 $this->Sender = $address;
774 if (defined(
'PCRE_VERSION')) {
775 if (version_compare(PCRE_VERSION,
'8.0') >= 0) {
776 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);
779 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);
784 return (strlen($address) >= 3 and strpos($address,
'@') >= 1 and strpos($address,
'@') != strlen($address) - 1);
801 if(!$this->
PreSend())
return false;
804 $this->mailHeader =
'';
806 if ($this->exceptions) {
820 $this->mailHeader =
"";
821 if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
826 if(!empty($this->AltBody)) {
827 $this->ContentType =
'multipart/alternative';
830 $this->error_count = 0;
833 if (!$this->AllowEmpty and empty($this->Body)) {
842 if ($this->Mailer ==
'mail') {
843 if (count($this->to) > 0) {
844 $this->mailHeader .= $this->
AddrAppend(
"To", $this->to);
846 $this->mailHeader .= $this->
HeaderLine(
"To",
"undisclosed-recipients:;");
852 if (!empty($this->DKIM_domain) && !empty($this->DKIM_private) && !empty($this->DKIM_selector) && !empty($this->DKIM_domain) && file_exists($this->DKIM_private)) {
861 if ($this->exceptions) {
877 switch($this->Mailer) {
879 return $this->
SendmailSend($this->MIMEHeader, $this->MIMEBody);
881 return $this->
SmtpSend($this->MIMEHeader, $this->MIMEBody);
883 return $this->
MailSend($this->MIMEHeader, $this->MIMEBody);
885 return $this->
MailSend($this->MIMEHeader, $this->MIMEBody);
889 if ($this->exceptions) {
892 if ($this->SMTPDebug) {
893 $this->
edebug($e->getMessage().
"\n");
908 if ($this->Sender !=
'') {
909 $sendmail = sprintf(
"%s -oi -f%s -t", escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
911 $sendmail = sprintf(
"%s -oi -t", escapeshellcmd($this->Sendmail));
913 if ($this->SingleTo ===
true) {
914 foreach ($this->SingleToArray as $val) {
915 if(!@$mail = popen($sendmail,
'w')) {
918 fputs($mail,
"To: " . $val .
"\n");
919 fputs($mail, $header);
921 $result = pclose($mail);
923 $isSent = ($result == 0) ? 1 : 0;
924 $this->
doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
930 if(!@$mail = popen($sendmail,
'w')) {
933 fputs($mail, $header);
935 $result = pclose($mail);
937 $isSent = ($result == 0) ? 1 : 0;
938 $this->
doCallback($isSent, $this->to, $this->cc, $this->bcc, $this->Subject, $body);
956 foreach($this->to as $t) {
959 $to = implode(
', ', $toArr);
961 if (empty($this->Sender)) {
964 $params = sprintf(
"-f%s", $this->Sender);
966 if ($this->Sender !=
'' and !ini_get(
'safe_mode')) {
967 $old_from = ini_get(
'sendmail_from');
968 ini_set(
'sendmail_from', $this->Sender);
971 if ($this->SingleTo ===
true && count($toArr) > 1) {
972 foreach ($toArr as $val) {
973 $rt = $this->
mail_passthru($val, $this->Subject, $body, $header, $params);
975 $isSent = ($rt == 1) ? 1 : 0;
976 $this->
doCallback($isSent, $val, $this->cc, $this->bcc, $this->Subject, $body);
981 $isSent = ($rt == 1) ? 1 : 0;
982 $this->
doCallback($isSent,
$to, $this->cc, $this->bcc, $this->Subject, $body);
984 if (isset($old_from)) {
985 ini_set(
'sendmail_from', $old_from);
1004 require_once $this->PluginDir .
'smtp.php';
1005 $bad_rcpt = array();
1010 $smtp_from = ($this->Sender ==
'') ? $this->From : $this->Sender;
1011 if(!$this->smtp->Mail($smtp_from)) {
1012 $this->
SetError($this->
Lang(
'from_failed') . $smtp_from .
' : ' .implode(
',', $this->smtp->getError()));
1017 foreach($this->to as
$to) {
1018 if (!$this->smtp->Recipient($to[0])) {
1019 $bad_rcpt[] = $to[0];
1022 $this->
doCallback($isSent, $to[0],
'',
'', $this->Subject, $body);
1026 $this->
doCallback($isSent, $to[0],
'',
'', $this->Subject, $body);
1029 foreach($this->cc as
$cc) {
1030 if (!$this->smtp->Recipient($cc[0])) {
1031 $bad_rcpt[] = $cc[0];
1034 $this->
doCallback($isSent,
'', $cc[0],
'', $this->Subject, $body);
1038 $this->
doCallback($isSent,
'', $cc[0],
'', $this->Subject, $body);
1041 foreach($this->bcc as
$bcc) {
1042 if (!$this->smtp->Recipient($bcc[0])) {
1043 $bad_rcpt[] = $bcc[0];
1046 $this->
doCallback($isSent,
'',
'', $bcc[0], $this->Subject, $body);
1050 $this->
doCallback($isSent,
'',
'', $bcc[0], $this->Subject, $body);
1055 if (count($bad_rcpt) > 0 ) {
1056 $badaddresses = implode(
', ', $bad_rcpt);
1059 if(!$this->smtp->Data($header . $body)) {
1062 if($this->SMTPKeepAlive ==
true) {
1063 $this->smtp->Reset();
1065 $this->smtp->Quit();
1066 $this->smtp->Close();
1081 if(is_null($this->smtp)) {
1082 $this->smtp =
new SMTP;
1086 if ($this->smtp->Connected()) {
1095 $tls = ($this->SMTPSecure ==
'tls');
1096 $ssl = ($this->SMTPSecure ==
'ssl');
1097 $hosts = explode(
';', $this->Host);
1098 $lastexception = null;
1100 foreach ($hosts as $hostentry) {
1101 $hostinfo = array();
1104 if (preg_match(
'/^(.+):([0-9]+)$/', $hostentry, $hostinfo)) {
1105 $host = $hostinfo[1];
1106 $port = $hostinfo[2];
1108 if ($this->smtp->Connect(($ssl ?
'ssl://':
'').$host, $port, $this->Timeout, $options)) {
1115 $this->smtp->Hello($hello);
1118 if (!$this->smtp->StartTLS()) {
1122 $this->smtp->Hello($hello);
1124 if ($this->SMTPAuth) {
1125 if (!$this->smtp->Authenticate($this->Username, $this->Password, $this->AuthType, $this->Realm, $this->Workstation)) {
1131 $lastexception = $e;
1133 $this->smtp->Quit();
1138 $this->smtp->Close();
1140 if ($this->exceptions and !is_null($lastexception)) {
1141 throw $lastexception;
1151 if ($this->smtp !== null) {
1152 if($this->smtp->Connected()) {
1153 $this->smtp->Quit();
1154 $this->smtp->Close();
1170 'authenticate' =>
'SMTP Error: Could not authenticate.',
1171 'connect_host' =>
'SMTP Error: Could not connect to SMTP host.',
1172 'data_not_accepted' =>
'SMTP Error: Data not accepted.',
1173 'empty_message' =>
'Message body empty',
1174 'encoding' =>
'Unknown encoding: ',
1175 'execute' =>
'Could not execute: ',
1176 'file_access' =>
'Could not access file: ',
1177 'file_open' =>
'File Error: Could not open file: ',
1178 'from_failed' =>
'The following From address failed: ',
1179 'instantiate' =>
'Could not instantiate mail function.',
1180 'invalid_address' =>
'Invalid address',
1181 'mailer_not_supported' =>
' mailer is not supported.',
1182 'provide_address' =>
'You must provide at least one recipient email address.',
1183 'recipients_failed' =>
'SMTP Error: The following recipients failed: ',
1184 'signing' =>
'Signing Error: ',
1185 'smtp_connect_failed' =>
'SMTP Connect() failed.',
1186 'smtp_error' =>
'SMTP server error: ',
1187 'variable_set' =>
'Cannot set or reset variable: '
1191 if ($langcode !=
'en') {
1192 $l = @include $lang_path.
'phpmailer.lang-'.$langcode.
'.php';
1195 return ($l ==
true);
1218 $addr_str = $type .
': ';
1219 $addresses = array();
1220 foreach ($addr as $a) {
1223 $addr_str .= implode(
', ', $addresses);
1236 if (empty($addr[1])) {
1253 public function WrapText($message, $length, $qp_mode =
false) {
1254 $soft_break = ($qp_mode) ? sprintf(
" =%s", $this->LE) :
$this->LE;
1257 $is_utf8 = (strtolower($this->CharSet) ==
"utf-8");
1258 $lelen = strlen($this->LE);
1259 $crlflen = strlen(self::CRLF);
1261 $message = $this->
FixEOL($message);
1262 if (substr($message, -$lelen) == $this->LE) {
1263 $message = substr($message, 0, -$lelen);
1266 $line = explode($this->LE, $message);
1268 for ($i = 0 ;$i < count($line); $i++) {
1269 $line_part = explode(
' ', $line[$i]);
1271 for ($e = 0; $e<count($line_part); $e++) {
1272 $word = $line_part[$e];
1273 if ($qp_mode and (strlen($word) > $length)) {
1274 $space_left = $length - strlen($buf) - $crlflen;
1276 if ($space_left > 20) {
1280 } elseif (substr($word, $len - 1, 1) ==
"=") {
1282 } elseif (substr($word, $len - 2, 1) ==
"=") {
1285 $part = substr($word, 0, $len);
1286 $word = substr($word, $len);
1287 $buf .=
' ' . $part;
1288 $message .= $buf . sprintf(
"=%s", self::CRLF);
1290 $message .= $buf . $soft_break;
1294 while (strlen($word) > 0) {
1301 } elseif (substr($word, $len - 1, 1) ==
"=") {
1303 } elseif (substr($word, $len - 2, 1) ==
"=") {
1306 $part = substr($word, 0, $len);
1307 $word = substr($word, $len);
1309 if (strlen($word) > 0) {
1310 $message .= $part . sprintf(
"=%s", self::CRLF);
1317 $buf .= ($e == 0) ? $word : (
' ' . $word);
1319 if (strlen($buf) > $length and $buf_o !=
'') {
1320 $message .= $buf_o . $soft_break;
1341 $foundSplitPos =
false;
1343 while (!$foundSplitPos) {
1344 $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
1345 $encodedCharPos = strpos($lastChunk,
"=");
1346 if ($encodedCharPos !==
false) {
1349 $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
1350 $dec = hexdec($hex);
1354 $maxLength = ($encodedCharPos == 0) ? $maxLength :
1355 $maxLength - ($lookBack - $encodedCharPos);
1356 $foundSplitPos =
true;
1357 } elseif ($dec >= 192) {
1359 $maxLength = $maxLength - ($lookBack - $encodedCharPos);
1360 $foundSplitPos =
true;
1361 } elseif ($dec < 192) {
1366 $foundSplitPos =
true;
1379 if($this->WordWrap < 1) {
1383 switch($this->message_type) {
1387 case 'alt_inline_attach':
1388 $this->AltBody = $this->
WrapText($this->AltBody, $this->WordWrap);
1391 $this->Body = $this->
WrapText($this->Body, $this->WordWrap);
1405 $uniq_id = md5(uniqid(time()));
1406 $this->boundary[1] =
'b1_' . $uniq_id;
1407 $this->boundary[2] =
'b2_' . $uniq_id;
1408 $this->boundary[3] =
'b3_' . $uniq_id;
1410 if ($this->MessageDate ==
'') {
1411 $result .= $this->
HeaderLine(
'Date', self::RFCDate());
1413 $result .= $this->
HeaderLine(
'Date', $this->MessageDate);
1416 if ($this->ReturnPath) {
1417 $result .= $this->
HeaderLine(
'Return-Path',
'<'.trim($this->ReturnPath).
'>');
1418 } elseif ($this->Sender ==
'') {
1419 $result .= $this->
HeaderLine(
'Return-Path',
'<'.trim($this->From).
'>');
1421 $result .= $this->
HeaderLine(
'Return-Path',
'<'.trim($this->Sender).
'>');
1425 if($this->Mailer !=
'mail') {
1426 if ($this->SingleTo ===
true) {
1427 foreach($this->to as $t) {
1428 $this->SingleToArray[] = $this->
AddrFormat($t);
1431 if(count($this->to) > 0) {
1432 $result .= $this->
AddrAppend(
'To', $this->to);
1433 } elseif (count($this->cc) == 0) {
1434 $result .= $this->
HeaderLine(
'To',
'undisclosed-recipients:;');
1440 $from[0][0] = trim($this->From);
1445 if(count($this->cc) > 0) {
1446 $result .= $this->
AddrAppend(
'Cc', $this->cc);
1450 if((($this->Mailer ==
'sendmail') || ($this->Mailer ==
'mail')) && (count($this->bcc) > 0)) {
1451 $result .= $this->
AddrAppend(
'Bcc', $this->bcc);
1454 if(count($this->ReplyTo) > 0) {
1455 $result .= $this->
AddrAppend(
'Reply-To', $this->ReplyTo);
1459 if($this->Mailer !=
'mail') {
1463 if($this->MessageID !=
'') {
1464 $result .= $this->
HeaderLine(
'Message-ID', $this->MessageID);
1466 $result .= sprintf(
"Message-ID: <%s@%s>%s", $uniq_id, $this->
ServerHostname(), $this->LE);
1468 $result .= $this->
HeaderLine(
'X-Priority', $this->Priority);
1469 if ($this->XMailer ==
'') {
1470 $result .= $this->
HeaderLine(
'X-Mailer',
'PHPMailer '.$this->Version.
' (https://github.com/PHPMailer/PHPMailer/)');
1472 $myXmailer = trim($this->XMailer);
1474 $result .= $this->
HeaderLine(
'X-Mailer', $myXmailer);
1478 if($this->ConfirmReadingTo !=
'') {
1479 $result .= $this->
HeaderLine(
'Disposition-Notification-To',
'<' . trim($this->ConfirmReadingTo) .
'>');
1483 for($index = 0; $index < count($this->CustomHeader); $index++) {
1484 $result .= $this->
HeaderLine(trim($this->CustomHeader[$index][0]), $this->
EncodeHeader(trim($this->CustomHeader[$index][1])));
1486 if (!$this->sign_key_file) {
1487 $result .= $this->
HeaderLine(
'MIME-Version',
'1.0');
1501 switch($this->message_type) {
1503 $result .= $this->
HeaderLine(
'Content-Type',
'multipart/related;');
1504 $result .= $this->
TextLine(
"\tboundary=\"" . $this->boundary[1].
'"');
1507 case 'inline_attach':
1509 case 'alt_inline_attach':
1510 $result .= $this->
HeaderLine(
'Content-Type',
'multipart/mixed;');
1511 $result .= $this->
TextLine(
"\tboundary=\"" . $this->boundary[1].
'"');
1515 $result .= $this->
HeaderLine(
'Content-Type',
'multipart/alternative;');
1516 $result .= $this->
TextLine(
"\tboundary=\"" . $this->boundary[1].
'"');
1520 $result .= $this->
TextLine(
'Content-Type: '.$this->ContentType.
'; charset='.$this->CharSet);
1524 if ($this->Encoding !=
'7bit') {
1525 $result .= $this->
HeaderLine(
'Content-Transfer-Encoding', $this->Encoding);
1528 if($this->Mailer !=
'mail') {
1541 return $this->MIMEHeader . $this->mailHeader . self::CRLF .
$this->MIMEBody;
1554 if ($this->sign_key_file) {
1560 switch($this->message_type) {
1562 $body .= $this->
GetBoundary($this->boundary[1],
'',
'',
'');
1563 $body .= $this->
EncodeString($this->Body, $this->Encoding);
1564 $body .= $this->LE.$this->LE;
1565 $body .= $this->
AttachAll(
'inline', $this->boundary[1]);
1568 $body .= $this->
GetBoundary($this->boundary[1],
'',
'',
'');
1569 $body .= $this->
EncodeString($this->Body, $this->Encoding);
1570 $body .= $this->LE.$this->LE;
1571 $body .= $this->
AttachAll(
'attachment', $this->boundary[1]);
1573 case 'inline_attach':
1574 $body .= $this->
TextLine(
'--' . $this->boundary[1]);
1575 $body .= $this->
HeaderLine(
'Content-Type',
'multipart/related;');
1576 $body .= $this->
TextLine(
"\tboundary=\"" . $this->boundary[2].
'"');
1578 $body .= $this->
GetBoundary($this->boundary[2],
'',
'',
'');
1579 $body .= $this->
EncodeString($this->Body, $this->Encoding);
1580 $body .= $this->LE.$this->LE;
1581 $body .= $this->
AttachAll(
'inline', $this->boundary[2]);
1583 $body .= $this->
AttachAll(
'attachment', $this->boundary[1]);
1586 $body .= $this->
GetBoundary($this->boundary[1],
'',
'text/plain',
'');
1587 $body .= $this->
EncodeString($this->AltBody, $this->Encoding);
1588 $body .= $this->LE.$this->LE;
1589 $body .= $this->
GetBoundary($this->boundary[1],
'',
'text/html',
'');
1590 $body .= $this->
EncodeString($this->Body, $this->Encoding);
1591 $body .= $this->LE.$this->LE;
1592 if(!empty($this->Ical)) {
1593 $body .= $this->
GetBoundary($this->boundary[1],
'',
'text/calendar; method=REQUEST',
'');
1594 $body .= $this->
EncodeString($this->Ical, $this->Encoding);
1595 $body .= $this->LE.$this->LE;
1600 $body .= $this->
GetBoundary($this->boundary[1],
'',
'text/plain',
'');
1601 $body .= $this->
EncodeString($this->AltBody, $this->Encoding);
1602 $body .= $this->LE.$this->LE;
1603 $body .= $this->
TextLine(
'--' . $this->boundary[1]);
1604 $body .= $this->
HeaderLine(
'Content-Type',
'multipart/related;');
1605 $body .= $this->
TextLine(
"\tboundary=\"" . $this->boundary[2].
'"');
1607 $body .= $this->
GetBoundary($this->boundary[2],
'',
'text/html',
'');
1608 $body .= $this->
EncodeString($this->Body, $this->Encoding);
1609 $body .= $this->LE.$this->LE;
1610 $body .= $this->
AttachAll(
'inline', $this->boundary[2]);
1615 $body .= $this->
TextLine(
'--' . $this->boundary[1]);
1616 $body .= $this->
HeaderLine(
'Content-Type',
'multipart/alternative;');
1617 $body .= $this->
TextLine(
"\tboundary=\"" . $this->boundary[2].
'"');
1619 $body .= $this->
GetBoundary($this->boundary[2],
'',
'text/plain',
'');
1620 $body .= $this->
EncodeString($this->AltBody, $this->Encoding);
1621 $body .= $this->LE.$this->LE;
1622 $body .= $this->
GetBoundary($this->boundary[2],
'',
'text/html',
'');
1623 $body .= $this->
EncodeString($this->Body, $this->Encoding);
1624 $body .= $this->LE.$this->LE;
1627 $body .= $this->
AttachAll(
'attachment', $this->boundary[1]);
1629 case 'alt_inline_attach':
1630 $body .= $this->
TextLine(
'--' . $this->boundary[1]);
1631 $body .= $this->
HeaderLine(
'Content-Type',
'multipart/alternative;');
1632 $body .= $this->
TextLine(
"\tboundary=\"" . $this->boundary[2].
'"');
1634 $body .= $this->
GetBoundary($this->boundary[2],
'',
'text/plain',
'');
1635 $body .= $this->
EncodeString($this->AltBody, $this->Encoding);
1636 $body .= $this->LE.$this->LE;
1637 $body .= $this->
TextLine(
'--' . $this->boundary[2]);
1638 $body .= $this->
HeaderLine(
'Content-Type',
'multipart/related;');
1639 $body .= $this->
TextLine(
"\tboundary=\"" . $this->boundary[3].
'"');
1641 $body .= $this->
GetBoundary($this->boundary[3],
'',
'text/html',
'');
1642 $body .= $this->
EncodeString($this->Body, $this->Encoding);
1643 $body .= $this->LE.$this->LE;
1644 $body .= $this->
AttachAll(
'inline', $this->boundary[3]);
1648 $body .= $this->
AttachAll(
'attachment', $this->boundary[1]);
1652 $body .= $this->
EncodeString($this->Body, $this->Encoding);
1658 } elseif ($this->sign_key_file) {
1660 if (!defined(
'PKCS7_TEXT')) {
1663 $file = tempnam(sys_get_temp_dir(),
'mail');
1664 file_put_contents($file, $body);
1665 $signed = tempnam(sys_get_temp_dir(),
'signed');
1666 if (@openssl_pkcs7_sign($file, $signed,
'file://'.realpath($this->sign_cert_file), array(
'file://'.realpath($this->sign_key_file), $this->sign_key_pass), null)) {
1668 $body = file_get_contents($signed);
1677 if ($this->exceptions) {
1696 if($charSet ==
'') {
1699 if($contentType ==
'') {
1702 if($encoding ==
'') {
1706 $result .= sprintf(
"Content-Type: %s; charset=%s", $contentType, $charSet);
1708 $result .= $this->
HeaderLine(
'Content-Transfer-Encoding', $encoding);
1730 $this->message_type = array();
1734 $this->message_type = implode(
"_", $this->message_type);
1735 if($this->message_type ==
"") $this->message_type =
"plain";
1746 return $name .
': ' . $value .
$this->LE;
1774 public function AddAttachment($path, $name =
'', $encoding =
'base64', $type =
'') {
1776 if ( !@is_file($path) ) {
1785 $filename = basename($path);
1786 if ( $name ==
'' ) {
1790 $this->attachment[] = array(
1803 if ($this->exceptions) {
1806 if ($this->SMTPDebug) {
1807 $this->
edebug($e->getMessage().
"\n");
1839 if($attachment[6] == $disposition_type) {
1843 $bString = $attachment[5];
1845 $string = $attachment[0];
1847 $path = $attachment[0];
1850 $inclhash = md5(serialize($attachment));
1851 if (in_array($inclhash, $incl)) {
continue; }
1852 $incl[] = $inclhash;
1853 $filename = $attachment[1];
1854 $name = $attachment[2];
1855 $encoding = $attachment[3];
1856 $type = $attachment[4];
1857 $disposition = $attachment[6];
1858 $cid = $attachment[7];
1859 if ( $disposition ==
'inline' && isset($cidUniq[$cid]) ) {
continue; }
1860 $cidUniq[$cid] =
true;
1862 $mime[] = sprintf(
"--%s%s",
$boundary, $this->LE);
1863 $mime[] = sprintf(
"Content-Type: %s; name=\"%s\"%s", $type, $this->
EncodeHeader($this->
SecureHeader($name)), $this->LE);
1864 $mime[] = sprintf(
"Content-Transfer-Encoding: %s%s", $encoding, $this->LE);
1866 if($disposition ==
'inline') {
1867 $mime[] = sprintf(
"Content-ID: <%s>%s", $cid, $this->LE);
1872 if (preg_match(
'/[ \(\)<>@,;:\\"\/\[\]\?=]/', $name)) {
1873 $mime[] = sprintf(
"Content-Disposition: %s; filename=\"%s\"%s", $disposition, $this->
EncodeHeader($this->
SecureHeader($name)), $this->LE.$this->LE);
1875 $mime[] = sprintf(
"Content-Disposition: %s; filename=%s%s", $disposition, $this->
EncodeHeader($this->
SecureHeader($name)), $this->LE.$this->LE);
1884 $mime[] = $this->LE.$this->LE;
1886 $mime[] = $this->
EncodeFile($path, $encoding);
1890 $mime[] = $this->LE.$this->LE;
1895 $mime[] = sprintf(
"--%s--%s",
$boundary, $this->LE);
1897 return implode(
"", $mime);
1912 if (!is_readable($path)) {
1915 $magic_quotes = get_magic_quotes_runtime();
1916 if ($magic_quotes) {
1917 if (version_compare(PHP_VERSION,
'5.3.0',
'<')) {
1918 set_magic_quotes_runtime(0);
1920 ini_set(
'magic_quotes_runtime', 0);
1923 $file_buffer = file_get_contents($path);
1924 $file_buffer = $this->
EncodeString($file_buffer, $encoding);
1925 if ($magic_quotes) {
1926 if (version_compare(PHP_VERSION,
'5.3.0',
'<')) {
1927 set_magic_quotes_runtime($magic_quotes);
1929 ini_set(
'magic_quotes_runtime', $magic_quotes);
1932 return $file_buffer;
1933 }
catch (Exception $e) {
1949 switch(strtolower($encoding)) {
1951 $encoded = chunk_split(base64_encode($str), 76, $this->LE);
1955 $encoded = $this->
FixEOL($str);
1957 if (substr($encoded, -(strlen($this->LE))) != $this->LE)
1963 case 'quoted-printable':
1983 switch (strtolower($position)) {
1985 if (!preg_match(
'/[\200-\377]/', $str)) {
1987 $encoded = addcslashes($str,
"\0..\37\177\\\"");
1988 if (($str == $encoded) && !preg_match(
'/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
1991 return (
"\"$encoded\"");
1994 $x = preg_match_all(
'/[^\040\041\043-\133\135-\176]/', $str, $matches);
1997 $x = preg_match_all(
'/[()"]/', $str, $matches);
2001 $x += preg_match_all(
'/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
2009 $maxlen = 75 - 7 - strlen($this->CharSet);
2011 if ($x > strlen($str)/3) {
2013 if (function_exists(
'mb_strlen') && $this->
HasMultiBytes($str)) {
2018 $encoded = base64_encode($str);
2019 $maxlen -= $maxlen % 4;
2020 $encoded = trim(chunk_split($encoded, $maxlen,
"\n"));
2024 $encoded = $this->
EncodeQ($str, $position);
2025 $encoded = $this->
WrapText($encoded, $maxlen,
true);
2026 $encoded = str_replace(
'='.self::CRLF,
"\n", trim($encoded));
2029 $encoded = preg_replace(
'/^(.*)$/m',
" =?".$this->CharSet.
"?$encoding?\\1?=", $encoded);
2030 $encoded = trim(str_replace(
"\n", $this->LE, $encoded));
2042 if (function_exists(
'mb_strlen')) {
2043 return (strlen($str) > mb_strlen($str, $this->CharSet));
2059 $start =
"=?".$this->CharSet.
"?B?";
2066 $mb_length = mb_strlen($str, $this->CharSet);
2068 $length = 75 - strlen($start) - strlen($end);
2070 $ratio = $mb_length / strlen($str);
2072 $offset = $avgLength = floor($length * $ratio * .75);
2074 for ($i = 0; $i < $mb_length; $i += $offset) {
2078 $offset = $avgLength - $lookBack;
2079 $chunk = mb_substr($str, $i, $offset, $this->CharSet);
2080 $chunk = base64_encode($chunk);
2083 while (strlen($chunk) > $length);
2085 $encoded .= $chunk . $lf;
2089 $encoded = substr($encoded, 0, -strlen($lf));
2102 if (function_exists(
'quoted_printable_encode')) {
2103 return quoted_printable_encode($string);
2106 $string = str_replace(array(
'%20',
'%0D%0A.',
'%0D%0A',
'%'), array(
' ',
"\r\n=2E",
"\r\n",
'='), rawurlencode($string));
2107 $string = preg_replace(
'/[^\r\n]{'.($line_max - 3).
'}[^=\r\n]{2}/',
"$0=\r\n", $string);
2120 public function EncodeQPphp($string, $line_max = 76, $space_conv =
false) {
2121 return $this->
EncodeQP($string, $line_max);
2132 public function EncodeQ($str, $position =
'text') {
2135 $encoded = str_replace(array(
"\r",
"\n"),
'', $str);
2136 switch (strtolower($position)) {
2138 $pattern =
'^A-Za-z0-9!*+\/ -';
2150 $pattern =
'\075\000-\011\013\014\016-\037\077\137\177-\377' . $pattern;
2154 if (preg_match_all(
"/[{$pattern}]/", $encoded, $matches)) {
2155 foreach (array_unique($matches[0]) as $char) {
2156 $encoded = str_replace($char,
'=' . sprintf(
'%02X', ord($char)), $encoded);
2161 return str_replace(
' ',
'_', $encoded);
2181 $this->attachment[] = array(
2184 2 => basename($filename),
2205 if ( !@is_file($path) ) {
2215 $filename = basename($path);
2216 if ( $name ==
'' ) {
2221 $this->attachment[] = array(
2255 $this->attachment[] = array(
2275 if ($attachment[6] ==
'inline') {
2288 if ($attachment[6] ==
'attachment') {
2300 return !empty($this->AltBody);
2312 foreach($this->to as
$to) {
2313 unset($this->all_recipients[strtolower($to[0])]);
2315 $this->to = array();
2323 foreach($this->cc as
$cc) {
2324 unset($this->all_recipients[strtolower($cc[0])]);
2326 $this->cc = array();
2334 foreach($this->bcc as
$bcc) {
2335 unset($this->all_recipients[strtolower($bcc[0])]);
2337 $this->bcc = array();
2345 $this->ReplyTo = array();
2354 $this->to = array();
2355 $this->cc = array();
2356 $this->bcc = array();
2357 $this->all_recipients = array();
2366 $this->attachment = array();
2374 $this->CustomHeader = array();
2388 $this->error_count++;
2389 if ($this->Mailer ==
'smtp' and !is_null($this->smtp)) {
2390 $lasterror = $this->smtp->getError();
2391 if (!empty($lasterror) and array_key_exists(
'smtp_msg', $lasterror)) {
2392 $msg .=
'<p>' . $this->
Lang(
'smtp_error') . $lasterror[
'smtp_msg'] .
"</p>\n";
2395 $this->ErrorInfo = $msg;
2407 date_default_timezone_set(@date_default_timezone_get());
2408 return date(
'D, j M Y H:i:s O');
2417 if (!empty($this->Hostname)) {
2419 } elseif (isset($_SERVER[
'SERVER_NAME'])) {
2420 $result = $_SERVER[
'SERVER_NAME'];
2422 $result =
'localhost.localdomain';
2435 if(count($this->language) < 1) {
2439 if(isset($this->language[$key])) {
2440 return $this->language[$key];
2442 return 'Language string failed to load: ' . $key;
2452 return ($this->error_count > 0);
2463 $nstr = str_replace(array(
"\r\n",
"\r"),
"\n", $str);
2465 if ($this->LE !==
"\n") {
2466 $nstr = str_replace(
"\n", $this->LE, $nstr);
2480 if ($value === null) {
2482 $this->CustomHeader[] = explode(
':', $name, 2);
2484 $this->CustomHeader[] = array($name, $value);
2498 public function MsgHTML($message, $basedir =
'', $advanced =
false) {
2499 preg_match_all(
"/(src|background)=[\"'](.*)[\"']/Ui", $message, $images);
2500 if (isset($images[2])) {
2501 foreach ($images[2] as $i => $url) {
2503 if (!preg_match(
'#^[A-z]+://#', $url)) {
2504 $filename = basename($url);
2505 $directory = dirname($url);
2506 if ($directory ==
'.') {
2509 $cid = md5($url).
'@phpmailer.0';
2510 if (strlen($basedir) > 1 && substr($basedir, -1) !=
'/') {
2513 if (strlen($directory) > 1 && substr($directory, -1) !=
'/') {
2516 if ($this->
AddEmbeddedImage($basedir.$directory.$filename, $cid, $filename,
'base64', self::_mime_types(self::mb_pathinfo($filename, PATHINFO_EXTENSION)))) {
2517 $message = preg_replace(
"/".$images[1][$i].
"=[\"']".preg_quote($url,
'/').
"[\"']/Ui", $images[1][$i].
"=\"cid:".$cid.
"\"", $message);
2523 if (empty($this->AltBody)) {
2524 $this->AltBody =
'To view this email message, open it in a program that understands HTML!' .
"\n\n";
2540 if (file_exists(
'extras/class.html2text.php')) {
2541 require_once
'extras/class.html2text.php';
2544 return $h->get_text();
2546 return html_entity_decode(trim(strip_tags(preg_replace(
'/<(head|title|style|script)[^>]*>.*?<\/\\1>/si',
'', $html))), ENT_QUOTES, $this->CharSet);
2558 'xl' =>
'application/excel',
2559 'hqx' =>
'application/mac-binhex40',
2560 'cpt' =>
'application/mac-compactpro',
2561 'bin' =>
'application/macbinary',
2562 'doc' =>
'application/msword',
2563 'word' =>
'application/msword',
2564 'class' =>
'application/octet-stream',
2565 'dll' =>
'application/octet-stream',
2566 'dms' =>
'application/octet-stream',
2567 'exe' =>
'application/octet-stream',
2568 'lha' =>
'application/octet-stream',
2569 'lzh' =>
'application/octet-stream',
2570 'psd' =>
'application/octet-stream',
2571 'sea' =>
'application/octet-stream',
2572 'so' =>
'application/octet-stream',
2573 'oda' =>
'application/oda',
2574 'pdf' =>
'application/pdf',
2575 'ai' =>
'application/postscript',
2576 'eps' =>
'application/postscript',
2577 'ps' =>
'application/postscript',
2578 'smi' =>
'application/smil',
2579 'smil' =>
'application/smil',
2580 'mif' =>
'application/vnd.mif',
2581 'xls' =>
'application/vnd.ms-excel',
2582 'ppt' =>
'application/vnd.ms-powerpoint',
2583 'wbxml' =>
'application/vnd.wap.wbxml',
2584 'wmlc' =>
'application/vnd.wap.wmlc',
2585 'dcr' =>
'application/x-director',
2586 'dir' =>
'application/x-director',
2587 'dxr' =>
'application/x-director',
2588 'dvi' =>
'application/x-dvi',
2589 'gtar' =>
'application/x-gtar',
2590 'php3' =>
'application/x-httpd-php',
2591 'php4' =>
'application/x-httpd-php',
2592 'php' =>
'application/x-httpd-php',
2593 'phtml' =>
'application/x-httpd-php',
2594 'phps' =>
'application/x-httpd-php-source',
2595 'js' =>
'application/x-javascript',
2596 'swf' =>
'application/x-shockwave-flash',
2597 'sit' =>
'application/x-stuffit',
2598 'tar' =>
'application/x-tar',
2599 'tgz' =>
'application/x-tar',
2600 'xht' =>
'application/xhtml+xml',
2601 'xhtml' =>
'application/xhtml+xml',
2602 'zip' =>
'application/zip',
2603 'mid' =>
'audio/midi',
2604 'midi' =>
'audio/midi',
2605 'mp2' =>
'audio/mpeg',
2606 'mp3' =>
'audio/mpeg',
2607 'mpga' =>
'audio/mpeg',
2608 'aif' =>
'audio/x-aiff',
2609 'aifc' =>
'audio/x-aiff',
2610 'aiff' =>
'audio/x-aiff',
2611 'ram' =>
'audio/x-pn-realaudio',
2612 'rm' =>
'audio/x-pn-realaudio',
2613 'rpm' =>
'audio/x-pn-realaudio-plugin',
2614 'ra' =>
'audio/x-realaudio',
2615 'wav' =>
'audio/x-wav',
2616 'bmp' =>
'image/bmp',
2617 'gif' =>
'image/gif',
2618 'jpeg' =>
'image/jpeg',
2619 'jpe' =>
'image/jpeg',
2620 'jpg' =>
'image/jpeg',
2621 'png' =>
'image/png',
2622 'tiff' =>
'image/tiff',
2623 'tif' =>
'image/tiff',
2624 'eml' =>
'message/rfc822',
2625 'css' =>
'text/css',
2626 'html' =>
'text/html',
2627 'htm' =>
'text/html',
2628 'shtml' =>
'text/html',
2629 'log' =>
'text/plain',
2630 'text' =>
'text/plain',
2631 'txt' =>
'text/plain',
2632 'rtx' =>
'text/richtext',
2633 'rtf' =>
'text/rtf',
2634 'xml' =>
'text/xml',
2635 'xsl' =>
'text/xml',
2636 'mpeg' =>
'video/mpeg',
2637 'mpe' =>
'video/mpeg',
2638 'mpg' =>
'video/mpeg',
2639 'mov' =>
'video/quicktime',
2640 'qt' =>
'video/quicktime',
2641 'rv' =>
'video/vnd.rn-realvideo',
2642 'avi' =>
'video/x-msvideo',
2643 'movie' =>
'video/x-sgi-movie'
2645 return (!isset($mimes[strtolower($ext)])) ?
'application/octet-stream' : $mimes[strtolower($ext)];
2656 $qpos = strpos($filename,
'?');
2657 if ($qpos !==
false) {
2658 $filename = substr($filename, 0, $qpos);
2674 $ret = array(
'dirname' =>
'',
'basename' =>
'',
'extension' =>
'',
'filename' =>
'');
2676 preg_match(
'%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $m);
2677 if(array_key_exists(1, $m)) {
2678 $ret[
'dirname'] = $m[1];
2680 if(array_key_exists(2, $m)) {
2681 $ret[
'basename'] = $m[2];
2683 if(array_key_exists(5, $m)) {
2684 $ret[
'extension'] = $m[5];
2686 if(array_key_exists(3, $m)) {
2687 $ret[
'filename'] = $m[3];
2690 case PATHINFO_DIRNAME:
2692 return $ret[
'dirname'];
2694 case PATHINFO_BASENAME:
2696 return $ret[
'basename'];
2698 case PATHINFO_EXTENSION:
2700 return $ret[
'extension'];
2702 case PATHINFO_FILENAME:
2704 return $ret[
'filename'];
2725 public function set($name, $value =
'') {
2727 if (isset($this->$name) ) {
2728 $this->$name = $value;
2732 }
catch (Exception $e) {
2748 return trim(str_replace(array(
"\r",
"\n"),
'', $str));
2761 return preg_replace(
'/(\r\n|\r|\n)/ms', $breaktype, $text);
2773 public function Sign($cert_filename, $key_filename, $key_pass) {
2774 $this->sign_cert_file = $cert_filename;
2775 $this->sign_key_file = $key_filename;
2776 $this->sign_key_pass = $key_pass;
2788 for ($i = 0; $i < strlen($txt); $i++) {
2789 $ord = ord($txt[$i]);
2790 if ( ((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E)) ) {
2793 $line .=
"=".sprintf(
"%02X", $ord);
2808 if (!defined(
'PKCS7_TEXT')) {
2809 if ($this->exceptions) {
2814 $privKeyStr = file_get_contents($this->DKIM_private);
2815 if ($this->DKIM_passphrase !=
'') {
2816 $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
2818 $privKey = $privKeyStr;
2820 if (openssl_sign($s, $signature, $privKey)) {
2821 return base64_encode($signature);
2834 $s = preg_replace(
"/\r\n\s+/",
" ", $s);
2835 $lines = explode(
"\r\n", $s);
2836 foreach ($lines as $key => $line) {
2837 list($heading, $value) = explode(
":", $line, 2);
2838 $heading = strtolower($heading);
2839 $value = preg_replace(
"/\s+/",
" ", $value) ;
2840 $lines[$key] = $heading.
":".trim($value) ;
2842 $s = implode(
"\r\n", $lines);
2854 if ($body ==
'')
return "\r\n";
2856 $body = str_replace(
"\r\n",
"\n", $body);
2857 $body = str_replace(
"\n",
"\r\n", $body);
2859 while (substr($body, strlen($body) - 4, 4) ==
"\r\n\r\n") {
2860 $body = substr($body, 0, strlen($body) - 2);
2874 public function DKIM_Add($headers_line, $subject, $body) {
2875 $DKIMsignatureType =
'rsa-sha1';
2876 $DKIMcanonicalization =
'relaxed/simple';
2877 $DKIMquery =
'dns/txt';
2878 $DKIMtime = time() ;
2879 $subject_header =
"Subject: $subject";
2880 $headers = explode($this->LE, $headers_line);
2884 foreach($headers as $header) {
2885 if (strpos($header,
'From:') === 0) {
2886 $from_header = $header;
2887 $current =
'from_header';
2888 } elseif (strpos($header,
'To:') === 0) {
2889 $to_header = $header;
2890 $current =
'to_header';
2892 if($current && strpos($header,
' =?') === 0){
2893 $current .= $header;
2899 $from = str_replace(
'|',
'=7C', $this->
DKIM_QP($from_header));
2900 $to = str_replace(
'|',
'=7C', $this->
DKIM_QP($to_header));
2901 $subject = str_replace(
'|',
'=7C', $this->
DKIM_QP($subject_header)) ;
2903 $DKIMlen = strlen($body) ;
2904 $DKIMb64 = base64_encode(pack(
"H*", sha1($body))) ;
2905 $ident = ($this->DKIM_identity ==
'')?
'' :
" i=" . $this->DKIM_identity .
";";
2906 $dkimhdrs =
"DKIM-Signature: v=1; a=" . $DKIMsignatureType .
"; q=" . $DKIMquery .
"; l=" . $DKIMlen .
"; s=" . $this->DKIM_selector .
";\r\n".
2907 "\tt=" . $DKIMtime .
"; c=" . $DKIMcanonicalization .
";\r\n".
2908 "\th=From:To:Subject;\r\n".
2909 "\td=" . $this->DKIM_domain .
";" . $ident .
"\r\n".
2913 "\tbh=" . $DKIMb64 .
";\r\n".
2915 $toSign = $this->
DKIM_HeaderC($from_header .
"\r\n" . $to_header .
"\r\n" . $subject_header .
"\r\n" . $dkimhdrs);
2917 return $dkimhdrs.$signed.
"\r\n";
2931 if (!empty($this->action_function) && is_callable($this->action_function)) {
2932 $params = array($isSent,
$to,
$cc,
$bcc, $subject, $body, $from);
2933 call_user_func_array($this->action_function, $params);
2948 $errorMsg =
'<strong>' . $this->getMessage() .
"</strong><br />\n";