ll("/[{$pattern}]/", $encoded, $matches)) { // If the string contains an '=', make sure it's the first thing we replace // so as to avoid double-encoding $eqkey = array_search('=', $matches[0]); if (false !== $eqkey) { unset($matches[0][$eqkey]); array_unshift($matches[0], '='); } foreach (array_unique($matches[0]) as $char) { $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded); } } // Replace every spaces to _ (more readable than =20) return str_replace(' ', '_', $encoded); } /** * Add a string or binary attachment (non-filesystem). * This method can be used to attach ascii or binary data, * such as a BLOB record from a database. * @param string $string String attachment data. * @param string $filename Name of the attachment. * @param string $encoding File encoding (see $Encoding). * @param string $type File extension (MIME) type. * @param string $disposition Disposition to use * @return void */ public function addStringAttachment( $string, $filename, $encoding = 'base64', $type = '', $disposition = 'attachment' ) { // 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, 1 => $filename, 2 => basename($filename), 3 => $encoding, 4 => $type, 5 => true, // isStringAttachment 6 => $disposition, 7 => 0 ); } /** * Add an embedded (inline) attachment from a file. * This can include images, sounds, and just about any other document type. * These differ from 'regular' attachments in that they are intended to be * displayed inline with the message, not just attached for download. * This is used in HTML messages that embed the images * the HTML refers to using the $cid value. * Never use a user-supplied path to a file! * @param string $path Path to the attachment. * @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 MIME type. * @param string $disposition Disposition to use * @return boolean True on successfully adding an attachment */ public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline') { if (!self::isPermittedPath($path) or !@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 == '') { $name = $filename; } // Append to $attachment array $this->attachment[] = array( 0 => $path, 1 => $filename, 2 => $name, 3 => $encoding, 4 => $type, 5 => false, // isStringAttachment 6 => $disposition, 7 => $cid ); return true; } /** * 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 MIME type. * @param string $disposition Disposition to use * @return boolean True on successfully adding an attachment */ public function addStringEmbeddedImage( $string, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline' ) { // If a MIME type is not specified, try to work it out from the name if ($type == '' and !empty($name)) { $type = self::filenameToType($name); } // Append to $attachment array $this->attachment[] = array( 0 => $string, 1 => $name, 2 => $name, 3 => $encoding, 4 => $type, 5 => true, // isStringAttachment 6 => $disposition, 7 => $cid ); return true; } /** * Check if an inline attachment is present. * @access public * @return boolean */ public function inlineImageExists() { foreach ($this->attachment as $attachment) { if ($attachment[6] == 'inline') { return true; } } return false; } /** * Check if an attachment (non-inline) is present. * @return boolean */ public function attachmentExists() { foreach ($this->attachment as $attachment) { if ($attachment[6] == 'attachment') { return true; } } return false; } /** * Check if this message has an alternative body set. * @return boolean */ public function alternativeExists() { return !empty($this->AltBody); } /** * Clear queued addresses of given kind. * @access protected * @param string $kind 'to', 'cc', or 'bcc' * @return void */ public function clearQueuedAddresses($kind) { $RecipientsQueue = $this->RecipientsQueue; foreach ($RecipientsQueue as $address => $params) { if ($params[0] == $kind) { unset($this->RecipientsQueue[$address]); } } } /** * Clear all To recipients. * @return void */ public function clearAddresses() { foreach ($this->to as $to) { unset($this->all_recipients[strtolower($to[0])]); } $this->to = array(); $this->clearQueuedAddresses('to'); } /** * Clear all CC recipients. * @return void */ public function clearCCs() { foreach ($this->cc as $cc) { unset($this->all_recipients[strtolower($cc[0])]); } $this->cc = array(); $this->clearQueuedAddresses('cc'); } /** * Clear all BCC recipients. * @return void */ public function clearBCCs() { foreach ($this->bcc as $bcc) { unset($this->all_recipients[strtolower($bcc[0])]); } $this->bcc = array(); $this->clearQueuedAddresses('bcc'); } /** * Clear all ReplyTo recipients. * @return void */ public function clearReplyTos() { $this->ReplyTo = array(); $this->ReplyToQueue = array(); } /** * Clear all recipient types. * @return void */ public function clearAllRecipients() { $this->to = array(); $this->cc = array(); $this->bcc = array(); $this->all_recipients = array(); $this->RecipientsQueue = array(); } /** * Clear all filesystem, string, and binary attachments. * @return void */ public function clearAttachments() { $this->attachment = array(); } /** * Clear all custom headers. * @return void */ public function clearCustomHeaders() { $this->CustomHeader = array(); } /** * Add an error message to the error container. * @access protected * @param string $msg * @return void */ protected function setError($msg) { $this->error_count++; if ($this->Mailer == 'smtp' and !is_null($this->smtp)) { $lasterror = $this->smtp->getError(); if (!empty($lasterror['error'])) { $msg .= $this->lang('smtp_error') . $lasterror['error']; if (!empty($lasterror['detail'])) { $msg .= ' Detail: '. $lasterror['detail']; } if (!empty($lasterror['smtp_code'])) { $msg .= ' SMTP code: ' . $lasterror['smtp_code']; } if (!empty($lasterror['smtp_code_ex'])) { $msg .= ' Additional SMTP info: ' . $lasterror['smtp_code_ex']; } } } $this->ErrorInfo = $msg; } /** * Return an RFC 822 formatted date. * @access public * @return string * @static */ 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'); } /** * Get the server hostname. * Returns 'localhost.localdomain' if unknown. * @access protected * @return string */ protected function serverHostname() { $result = 'localhost.localdomain'; if (!empty($this->Hostname)) { $result = $this->Hostname; } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) { $result = $_SERVER['SERVER_NAME']; } elseif (function_exists('gethostname') && gethostname() !== false) { $result = gethostname(); } elseif (php_uname('n') !== false) { $result = php_uname('n'); } return $result; } /** * Get an error message in the current language. * @access protected * @param string $key * @return string */ protected function lang($key) { if (count($this->language) < 1) { $this->setLanguage('en'); // set the default language } if (array_key_exists($key, $this->language)) { if ($key == 'smtp_connect_failed') { //Include a link to troubleshooting docs on SMTP connection failure //this is by far the biggest cause of support questions //but it's usually not PHPMailer's fault. return $this->language[$key] . ' https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting'; } return $this->language[$key]; } else { //Return the key as a fallback return $key; } } /** * Check if an error occurred. * @access public * @return boolean True if an error did occur. */ public function isError() { return ($this->error_count > 0); } /** * Ensure consistent line endings in a string. * Changes every end of line from CRLF, CR or LF to $this->LE. * @access public * @param string $str String to fixEOL * @return string */ public function fixEOL($str) { // Normalise 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; } /** * Add a custom header. * $name value can be overloaded to contain * both header name and value (name:value) * @access public * @param string $name Custom header name * @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); } } /** * Returns all custom headers. * @return array */ public function getCustomHeaders() { return $this->CustomHeader; } /** * Create a message body from an HTML string. * Automatically inlines images and creates a plain-text version by converting the HTML, * overwriting any existing values in Body and AltBody. * Do not source $message content from user input! * $basedir is prepended when handling relative URLs, e.g. and must not be empty * will look for an image file in $basedir/images/a.png and convert it to inline. * If you don't provide a $basedir, relative paths will be left untouched (and thus probably break in email) * If you don't want to apply these transformations to your HTML, just set Body and AltBody directly. * @access public * @param string $message HTML message string * @param string $basedir Absolute path to a base directory to prepend to relative paths to images * @param boolean|callable $advanced Whether to use the internal HTML to text converter * or your own custom converter @see PHPMailer::html2text() * @return string $message The transformed message Body */ public function msgHTML($message, $basedir = '', $advanced = false) { preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images); if (array_key_exists(2, $images)) { if (strlen($basedir) > 1 && substr($basedir, -1) != '/') { // Ensure $basedir has a trailing / $basedir .= '/'; } foreach ($images[2] as $imgindex => $url) { // Convert data URIs into embedded images if (preg_match('#^data:(image[^;,]*)(;base64)?,#', $url, $match)) { $data = substr($url, strpos($url, ',')); if ($match[2]) { $data = base64_decode($data); } else { $data = rawurldecode($data); } $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 if ($this->addStringEmbeddedImage($data, $cid, 'embed' . $imgindex, 'base64', $match[1])) { $message = str_replace( $images[0][$imgindex], $images[1][$imgindex] . '="cid:' . $cid . '"', $message ); } continue; } if ( // Only process relative URLs if a basedir is provided (i.e. no absolute local paths) !empty($basedir) // Ignore URLs containing parent dir traversal (..) && (strpos($url, '..') === false) // Do not change urls that are already inline images && substr($url, 0, 4) !== 'cid:' // Do not change absolute URLs, including anonymous protocol && !preg_match('#^[a-z][a-z0-9+.-]*:?//#i', $url) ) { $filename = basename($url); $directory = dirname($url); if ($directory == '.') { $directory = ''; } $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 if (strlen($directory) > 1 && substr($directory, -1) != '/') { $directory .= '/'; } if ($this->addEmbeddedImage( $basedir . $directory . $filename, $cid, $filename, 'base64', self::_mime_types((string)self::mb_pathinfo($filename, PATHINFO_EXTENSION)) ) ) { $message = preg_replace( '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui', $images[1][$imgindex] . '="cid:' . $cid . '"', $message ); } } } } $this->isHTML(true); // 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)); if (!$this->alternativeExists()) { $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . self::CRLF . self::CRLF; } return $this->Body; } /** * Convert an HTML string into plain text. * This is used by msgHTML(). * Note - older versions of this function used a bundled advanced converter * which was been removed for license reasons in #232. * Example usage: * * // Use default conversion * $plain = $mail->html2text($html); * // Use your own custom converter * $plain = $mail->html2text($html, function($html) { * $converter = new MyHtml2text($html); * return $converter->get_text(); * }); * * @param string $html The HTML text to convert * @param boolean|callable $advanced Any boolean value to use the internal converter, * or provide your own callable for custom conversion. * @return string */ public function html2text($html, $advanced = false) { if (is_callable($advanced)) { return call_user_func($advanced, $html); } return html_entity_decode( trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))), ENT_QUOTES, $this->CharSet ); } /** * Get the MIME type for a file extension. * @param string $ext File extension * @access public * @return string MIME type of file. * @static */ public static function _mime_types($ext = '') { $mimes = array( 'xl' => 'application/excel', 'js' => 'application/javascript', 'hqx' => 'application/mac-binhex40', 'cpt' => 'application/mac-compactpro', 'bin' => 'application/macbinary', 'doc' => 'application/msword', 'word' => 'application/msword', 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', 'class' => 'application/octet-stream', 'dll' => 'application/octet-stream', 'dms' => 'application/octet-stream', 'exe' => 'application/octet-stream', 'lha' => 'application/octet-stream', 'lzh' => 'application/octet-stream', 'psd' => 'application/octet-stream', 'sea' => 'application/octet-stream', 'so' => 'application/octet-stream', 'oda' => 'application/oda', 'pdf' => 'application/pdf', 'ai' => 'application/postscript', 'eps' => 'application/postscript', 'ps' => 'application/postscript', 'smi' => 'application/smil', 'smil' => 'application/smil', 'mif' => 'application/vnd.mif', 'xls' => 'application/vnd.ms-excel', 'ppt' => 'application/vnd.ms-powerpoint', 'wbxml' => 'application/vnd.wap.wbxml', 'wmlc' => 'application/vnd.wap.wmlc', 'dcr' => 'application/x-director', 'dir' => 'application/x-director', 'dxr' => 'application/x-director', 'dvi' => 'application/x-dvi', 'gtar' => 'application/x-gtar', 'php3' => 'application/x-httpd-php', 'php4' => 'application/x-httpd-php', 'php' => 'application/x-httpd-php', 'phtml' => 'application/x-httpd-php', 'phps' => 'application/x-httpd-php-source', 'swf' => 'application/x-shockwave-flash', 'sit' => 'application/x-stuffit', 'tar' => 'application/x-tar', 'tgz' => 'application/x-tar', 'xht' => 'application/xhtml+xml', 'xhtml' => 'application/xhtml+xml', 'zip' => 'application/zip', 'mid' => 'audio/midi', 'midi' => 'audio/midi', 'mp2' => 'audio/mpeg', 'mp3' => 'audio/mpeg', 'mpga' => 'audio/mpeg', 'aif' => 'audio/x-aiff', 'aifc' => 'audio/x-aiff', 'aiff' => 'audio/x-aiff', 'ram' => 'audio/x-pn-realaudio', 'rm' => 'audio/x-pn-realaudio', 'rpm' => 'audio/x-pn-realaudio-plugin', 'ra' => 'audio/x-realaudio', 'wav' => 'audio/x-wav', 'bmp' => 'image/bmp', 'gif' => 'image/gif', 'jpeg' => 'image/jpeg', 'jpe' => 'image/jpeg', 'jpg' => 'image/jpeg', 'png' => 'image/png', 'tiff' => 'image/tiff', 'tif' => 'image/tiff', 'eml' => 'message/rfc822', 'css' => 'text/css', 'html' => 'text/html', 'htm' => 'text/html', 'shtml' => 'text/html', 'log' => 'text/plain', 'text' => 'text/plain', 'txt' => 'text/plain', 'rtx' => 'text/richtext', 'rtf' => 'text/rtf', 'vcf' => 'text/vcard', 'vcard' => 'text/vcard', 'xml' => 'text/xml', 'xsl' => 'text/xml', 'mpeg' => 'video/mpeg', 'mpe' => 'video/mpeg', 'mpg' => 'video/mpeg', 'mov' => 'video/quicktime', 'qt' => 'video/quicktime', 'rv' => 'video/vnd.rn-realvideo', 'avi' => 'video/x-msvideo', 'movie' => 'video/x-sgi-movie' ); if (array_key_exists(strtolower($ext), $mimes)) { return $mimes[strtolower($ext)]; } return 'application/octet-stream'; } /** * Map a file name to a MIME type. * Defaults to 'application/octet-stream', i.e.. arbitrary binary data. * @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 (false !== $qpos) { $filename = substr($filename, 0, $qpos); } $pathinfo = self::mb_pathinfo($filename); return self::_mime_types($pathinfo['extension']); } /** * Multi-byte-safe pathinfo replacement. * 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' => ''); $pathinfo = array(); if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) { if (array_key_exists(1, $pathinfo)) { $ret['dirname'] = $pathinfo[1]; } if (array_key_exists(2, $pathinfo)) { $ret['basename'] = $pathinfo[2]; } if (array_key_exists(5, $pathinfo)) { $ret['extension'] = $pathinfo[5]; } if (array_key_exists(3, $pathinfo)) { $ret['filename'] = $pathinfo[3]; } } switch ($options) { case PATHINFO_DIRNAME: case 'dirname': return $ret['dirname']; case PATHINFO_BASENAME: case 'basename': return $ret['basename']; case PATHINFO_EXTENSION: case 'extension': return $ret['extension']; case PATHINFO_FILENAME: case 'filename': return $ret['filename']; default: return $ret; } } /** * Set or reset instance properties. * You should avoid this function - it's more verbose, less efficient, more error-prone and * harder to debug than setting properties directly. * Usage Example: * `$mail->set('SMTPSecure', 'tls');` * is the same as: * `$mail->SMTPSecure = 'tls';` * @access public * @param string $name The property name to set * @param mixed $value The value to set the property to * @return boolean * @TODO Should this not be using the __set() magic function? */ public function set($name, $value = '') { if (property_exists($this, $name)) { $this->$name = $value; return true; } else { $this->setError($this->lang('variable_set') . $name); return false; } } /** * Strip newlines to prevent header injection. * @access public * @param string $str * @return string */ public function secureHeader($str) { return trim(str_replace(array("\r", "\n"), '', $str)); } /** * Normalize line breaks in a string. * Converts 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 public and private key files and password for S/MIME signing. * @access public * @param string $cert_filename * @param string $key_filename * @param string $key_pass Password for private key * @param string $extracerts_filename Optional path to chain certificate */ public function sign($cert_filename, $key_filename, $key_pass, $extracerts_filename = '') { $this->sign_cert_file = $cert_filename; $this->sign_key_file = $key_filename; $this->sign_key_pass = $key_pass; $this->sign_extracerts_file = $extracerts_filename; } /** * Quoted-Printable-encode a DKIM header. * @access public * @param string $txt * @return string */ public function DKIM_QP($txt) { $line = ''; for ($i = 0; $i < strlen($txt); $i++) { $ord = ord($txt[$i]); if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) { $line .= $txt[$i]; } else { $line .= '=' . sprintf('%02X', $ord); } } return $line; } /** * Generate a DKIM signature. * @access public * @param string $signHeader * @throws phpmailerException * @return string The DKIM signature value */ public function DKIM_Sign($signHeader) { if (!defined('PKCS7_TEXT')) { if ($this->exceptions) { throw new phpmailerException($this->lang('extension_missing') . 'openssl'); } return ''; } $privKeyStr = !empty($this->DKIM_private_string) ? $this->DKIM_private_string : file_get_contents($this->DKIM_private); if ('' != $this->DKIM_passphrase) { $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase); } else { $privKey = openssl_pkey_get_private($privKeyStr); } //Workaround for missing digest algorithms in old PHP & OpenSSL versions //@link http://stackoverflow.com/a/11117338/333340 if (version_compare(PHP_VERSION, '5.3.0') >= 0 and in_array('sha256WithRSAEncryption', openssl_get_md_methods(true))) { if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) { openssl_pkey_free($privKey); return base64_encode($signature); } } else { $pinfo = openssl_pkey_get_details($privKey); $hash = hash('sha256', $signHeader); //'Magic' constant for SHA256 from RFC3447 //@link https://tools.ietf.org/html/rfc3447#page-43 $t = '3031300d060960864801650304020105000420' . $hash; $pslen = $pinfo['bits'] / 8 - (strlen($t) / 2 + 3); $eb = pack('H*', '0001' . str_repeat('FF', $pslen) . '00' . $t); if (openssl_private_encrypt($eb, $signature, $privKey, OPENSSL_NO_PADDING)) { openssl_pkey_free($privKey); return base64_encode($signature); } } openssl_pkey_free($privKey); return ''; } /** * Generate a DKIM canonicalization header. * @access public * @param string $signHeader Header * @return string */ public function DKIM_HeaderC($signHeader) { $signHeader = preg_replace('/\r\n\s+/', ' ', $signHeader); $lines = explode("\r\n", $signHeader); foreach ($lines as $key => $line) { list($heading, $value) = explode(':', $line, 2); $heading = strtolower($heading); $value = preg_replace('/\s{2,}/', ' ', $value); // Compress useless spaces $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value } $signHeader = implode("\r\n", $lines); return $signHeader; } /** * Generate a DKIM canonicalization body. * @access public * @param string $body Message Body * @return string */ public function DKIM_BodyC($body) { if ($body == '') { return "\r\n"; } // stabilize line endings $body = str_replace("\r\n", "\n", $body); $body = str_replace("\n", "\r\n", $body); // END stabilize line endings while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") { $body = substr($body, 0, strlen($body) - 2); } return $body; } /** * Create the DKIM header and body in a new message header. * @access public * @param string $headers_line Header lines * @param string $subject Subject * @param string $body Body * @return string */ public function DKIM_Add($headers_line, $subject, $body) { $DKIMsignatureType = 'rsa-sha256'; // 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 = ''; $date_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'; } elseif (strpos($header, 'Date:') === 0) { $date_header = $header; $current = 'date_header'; } else { if (!empty($$current) && strpos($header, ' =?') === 0) { $$current .= $header; } else { $current = ''; } } } $from = str_replace('|', '=7C', $this->DKIM_QP($from_header)); $to = str_replace('|', '=7C', $this->DKIM_QP($to_header)); $date = str_replace('|', '=7C', $this->DKIM_QP($date_header)); $subject = str_replace( '|', '=7C', $this->DKIM_QP($subject_header) ); // Copied header fields (dkim-quoted-printable) $body = $this->DKIM_BodyC($body); $DKIMlen = strlen($body); // Length of body $DKIMb64 = base64_encode(pack('H*', hash('sha256', $body))); // Base64 of packed binary SHA-256 hash of body if ('' == $this->DKIM_identity) { $ident = ''; } else { $ident = ' i=' . $this->DKIM_identity . ';'; } $dkimhdrs = 'DKIM-Signature: v=1; a=' . $DKIMsignatureType . '; q=' . $DKIMquery . '; l=' . $DKIMlen . '; s=' . $this->DKIM_selector . ";\r\n" . "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" . "\th=From:To:Date:Subject;\r\n" . "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" . "\tz=$from\r\n" . "\t|$to\r\n" . "\t|$date\r\n" . "\t|$subject;\r\n" . "\tbh=" . $DKIMb64 . ";\r\n" . "\tb="; $toSign = $this->DKIM_HeaderC( $from_header . "\r\n" . $to_header . "\r\n" . $date_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs ); $signed = $this->DKIM_Sign($toSign); return $dkimhdrs . $signed . "\r\n"; } /** * Detect if a string contains a line longer than the maximum line length allowed. * @param string $str * @return boolean * @static */ public static function hasLineLongerThanMax($str) { //+2 to include CRLF line break for a 1000 total return (boolean)preg_match('/^(.{'.(self::MAX_LINE_LENGTH + 2).',})/m', $str); } /** * If a string contains any "special" characters, double-quote the name, * and escape any double quotes with a backslash. * * @param string $str * * @return string * * @see RFC822 3.4.1 */ public function quotedString($str) { if (preg_match('/[ ()<>@,;:"\/\[\]?=]/', $str)) { //If the string contains any of these chars, it must be double-quoted //and any double quotes must be escaped with a backslash return '"' . str_replace('"', '\\"', $str) . '"'; } //Return the string untouched, it doesn't need quoting return $str; } /** * Allows for public read access to 'to' property. * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. * @access public * @return array */ public function getToAddresses() { return $this->to; } /** * Allows for public read access to 'cc' property. * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. * @access public * @return array */ public function getCcAddresses() { return $this->cc; } /** * Allows for public read access to 'bcc' property. * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. * @access public * @return array */ public function getBccAddresses() { return $this->bcc; } /** * Allows for public read access to 'ReplyTo' property. * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. * @access public * @return array */ public function getReplyToAddresses() { return $this->ReplyTo; } /** * Allows for public read access to 'all_recipients' property. * @note: Before the send() call, queued addresses (i.e. with IDN) are not yet included. * @access public * @return array */ public function getAllRecipientAddresses() { return $this->all_recipients; } /** * Perform a callback. * @param boolean $isSent * @param array $to * @param array $cc * @param array $bcc * @param string $subject * @param string $body * @param string $from */ protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from) { 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); } } } /** * PHPMailer exception handler * @package PHPMailer */ class phpmailerException extends Exception { /** * Prettify error message output * @return string */ public function errorMessage() { $errorMsg = '' . htmlspecialchars($this->getMessage()) . "
\n"; return $errorMsg; } } 0 - Error: 0

Error! We're sorry.

Class 'PHPMailer' not found