| <?php |
| /** |
| * File containing the ezcMailTools class |
| * |
| * Licensed to the Apache Software Foundation (ASF) under one |
| * or more contributor license agreements. See the NOTICE file |
| * distributed with this work for additional information |
| * regarding copyright ownership. The ASF licenses this file |
| * to you under the Apache License, Version 2.0 (the |
| * "License"); you may not use this file except in compliance |
| * with the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, |
| * software distributed under the License is distributed on an |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
| * KIND, either express or implied. See the License for the |
| * specific language governing permissions and limitations |
| * under the License. |
| * |
| * @package Mail |
| * @version //autogen// |
| * @license http://www.apache.org/licenses/LICENSE-2.0 Apache License, Version 2.0 |
| */ |
| |
| /** |
| * This class contains static convenience methods for composing addresses |
| * and ensuring correct line-breaks in the mail. |
| * |
| * @package Mail |
| * @version //autogen// |
| * @mainclass |
| */ |
| class ezcMailTools |
| { |
| /** |
| * Reply to sender. |
| */ |
| const REPLY_SENDER = 1; |
| |
| /** |
| * Reply to all. |
| */ |
| const REPLY_ALL = 1; |
| |
| /** |
| * Server to use for validateEmailAddressMx(). Change this if this server |
| * cannot be used with your Internet Service Provider. |
| * |
| * Default value: 'smtp.ez.no'. |
| * |
| * @var string |
| */ |
| public static $mxValidateServer = 'smtp.ez.no'; |
| |
| /** |
| * Email address to use for validateEmailAddressMx(). Change this if this |
| * address cannot be used with your Internet Service Provider. |
| * |
| * Default value: 'postmaster@ez.no'. |
| * |
| * @var string |
| */ |
| public static $mxValidateAddress = 'postmaster@ez.no'; |
| |
| /** |
| * Holds the unique ID's. |
| * |
| * @var int |
| */ |
| private static $idCounter = 0; |
| |
| /** |
| * The characters to use for line-breaks in the mail. |
| * |
| * The default is \r\n which is the value specified in RFC822. |
| * |
| * @var string |
| */ |
| private static $lineBreak = "\r\n"; |
| |
| /** |
| * Returns ezcMailAddress $item as a RFC822 compliant address string. |
| * |
| * Example: |
| * <code> |
| * composeEmailAddress( new ezcMailAddress( 'sender@example.com', 'John Doe' ) ); |
| * </code> |
| * |
| * Returns: |
| * <pre> |
| * John Doe <sender@example.com> |
| * </pre> |
| * |
| * The name part of $item will be surrounded by quotes if it contains any of |
| * these characters: , @ < > : ; ' " |
| * |
| * @param ezcMailAddress $item |
| * @return string |
| */ |
| public static function composeEmailAddress( ezcMailAddress $item ) |
| { |
| $name = trim( $item->name ); |
| if ( $name !== '' ) |
| { |
| // remove the quotes around the name part if they are already there |
| if ( $name{0} === '"' && $name{strlen( $name ) - 1} === '"' ) |
| { |
| $name = substr( $name, 1, -1 ); |
| } |
| |
| // add slashes to " and \ and surround the name part with quotes |
| if ( strpbrk( $name, ",@<>:;'\"" ) !== false ) |
| { |
| $name = str_replace( '\\', '\\\\', $name ); |
| $name = str_replace( '"', '\"', $name ); |
| $name = "\"{$name}\""; |
| } |
| |
| switch ( strtolower( $item->charset ) ) |
| { |
| case 'us-ascii': |
| $text = $name . ' <' . $item->email . '>'; |
| break; |
| |
| case 'iso-8859-1': case 'iso-8859-2': case 'iso-8859-3': case 'iso-8859-4': |
| case 'iso-8859-5': case 'iso-8859-6': case 'iso-8859-7': case 'iso-8859-8': |
| case 'iso-8859-9': case 'iso-8859-10': case 'iso-8859-11': case 'iso-8859-12': |
| case 'iso-8859-13': case 'iso-8859-14': case 'iso-8859-15' :case 'iso-8859-16': |
| case 'windows-1250': case 'windows-1251': case 'windows-1252': |
| case 'utf-8': |
| if ( strpbrk( $name, "\x80\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff" ) === false ) |
| { |
| $text = $name . ' <' . $item->email . '>'; |
| break; |
| } |
| // break intentionally missing |
| |
| default: |
| $preferences = array( |
| 'input-charset' => $item->charset, |
| 'output-charset' => $item->charset, |
| 'scheme' => 'Q', |
| 'line-break-chars' => ezcMailTools::lineBreak() |
| ); |
| $name = iconv_mime_encode( 'dummy', $name, $preferences ); |
| $name = substr( $name, 7 ); // "dummy: " + 1 |
| $text = $name . ' <' . $item->email . '>'; |
| break; |
| } |
| } |
| else |
| { |
| $text = $item->email; |
| } |
| return $text; |
| } |
| |
| /** |
| * Returns the array $items consisting of ezcMailAddress objects |
| * as one RFC822 compliant address string. |
| * |
| * Set foldLength to control how many characters each line can have before a line |
| * break is inserted according to the folding rules specified in RFC2822. |
| * |
| * @param array(ezcMailAddress) $items |
| * @param int $foldLength |
| * @return string |
| */ |
| public static function composeEmailAddresses( array $items, $foldLength = null ) |
| { |
| $textElements = array(); |
| foreach ( $items as $item ) |
| { |
| $textElements[] = ezcMailTools::composeEmailAddress( $item ); |
| } |
| |
| if ( $foldLength === null ) // quick version |
| { |
| return implode( ', ', $textElements ); |
| } |
| |
| $result = ""; |
| $charsSinceFold = 0; |
| foreach ( $textElements as $element ) |
| { |
| $length = strlen( $element ); |
| if ( ( $charsSinceFold + $length + 2 /* comma, space */ ) > $foldLength ) |
| { |
| // fold last line if there is any |
| if ( $result != '' ) |
| { |
| $result .= "," . ezcMailTools::lineBreak() .' '; |
| $charsSinceFold = 0; |
| } |
| $result .= $element; |
| } |
| else |
| { |
| if ( $result == '' ) |
| { |
| $result = $element; |
| } |
| else |
| { |
| $result .= ', ' . $element; |
| } |
| } |
| $charsSinceFold += $length + 1 /*space*/; |
| } |
| return $result; |
| } |
| |
| /** |
| * Returns an ezcMailAddress object parsed from the address string $address. |
| * |
| * You can set the encoding of the name part with the $encoding parameter. |
| * If $encoding is omitted or set to "mime" parseEmailAddress will asume that |
| * the name part is mime encoded. |
| * |
| * This method does not perform validation. It will also accept slightly |
| * malformed addresses. |
| * |
| * If the mail address given can not be decoded null is returned. |
| * |
| * Example: |
| * <code> |
| * ezcMailTools::parseEmailAddress( 'John Doe <john@example.com>' ); |
| * </code> |
| * |
| * @param string $address |
| * @param string $encoding |
| * @return ezcMailAddress |
| */ |
| public static function parseEmailAddress( $address, $encoding = "mime" ) |
| { |
| // we don't care about the "group" part of the address since this is not used anywhere |
| |
| $matches = array(); |
| $pattern = '/<?\"?[a-zA-Z0-9!#\$\%\&\'\*\+\-\/=\?\^_`{\|}~\.]+\"?@[a-zA-Z0-9!#\$\%\&\'\*\+\-\/=\?\^_`{\|}~\.]+>?$/'; |
| if ( preg_match( trim( $pattern ), $address, $matches, PREG_OFFSET_CAPTURE ) != 1 ) |
| { |
| return null; |
| } |
| $name = substr( $address, 0, $matches[0][1] ); |
| |
| // trim <> from the address and "" from the name |
| $name = trim( $name, '" ' ); |
| $mail = trim( $matches[0][0], '<>' ); |
| // remove any quotes found in mail addresses like "bah,"@example.com |
| $mail = str_replace( '"', '', $mail ); |
| |
| if ( $encoding == 'mime' ) |
| { |
| // the name may contain interesting character encoding. We need to convert it. |
| $name = ezcMailTools::mimeDecode( $name ); |
| } |
| else |
| { |
| $name = ezcMailCharsetConverter::convertToUTF8( $name, $encoding ); |
| } |
| |
| $address = new ezcMailAddress( $mail, $name, 'utf-8' ); |
| return $address; |
| } |
| |
| /** |
| * Returns an array of ezcMailAddress objects parsed from the address string $addresses. |
| * |
| * You can set the encoding of the name parts with the $encoding parameter. |
| * If $encoding is omitted or set to "mime" parseEmailAddresses will asume that |
| * the name parts are mime encoded. |
| * |
| * Example: |
| * <code> |
| * ezcMailTools::parseEmailAddresses( 'John Doe <john@example.com>' ); |
| * </code> |
| * |
| * @param string $addresses |
| * @param string $encoding |
| * @return array(ezcMailAddress) |
| */ |
| public static function parseEmailAddresses( $addresses, $encoding = "mime" ) |
| { |
| $addressesArray = array(); |
| $inQuote = false; |
| $last = 0; // last hit |
| $length = strlen( $addresses ); |
| for ( $i = 0; $i < $length; $i++ ) |
| { |
| if ( $addresses[$i] == '"' ) |
| { |
| $inQuote = !$inQuote; |
| } |
| else if ( $addresses[$i] == ',' && !$inQuote ) |
| { |
| $addressesArray[] = substr( $addresses, $last, $i - $last ); |
| $last = $i + 1; // eat comma |
| } |
| } |
| |
| // fetch the last one |
| $addressesArray[] = substr( $addresses, $last ); |
| |
| $addressObjects = array(); |
| foreach ( $addressesArray as $address ) |
| { |
| $addressObject = self::parseEmailAddress( $address, $encoding ); |
| if ( $addressObject !== null ) |
| { |
| $addressObjects[] = $addressObject; |
| } |
| } |
| |
| return $addressObjects; |
| } |
| |
| /** |
| * Returns true if $address is a valid email address, false otherwise. |
| * |
| * By default it will only validate against the same regular expression |
| * used in ext/filter. It follows |
| * {@link http://www.faqs.org/rfcs/rfc822.html RFC822} and |
| * {@link http://www.faqs.org/rfcs/rfc2822.html RFC2822}. |
| * |
| * If $checkMxRecords is true, then an MX records check will be performed |
| * also, by sending a test mail (RCPT TO) to $address using the MX records |
| * found for the domain part of $address. MX record checking does not work |
| * on Windows due to the lack of getmxrr() and checkdnsrr() PHP functions. |
| * The ezcBaseFunctionalityNotSupportedException is thrown in this case. |
| * |
| * If checking against MX records, set these values before performing the |
| * check, to ensure the MX record checks work properly: |
| * <code> |
| * ezcMailTools::$mxValidateServer = 'your.mail.server'; // default 'smtp.ez.no' |
| * ezcMailTools::$mxValidateAddress = 'email@mail.server'; // default 'postmaster@ez.no' |
| * </code> |
| * |
| * The input email address $address should be trimmed from white spaces |
| * and/or quotes around it before calling this function (if needed). |
| * |
| * An email address has this form: |
| * <code> |
| * localpart@domainpart |
| * </code> |
| * |
| * The localpart has these rules, and these rules are just an approximation of |
| * the rules in RFC2822: |
| * - allowed characters: . + ~ / ' - _ ` ^ $ % & ! ' | { |
| * - the dot (.) cannot be the first or the last character |
| * - the double-quote character (") can only surround the localpart (so |
| * if it appears it must be the first and the last character of localpart) |
| * - spaces are allowed if the localpart is surrounded in double-quotes |
| * - other ASCII characters (even from the extended-ASCII set) are allowed |
| * if the localparts is surrounded in double-quotes (the function |
| * ezcMailTools::composeEmailAddress will encode it when using it |
| * in a mail header) |
| * - the double-quotes character (") cannot be escaped to appear in a |
| * localpart surrounded by double quotes (so "john"doe"@example.com is not |
| * a valid email address) |
| * |
| * The domainpart has the same rules as a domain name, as defined in |
| * {@link http://www.faqs.org/rfcs/rfc822.html RFC822} and |
| * {@link http://www.faqs.org/rfcs/rfc2822.html RFC2822}. |
| * |
| * See also the test files (in the "Mail/tests/tools/data" directory) for |
| * examples of correct and incorrect email addresses. |
| * |
| * @throws ezcBaseFunctionalityNotSupportedException |
| * if $checkMxRecords is true and getmxrr() or checkdnsrr() functions |
| * are missing (e.g. on Windows) |
| * @param string $address |
| * @param bool $checkMxRecords |
| * @return bool |
| */ |
| public static function validateEmailAddress( $address, $checkMxRecords = false ) |
| { |
| $pattern = '/^((\"[^\"\f\n\r\t\v\b]+\")|([A-Za-z0-9_\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+(\.[A-Za-z0-9_\!\#\$\%\&\'\*\+\-\~\/\^\`\|\{\}]+)*))@((\[(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))\])|(((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9]))\.((25[0-5])|(2[0-4][0-9])|([0-1]?[0-9]?[0-9])))|((([A-Za-z0-9\-])+\.)+[A-Za-z\-]{2,}))$/'; |
| |
| if ( preg_match( $pattern, $address ) ) |
| { |
| if ( $checkMxRecords ) |
| { |
| return self::validateEmailAddressMx( $address ); |
| } |
| else |
| { |
| // $address passed through regexp, with no MX checks |
| return true; |
| } |
| } |
| else |
| { |
| // $address did not pass through regexp |
| return false; |
| } |
| } |
| |
| /** |
| * Checks if the email address $address is valid based on its MX records. |
| * |
| * Steps: |
| * - the MX records are fetched for the domain part of $address, along with |
| * their weights |
| * - the MX records are sorted based on the weights |
| * - for each MX record a connection is open |
| * - a test mail (RCPT TO) is tried to be sent to $address |
| * - if one test mail succeeds, then the address is valid, else invalid |
| * |
| * Set these values before calling this function, to ensure the MX record |
| * checks work properly: |
| * <code> |
| * ezcMailTools::$mxValidateServer = 'your.mail.server'; // default 'smtp.ez.no' |
| * ezcMailTools::$mxValidateAddress = 'email@mail.server'; // default 'postmaster@ez.no' |
| * </code> |
| * |
| * MX record checking does not work on Windows due to the lack of getmxrr() |
| * and checkdnsrr() PHP functions. The ezcBaseFunctionalityNotSupportedException |
| * is thrown in this case. |
| * |
| * @throws ezcBaseFunctionalityNotSupportedException |
| * if getmxrr() or checkdnsrr() functions are missing (e.g. on Windows) |
| * @param string $address |
| * @return bool |
| */ |
| protected static function validateEmailAddressMx( $address ) |
| { |
| if ( !ezcBaseFeatures::hasFunction( 'getmxrr' ) || !ezcBaseFeatures::hasFunction( 'checkdnsrr' ) ) |
| { |
| throw new ezcBaseFunctionalityNotSupportedException( 'Checking DNS records', 'getmxrr() or checkdnsrr() missing' ); |
| } |
| |
| $timeoutOpen = 3; // for fsockopen() |
| $timeoutConnection = 5; // for stream_set_timeout() |
| |
| list( $local, $domain ) = explode( '@', $address ); |
| if ( !empty( $domain ) ) |
| { |
| if ( getmxrr( $domain, $hosts, $weights ) ) |
| { |
| for ( $i = 0; $i < count( $hosts ); $i++ ) |
| { |
| $mx[$hosts[$i]] = $weights[$i]; |
| } |
| |
| asort( $mx ); |
| $mx = array_keys( $mx ); |
| } |
| elseif ( checkdnsrr( $domain, 'A' ) ) |
| { |
| $mx[0] = gethostbyname( $domain ); |
| } |
| else |
| { |
| $mx = array(); |
| } |
| |
| if ( ( $numberOfMx = count( $mx ) ) > 0 ) |
| { |
| $smtp = array( |
| "HELO " . self::$mxValidateServer, |
| "MAIL FROM: <" . self::$mxValidateAddress . ">", |
| "RCPT TO: <{$address}>", |
| "QUIT", |
| ); |
| |
| for ( $i = 0; $i < $numberOfMx; $i++ ) |
| { |
| if ( $socket = @fsockopen( $mx[$i], 25, $errno = 0, $errstr = 0, $timeoutOpen ) ) |
| { |
| $response = fgets( $socket ); |
| stream_set_timeout( $socket, $timeoutConnection ); |
| $meta = stream_get_meta_data( $socket ); |
| if ( !$meta['timed_out'] && !preg_match( '/^2\d\d[ -]/', $response ) ) |
| { |
| return false; |
| } |
| foreach ( $smtp as $command ) |
| { |
| fputs( $socket, "{$command}\r\n" ); |
| $response = fgets( $socket, 4096 ); |
| if ( !$meta['timed_out'] && preg_match( '/^5\d\d[ -]/', $response ) ) |
| { |
| return false; |
| } |
| } |
| fclose( $socket ); |
| return true; |
| } |
| elseif ( $i === $numberOfMx - 1 ) |
| { |
| // none of the mail servers could be contacted |
| return false; |
| } |
| } |
| } |
| else |
| { |
| // no mail servers found |
| return false; |
| } |
| } |
| } |
| |
| /** |
| * Returns an unique message ID to be used for a mail message. |
| * |
| * The hostname $hostname will be added to the unique ID as required by RFC822. |
| * If an e-mail address is provided instead, the hostname is extracted and used. |
| * |
| * The formula to generate the message ID is: [time_and_date].[process_id].[counter] |
| * |
| * @param string $hostname |
| * @return string |
| */ |
| public static function generateMessageId( $hostname ) |
| { |
| if ( strpos( $hostname, '@' ) !== false ) |
| { |
| $hostname = strstr( $hostname, '@' ); |
| } |
| else |
| { |
| $hostname = '@' . $hostname; |
| } |
| return date( 'YmdGHjs' ) . '.' . getmypid() . '.' . self::$idCounter++ . $hostname; |
| } |
| |
| /** |
| * Returns an unique ID to be used for Content-ID headers. |
| * |
| * The part $partName is default set to "part". Another value can be used to provide, |
| * for example, a file name of a part. $partName will be encoded with base64 to be |
| * compliant with the RFCs. |
| * |
| * The formula used is [base64( $partName )]."@".[time].[counter] |
| * |
| * @param string $partName |
| * @return string |
| */ |
| public static function generateContentId( $partName = "part" ) |
| { |
| return str_replace( array( '=', '+', '/' ), '', base64_encode( $partName ) ) . '@' . date( 'His' ) . self::$idCounter++; |
| } |
| |
| /** |
| * Sets the endLine $character(s) to use when generating mail. |
| * The default is to use "\r\n" as specified by RFC 2045. |
| * |
| * @param string $characters |
| */ |
| public static function setLineBreak( $characters ) |
| { |
| self::$lineBreak = $characters; |
| } |
| |
| /** |
| * Returns one endLine character. |
| * |
| * The default is to use "\n\r" as specified by RFC 2045. |
| * |
| * @return string |
| */ |
| public static function lineBreak() |
| { |
| // Note, this function does deliberately not |
| // have a $count parameter because of speed issues. |
| return self::$lineBreak; |
| } |
| |
| /** |
| * Decodes mime encoded fields and tries to recover from errors. |
| * |
| * Decodes the $text encoded as a MIME string to the $charset. In case the |
| * strict conversion fails this method tries to workaround the issues by |
| * trying to "fix" the original $text before trying to convert it. |
| * |
| * @param string $text |
| * @param string $charset |
| * @return string |
| */ |
| public static function mimeDecode( $text, $charset = 'utf-8' ) |
| { |
| $origtext = $text; |
| $text = @iconv_mime_decode( $text, 0, $charset ); |
| if ( $text !== false ) |
| { |
| return $text; |
| } |
| |
| // something went wrong while decoding, let's see if we can fix it |
| // Try to fix lower case hex digits |
| $text = preg_replace_callback( |
| '/=(([a-f][a-f0-9])|([a-f0-9][a-f]))/', |
| create_function( '$matches', 'return strtoupper($matches[0]);' ), |
| $origtext |
| ); |
| $text = @iconv_mime_decode( $text, 0, $charset ); |
| if ( $text !== false ) |
| { |
| return $text; |
| } |
| |
| // Workaround a bug in PHP 5.1.0-5.1.3 where the "b" and "q" methods |
| // are not understood (but only "B" and "Q") |
| $text = str_replace( array( '?b?', '?q?' ), array( '?B?', '?Q?' ), $origtext ); |
| $text = @iconv_mime_decode( $text, 0, $charset ); |
| if ( $text !== false ) |
| { |
| return $text; |
| } |
| |
| // Try it as latin 1 string |
| $text = preg_replace( '/=\?([^?]+)\?/', '=?iso-8859-1?', $origtext ); |
| $text = iconv_mime_decode( $text, 0, $charset ); |
| |
| return $text; |
| } |
| |
| /** |
| * Returns a new mail object that is a reply to the current object. |
| * |
| * The new mail will have the correct to, cc, bcc and reference headers set. |
| * It will not have any body set. |
| * |
| * By default the reply will only be sent to the sender of the original mail. |
| * If $type is set to REPLY_ALL, all the original recipients will be included |
| * in the reply. |
| * |
| * Use $subjectPrefix to set the prefix to the subject of the mail. The default |
| * is to prefix with 'Re: '. |
| * |
| * @param ezcMail $mail |
| * @param ezcMailAddress $from |
| * @param int $type REPLY_SENDER or REPLY_ALL |
| * @param string $subjectPrefix |
| * @param string $mailClass |
| * @return ezcMail |
| */ |
| static public function replyToMail( ezcMail $mail, ezcMailAddress $from, |
| $type = self::REPLY_SENDER, $subjectPrefix = "Re: ", |
| $mailClass = "ezcMail" ) |
| { |
| $reply = new $mailClass(); |
| $reply->from = $from; |
| |
| // To = Reply-To if set |
| if ( $mail->getHeader( 'Reply-To' ) != '' ) |
| { |
| $reply->to = ezcMailTools::parseEmailAddresses( $mail->getHeader( 'Reply-To' ) ); |
| } |
| else // Else To = From |
| |
| { |
| $reply->to = array( $mail->from ); |
| } |
| |
| if ( $type == self::REPLY_ALL ) |
| { |
| // Cc = Cc + To - your own address |
| $cc = array(); |
| foreach ( $mail->to as $address ) |
| { |
| if ( $address->email != $from->email ) |
| { |
| $cc[] = $address; |
| } |
| } |
| foreach ( $mail->cc as $address ) |
| { |
| if ( $address->email != $from->email ) |
| { |
| $cc[] = $address; |
| } |
| } |
| $reply->cc = $cc; |
| } |
| |
| $reply->subject = $subjectPrefix . $mail->subject; |
| |
| if ( $mail->getHeader( 'Message-Id' ) ) |
| { |
| // In-Reply-To = Message-Id |
| $reply->setHeader( 'In-Reply-To', $mail->getHeader( 'Message-ID' ) ); |
| |
| // References = References . Message-Id |
| if ( $mail->getHeader( 'References' ) != '' ) |
| { |
| $reply->setHeader( 'References', $mail->getHeader( 'References' ) |
| . ' ' . $mail->getHeader( 'Message-ID' ) ); |
| } |
| else |
| { |
| $reply->setHeader( 'References', $mail->getHeader( 'Message-ID' ) ); |
| } |
| } |
| else // original mail is borked. Let's support it anyway. |
| { |
| $reply->setHeader( 'References', $mail->getHeader( 'References' ) ); |
| } |
| |
| return $reply; |
| } |
| |
| /** |
| * Guesses the content and mime type by using the file extension. |
| * |
| * The content and mime types are returned through the $contentType |
| * and $mimeType arguments. |
| * For the moment only for image files. |
| * |
| * @param string $fileName |
| * @param string $contentType |
| * @param string $mimeType |
| */ |
| static public function guessContentType( $fileName, &$contentType, &$mimeType ) |
| { |
| $extension = strtolower( pathinfo( $fileName, PATHINFO_EXTENSION ) ); |
| switch ( $extension ) |
| { |
| case 'gif': |
| $contentType = 'image'; |
| $mimeType = 'gif'; |
| break; |
| |
| case 'jpg': |
| case 'jpe': |
| case 'jpeg': |
| $contentType = 'image'; |
| $mimeType = 'jpeg'; |
| break; |
| |
| case 'png': |
| $contentType = 'image'; |
| $mimeType = 'png'; |
| break; |
| |
| case 'bmp': |
| $contentType = 'image'; |
| $mimeType = 'bmp'; |
| break; |
| |
| case 'tif': |
| case 'tiff': |
| $contentType = 'image'; |
| $mimeType = 'tiff'; |
| break; |
| |
| default: |
| return false; |
| } |
| return true; |
| } |
| |
| /** |
| * Replaces HTML embedded "cid:" references with replacements from $contentIdArray. |
| * |
| * The method matches all "cid:" references in the $htmlText and then loops |
| * over each match. For each match the found content ID is looked-up as key |
| * in the $contentIdArray and the value is then inserted as replacement for |
| * the "cid:" reference. |
| * |
| * <code> |
| * <?php |
| * $contentIdArray = array( 'consoletools-table.png@1421450' => 'http://localhost/consoletools-table.jpg' ); |
| * $text = "<html> Embedded image: <img src='cid:consoletools-table.png@1421450'/> </html>"; |
| * $htmlBody = ezcMailTools::replaceContentIdRefs( $text, $contentIdArray ); |
| * // $htmlBody is now: |
| * // <html> Embedded image: <img src='http://localhost/consoletools-table.jpg'/> </html> |
| * ?> |
| * </code> |
| * |
| * The $contentIdArray can be build by iterating over all parts in the |
| * mail, and for each ezcMailFilePart that you find: 1. copy the associated |
| * file (fileName property of the ezcMailFilePart object) to your webroot; |
| * 2. add an element to the array with the key created from the contentId |
| * property from the ezcMailFilePart object. See the tutorial for an |
| * example of this. |
| * |
| * @param string $htmlText |
| * @param array(string=>string) $contentIdArray |
| * @return string |
| */ |
| static function replaceContentIdRefs( $htmlText, $contentIdArray ) |
| { |
| preg_match_all( '@src=[\'"](cid:(.*?))[\'"]@', $htmlText, $matches ); |
| for ( $i = 0; $i < count( $matches[0] ); $i++ ) |
| { |
| if ( isset( $contentIdArray[$matches[2][$i]] ) ) |
| { |
| $htmlText = str_replace( $matches[1][$i], $contentIdArray[$matches[2][$i]], $htmlText ); |
| } |
| } |
| return $htmlText; |
| } |
| } |
| ?> |