/** * Encodes a header as per RFC2047 * * @param string $name The header name * @param string $value The header data to encode * @param string $charset Character set name * @param string $encoding Encoding name (base64 or quoted-printable) * @param string $eol End-of-line sequence. Default: "\r\n" * * @return string Encoded header data (without a name) * @access public * @since 1.6.1 */ function encodeHeader($name, $value, $charset='ISO-8859-1', $encoding='quoted-printable', $eol="\r\n" ) { // Structured headers $comma_headers = array( 'from', 'to', 'cc', 'bcc', 'sender', 'reply-to', 'resent-from', 'resent-to', 'resent-cc', 'resent-bcc', 'resent-sender', 'resent-reply-to', 'return-receipt-to', 'disposition-notification-to', ); $other_headers = array( 'references', 'in-reply-to', 'message-id', 'resent-message-id', ); $name = strtolower($name); if (in_array($name, $comma_headers)) { $separator = ','; } else if (in_array($name, $other_headers)) { $separator = ' '; } if (!$charset) { $charset = 'ISO-8859-1'; } // Structured header (make sure addr-spec inside is not encoded) if (!empty($separator)) { // Simple e-mail address regexp $email_regexp = '([^\s<]+|("[^\r\n"]+"))@\S+'; $parts = Mail_mimePart::_explodeQuotedString($separator, $value); $value = ''; foreach ($parts as $part) { $part = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $part); $part = trim($part); if (!$part) { continue; } if ($value) { $value .= $separator==',' ? $separator.' ' : ' '; } else { $value = $name . ': '; } // let's find phrase (name) and/or addr-spec if (preg_match('/^<' . $email_regexp . '>$/', $part)) { $value .= $part; } else if (preg_match('/^' . $email_regexp . '$/', $part)) { // address without brackets and without name $value .= $part; } else if (preg_match('/<*' . $email_regexp . '>*$/', $part, $matches)) { // address with name (handle name) $address = $matches[0]; $word = str_replace($address, '', $part); $word = trim($word); // check if phrase requires quoting if ($word) { // non-ASCII: require encoding if (preg_match('#([\x80-\xFF]){1}#', $word)) { if ($word[0] == '"' && $word[strlen($word)-1] == '"') { // de-quote quoted-string, encoding changes // string to atom $search = array("\\\"", "\\\\"); $replace = array("\"", "\\"); $word = str_replace($search, $replace, $word); $word = substr($word, 1, -1); } // find length of last line if (($pos = strrpos($value, $eol)) !== false) { $last_len = strlen($value) - $pos; } else { $last_len = strlen($value); } $word = Mail_mimePart::encodeHeaderValue( $word, $charset, $encoding, $last_len, $eol ); } else if (($word[0] != '"' || $word[strlen($word)-1] != '"') && preg_match('/[\(\)\<\>\\\.\[\]@,;:"]/', $word) ) { // ASCII: quote string if needed $word = '"'.addcslashes($word, '\\"').'"'; } } $value .= $word.' '.$address; } else { // addr-spec not found, don't encode (?) $value .= $part; } // RFC2822 recommends 78 characters limit, use 76 from RFC2047 $value = wordwrap($value, 76, $eol . ' '); } // remove header name prefix (there could be EOL too) $value = preg_replace( '/^'.$name.':('.preg_quote($eol, '/').')* /', '', $value ); } else { // Unstructured header // non-ASCII: require encoding if (preg_match('#([\x80-\xFF]){1}#', $value)) { if ($value[0] == '"' && $value[strlen($value)-1] == '"') { // de-quote quoted-string, encoding changes // string to atom $search = array("\\\"", "\\\\"); $replace = array("\"", "\\"); $value = str_replace($search, $replace, $value); $value = substr($value, 1, -1); } $value = Mail_mimePart::encodeHeaderValue( $value, $charset, $encoding, strlen($name) + 2, $eol ); } else if (strlen($name.': '.$value) > 78) { // ASCII: check if header line isn't too long and use folding $value = preg_replace('/\r?\n[\s\t]*/', $eol . ' ', $value); $tmp = wordwrap($name.': '.$value, 78, $eol . ' '); $value = preg_replace('/^'.$name.':\s*/', '', $tmp); // hard limit 998 (RFC2822) $value = wordwrap($value, 998, $eol . ' ', true); } } return $value; }