summaryrefslogtreecommitdiff
path: root/program/lib/Mail
diff options
context:
space:
mode:
authorsvncommit <devs@roundcube.net>2006-06-09 16:47:21 +0000
committersvncommit <devs@roundcube.net>2006-06-09 16:47:21 +0000
commita8435bdd12437c5b655859d2ad194832921fcd0d (patch)
tree7b1b9259e17ad7788d2a5f301aa0726a79a00d26 /program/lib/Mail
parentd72d411ee338ae2cca0bef2c08822b52eb72e8e5 (diff)
Updated to latest version. Resolves issues with non-ISO-8859-1 characters in attachment filenames and headers
Diffstat (limited to 'program/lib/Mail')
-rw-r--r--program/lib/Mail/mime.php155
1 files changed, 139 insertions, 16 deletions
diff --git a/program/lib/Mail/mime.php b/program/lib/Mail/mime.php
index de2bba0a9..42842e3a4 100644
--- a/program/lib/Mail/mime.php
+++ b/program/lib/Mail/mime.php
@@ -114,6 +114,7 @@ class Mail_mime
{
$this->_setEOL($crlf);
$this->_build_params = array(
+ 'head_encoding' => 'quoted-printable',
'text_encoding' => '7bit',
'html_encoding' => 'quoted-printable',
'7bit_wrap' => 998,
@@ -247,13 +248,15 @@ class Mail_mime
* @param string $disposition The content-disposition of this file
* Defaults to attachment.
* Possible values: attachment, inline.
+ * @param string $charset The character set used in the filename
+ * of this attachment.
* @return mixed true on success or PEAR_Error object
* @access public
*/
function addAttachment($file, $c_type = 'application/octet-stream',
$name = '', $isfilename = true,
$encoding = 'base64',
- $disposition = 'attachment')
+ $disposition = 'attachment', $charset = '')
{
$filedata = ($isfilename === true) ? $this->_file2str($file)
: $file;
@@ -279,6 +282,7 @@ class Mail_mime
'name' => $filename,
'c_type' => $c_type,
'encoding' => $encoding,
+ 'charset' => $charset,
'disposition' => $disposition
);
return true;
@@ -433,7 +437,7 @@ class Mail_mime
function &_addHtmlImagePart(&$obj, $value)
{
$params['content_type'] = $value['c_type'] . '; ' .
- 'name="' . $params['dfilename'] . '"';
+ 'name="' . $value['name'] . '"';
$params['encoding'] = 'base64';
$params['disposition'] = 'inline';
$params['dfilename'] = $value['name'];
@@ -454,12 +458,20 @@ class Mail_mime
*/
function &_addAttachmentPart(&$obj, $value)
{
+ $params['dfilename'] = $value['name'];
+ $params['encoding'] = $value['encoding'];
+ if ($value['disposition'] != "inline") {
+ $fname = array("fname" => $value['name']);
+ $fname_enc = $this->_encodeHeaders($fname);
+ $params['dfilename'] = $fname_enc['fname'];
+ }
+ if ($value['charset']) {
+ $params['charset'] = $value['charset'];
+ }
$params['content_type'] = $value['c_type'] . '; ' .
'name="' . $params['dfilename'] . '"';
- $params['encoding'] = $value['encoding'];
$params['disposition'] = isset($value['disposition']) ?
$value['disposition'] : 'attachment';
- $params['dfilename'] = $value['name'];
$ret = $obj->addSubpart($value['body'], $params);
return $ret;
}
@@ -500,9 +512,14 @@ class Mail_mime
*
* @param array Build parameters that change the way the email
* is built. Should be associative. Can contain:
+ * head_encoding - What encoding to use for the headers.
+ * Options: quoted-printable or base64
+ * Default is quoted-printable
* text_encoding - What encoding to use for plain text
+ * Options: 7bit, 8bit, base64, or quoted-printable
* Default is 7bit
* html_encoding - What encoding to use for html
+ * Options: 7bit, 8bit, base64, or quoted-printable
* Default is quoted-printable
* 7bit_wrap - Number of characters before text is
* wrapped in 7bit encoding
@@ -743,25 +760,130 @@ class Mail_mime
}
/**
+ * Since the PHP send function requires you to specifiy
+ * recipients (To: header) separately from the other
+ * headers, the To: header is not properly encoded.
+ * To fix this, you can use this public method to
+ * encode your recipients before sending to the send
+ * function
+ *
+ * @param string $recipients A comma-delimited list of recipients
+ * @return string Encoded data
+ * @access public
+ */
+ function encodeRecipients($recipients)
+ {
+ $input = array("To" => $recipients);
+ $retval = $this->_encodeHeaders($input);
+ return $retval["To"] ;
+ }
+
+ /**
* Encodes a header as per RFC2047
*
- * @param string $input The header data to encode
- * @return string Encoded data
+ * @param array $input The header data to encode
+ * @return array Encoded data
* @access private
*/
function _encodeHeaders($input)
{
foreach ($input as $hdr_name => $hdr_value) {
- preg_match_all('/(\w*[\x80-\xFF]+\w*)/', $hdr_value, $matches);
- foreach ($matches[1] as $value) {
- $replacement = preg_replace('/([\x80-\xFF])/e',
- '"=" .
- strtoupper(dechex(ord("\1")))',
- $value);
- $hdr_value = str_replace($value, '=?' .
- $this->_build_params['head_charset'] .
- '?Q?' . $replacement . '?=',
- $hdr_value);
+ if (function_exists('iconv_mime_encode') && preg_match('#[\x80-\xFF]{1}#', $hdr_value)){
+ $imePref = array();
+ if ($this->_build_params['head_encoding'] == 'base64'){
+ $imePrefs['scheme'] = 'B';
+ }else{
+ $imePrefs['scheme'] = 'Q';
+ }
+ $imePrefs['input-charset'] = $this->_build_params['head_charset'];
+ $imePrefs['output-charset'] = $this->_build_params['head_charset'];
+ $hdr_value = iconv_mime_encode($hdr_name, $hdr_value, $imePrefs);
+ $hdr_value = preg_replace("#^{$hdr_name}\:\ #", "", $hdr_value);
+ }elseif (preg_match('#[\x80-\xFF]{1}#', $hdr_value)){
+ //This header contains non ASCII chars and should be encoded.
+ switch ($this->_build_params['head_encoding']) {
+ case 'base64':
+ //Base64 encoding has been selected.
+
+ //Generate the header using the specified params and dynamicly
+ //determine the maximum length of such strings.
+ //75 is the value specified in the RFC. The -2 is there so
+ //the later regexp doesn't break any of the translated chars.
+ $prefix = '=?' . $this->_build_params['head_charset'] . '?B?';
+ $suffix = '?=';
+ $maxLength = 75 - strlen($prefix . $suffix) - 2;
+ $maxLength1stLine = $maxLength - strlen($hdr_name);
+
+ //Base64 encode the entire string
+ $hdr_value = base64_encode($hdr_value);
+
+ //This regexp will break base64-encoded text at every
+ //$maxLength but will not break any encoded letters.
+ $reg1st = "|.{0,$maxLength1stLine}[^\=][^\=]|";
+ $reg2nd = "|.{0,$maxLength}[^\=][^\=]|";
+ break;
+ case 'quoted-printable':
+ default:
+ //quoted-printable encoding has been selected
+
+ //Generate the header using the specified params and dynamicly
+ //determine the maximum length of such strings.
+ //75 is the value specified in the RFC. The -2 is there so
+ //the later regexp doesn't break any of the translated chars.
+ $prefix = '=?' . $this->_build_params['head_charset'] . '?Q?';
+ $suffix = '?=';
+ $maxLength = 75 - strlen($prefix . $suffix) - 2;
+ $maxLength1stLine = $maxLength - strlen($hdr_name);
+
+ //Replace all special characters used by the encoder.
+ $search = array("=", "_", "?", " ");
+ $replace = array("=3D", "=5F", "=3F", "_");
+ $hdr_value = str_replace($search, $replace, $hdr_value);
+
+ //Replace all extended characters (\x80-xFF) with their
+ //ASCII values.
+ $hdr_value = preg_replace(
+ '#([\x80-\xFF])#e',
+ '"=" . strtoupper(dechex(ord("\1")))',
+ $hdr_value
+ );
+ //This regexp will break QP-encoded text at every $maxLength
+ //but will not break any encoded letters.
+ $reg1st = "|(.{0,$maxLength})[^\=]|";
+ $reg2nd = "|(.{0,$maxLength})[^\=]|";
+ break;
+ }
+ //Begin with the regexp for the first line.
+ $reg = $reg1st;
+ $output = "";
+ while ($hdr_value) {
+ //Split translated string at every $maxLength
+ //But make sure not to break any translated chars.
+ $found = preg_match($reg, $hdr_value, $matches);
+
+ //After this first line, we need to use a different
+ //regexp for the first line.
+ $reg = $reg2nd;
+
+ //Save the found part and encapsulate it in the
+ //prefix & suffix. Then remove the part from the
+ //$hdr_value variable.
+ if ($found){
+ $part = $matches[0];
+ $hdr_value = substr($hdr_value, strlen($matches[0]));
+ }else{
+ $part = $hdr_value;
+ $hdr_value = "";
+ }
+
+ //RFC 2047 specifies that any split header should be seperated
+ //by a CRLF SPACE.
+ if ($output){
+ $output .= "\r\n ";
+ }
+ $output .= $prefix . $part . $suffix;
+ }
+ $hdr_value = $output;
}
$input[$hdr_name] = $hdr_value;
}
@@ -787,3 +909,4 @@ class Mail_mime
} // End of class
?>
+