| 1 | <?php |
|---|
| 2 | |
|---|
| 3 | /* |
|---|
| 4 | +-----------------------------------------------------------------------+ |
|---|
| 5 | | program/include/rcube_mail_mime.php | |
|---|
| 6 | | | |
|---|
| 7 | | This file is part of the RoundCube Webmail client | |
|---|
| 8 | | Copyright (C) 2007-2009, RoundCube Dev. - Switzerland | |
|---|
| 9 | | Licensed under the GNU GPL | |
|---|
| 10 | | | |
|---|
| 11 | | PURPOSE: | |
|---|
| 12 | | Extend PEAR:Mail_mime class and override encodeHeaders method | |
|---|
| 13 | | | |
|---|
| 14 | +-----------------------------------------------------------------------+ |
|---|
| 15 | | Author: Thomas Bruederli <roundcube@gmail.com> | |
|---|
| 16 | +-----------------------------------------------------------------------+ |
|---|
| 17 | |
|---|
| 18 | $Id: sendmail.inc 506 2007-03-14 00:39:51Z thomasb $ |
|---|
| 19 | |
|---|
| 20 | */ |
|---|
| 21 | |
|---|
| 22 | |
|---|
| 23 | /** |
|---|
| 24 | * Replacement PEAR:Mail_mime with some additional or overloaded methods |
|---|
| 25 | * |
|---|
| 26 | * @package Mail |
|---|
| 27 | */ |
|---|
| 28 | class rcube_mail_mime extends Mail_mime |
|---|
| 29 | { |
|---|
| 30 | |
|---|
| 31 | protected $mime_content; |
|---|
| 32 | |
|---|
| 33 | /** |
|---|
| 34 | * Set build parameters |
|---|
| 35 | */ |
|---|
| 36 | function setParam($param) |
|---|
| 37 | { |
|---|
| 38 | if (is_array($param)) { |
|---|
| 39 | $this->_build_params = array_merge($this->_build_params, $param); |
|---|
| 40 | } |
|---|
| 41 | } |
|---|
| 42 | |
|---|
| 43 | /** |
|---|
| 44 | * Adds an image to the list of embedded images. |
|---|
| 45 | * |
|---|
| 46 | * @param string $file The image file name OR image data itself |
|---|
| 47 | * @param string $c_type The content type |
|---|
| 48 | * @param string $name The filename of the image. |
|---|
| 49 | * Only use if $file is the image data |
|---|
| 50 | * @param bool $isfilename Whether $file is a filename or not |
|---|
| 51 | * Defaults to true |
|---|
| 52 | * @param string $contentid Desired Content-ID of MIME part |
|---|
| 53 | * Defaults to generated unique ID |
|---|
| 54 | * @return mixed true on success or PEAR_Error object |
|---|
| 55 | * @access public |
|---|
| 56 | */ |
|---|
| 57 | function addHTMLImage($file, $c_type='application/octet-stream', $name = '', $isfilename = true, $contentid = '') |
|---|
| 58 | { |
|---|
| 59 | $filedata = ($isfilename === true) ? $this->_file2str($file) : $file; |
|---|
| 60 | if ($isfilename === true) { |
|---|
| 61 | $filename = ($name == '' ? $file : $name); |
|---|
| 62 | } |
|---|
| 63 | else { |
|---|
| 64 | $filename = $name; |
|---|
| 65 | } |
|---|
| 66 | |
|---|
| 67 | if (PEAR::isError($filedata)) { |
|---|
| 68 | return $filedata; |
|---|
| 69 | } |
|---|
| 70 | |
|---|
| 71 | if ($contentid == '') { |
|---|
| 72 | $contentid = md5(uniqid(time())); |
|---|
| 73 | } |
|---|
| 74 | |
|---|
| 75 | $this->_html_images[] = array( |
|---|
| 76 | 'body' => $filedata, |
|---|
| 77 | 'name' => $filename, |
|---|
| 78 | 'c_type' => $c_type, |
|---|
| 79 | 'cid' => $contentid |
|---|
| 80 | ); |
|---|
| 81 | |
|---|
| 82 | return true; |
|---|
| 83 | } |
|---|
| 84 | |
|---|
| 85 | |
|---|
| 86 | /** |
|---|
| 87 | * returns the HTML body portion of the message |
|---|
| 88 | * @return string HTML body of the message |
|---|
| 89 | * @access public |
|---|
| 90 | */ |
|---|
| 91 | function getHTMLBody() |
|---|
| 92 | { |
|---|
| 93 | return $this->_htmlbody; |
|---|
| 94 | } |
|---|
| 95 | |
|---|
| 96 | |
|---|
| 97 | /** |
|---|
| 98 | * Creates a new mimePart object, using multipart/mixed as |
|---|
| 99 | * the initial content-type and returns it during the |
|---|
| 100 | * build process. |
|---|
| 101 | * |
|---|
| 102 | * @return object The multipart/mixed mimePart object |
|---|
| 103 | * @access private |
|---|
| 104 | */ |
|---|
| 105 | function &_addMixedPart() |
|---|
| 106 | { |
|---|
| 107 | $params['content_type'] = $this->_headers['Content-Type'] ? $this->_headers['Content-Type'] : 'multipart/mixed'; |
|---|
| 108 | $ret = new Mail_mimePart('', $params); |
|---|
| 109 | return $ret; |
|---|
| 110 | } |
|---|
| 111 | |
|---|
| 112 | |
|---|
| 113 | /** |
|---|
| 114 | * Encodes a header as per RFC2047 |
|---|
| 115 | * |
|---|
| 116 | * @param array $input The header data to encode |
|---|
| 117 | * @param array $params Extra build parameters |
|---|
| 118 | * @return array Encoded data |
|---|
| 119 | * @access private |
|---|
| 120 | * @override |
|---|
| 121 | */ |
|---|
| 122 | function _encodeHeaders($input, $params = array()) |
|---|
| 123 | { |
|---|
| 124 | $maxlen = 73; |
|---|
| 125 | $params += $this->_build_params; |
|---|
| 126 | |
|---|
| 127 | foreach ($input as $hdr_name => $hdr_value) |
|---|
| 128 | { |
|---|
| 129 | // if header contains e-mail addresses |
|---|
| 130 | if (preg_match('/\s<.+@[a-z0-9\-\.]+\.[a-z]+>/U', $hdr_value)) { |
|---|
| 131 | $chunks = rcube_explode_quoted_string(',', $hdr_value); |
|---|
| 132 | } |
|---|
| 133 | else { |
|---|
| 134 | $chunks = array($hdr_value); |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | $hdr_value = ''; |
|---|
| 138 | $line_len = 0; |
|---|
| 139 | |
|---|
| 140 | foreach ($chunks as $i => $value) { |
|---|
| 141 | $value = trim($value); |
|---|
| 142 | |
|---|
| 143 | //This header contains non ASCII chars and should be encoded. |
|---|
| 144 | if (preg_match('/[\x80-\xFF]{1}/', $value)) { |
|---|
| 145 | $suffix = ''; |
|---|
| 146 | // Don't encode e-mail address |
|---|
| 147 | if (preg_match('/(.+)\s(<.+@[a-z0-9\-\.]+>)$/Ui', $value, $matches)) { |
|---|
| 148 | $value = $matches[1]; |
|---|
| 149 | $suffix = ' '.$matches[2]; |
|---|
| 150 | } |
|---|
| 151 | |
|---|
| 152 | switch ($params['head_encoding']) { |
|---|
| 153 | case 'base64': |
|---|
| 154 | // Base64 encoding has been selected. |
|---|
| 155 | $mode = 'B'; |
|---|
| 156 | $encoded = base64_encode($value); |
|---|
| 157 | break; |
|---|
| 158 | |
|---|
| 159 | case 'quoted-printable': |
|---|
| 160 | default: |
|---|
| 161 | // quoted-printable encoding has been selected |
|---|
| 162 | $mode = 'Q'; |
|---|
| 163 | // replace ?, =, _ and spaces |
|---|
| 164 | $encoded = str_replace(array('=','_','?',' '), array('=3D','=5F','=3F','_'), $value); |
|---|
| 165 | $encoded = preg_replace('/([\x80-\xFF])/e', "'='.sprintf('%02X', ord('\\1'))", $encoded); |
|---|
| 166 | } |
|---|
| 167 | |
|---|
| 168 | $value = '=?' . $params['head_charset'] . '?' . $mode . '?' . $encoded . '?=' . $suffix; |
|---|
| 169 | } |
|---|
| 170 | |
|---|
| 171 | // add chunk to output string by regarding the header maxlen |
|---|
| 172 | $len = strlen($value); |
|---|
| 173 | if ($i == 0 || $line_len + $len < $maxlen) { |
|---|
| 174 | $hdr_value .= ($i>0?', ':'') . $value; |
|---|
| 175 | $line_len += $len + ($i>0?2:0); |
|---|
| 176 | } |
|---|
| 177 | else { |
|---|
| 178 | $hdr_value .= ($i>0?', ':'') . "\n " . $value; |
|---|
| 179 | $line_len = $len; |
|---|
| 180 | } |
|---|
| 181 | } |
|---|
| 182 | |
|---|
| 183 | $input[$hdr_name] = wordwrap($hdr_value, 990, "\n", true); // hard limit header length |
|---|
| 184 | } |
|---|
| 185 | |
|---|
| 186 | return $input; |
|---|
| 187 | } |
|---|
| 188 | |
|---|
| 189 | |
|---|
| 190 | /** |
|---|
| 191 | * Provides caching of body of constructed MIME Message to avoid |
|---|
| 192 | * duplicate construction of message and damage of MIME headers |
|---|
| 193 | * |
|---|
| 194 | * @return string The mime content |
|---|
| 195 | * @access public |
|---|
| 196 | * @override |
|---|
| 197 | */ |
|---|
| 198 | public function &get($build_params = null) |
|---|
| 199 | { |
|---|
| 200 | if(empty($this->mime_content)) |
|---|
| 201 | $this->mime_content = parent::get($build_params); |
|---|
| 202 | return $this->mime_content; |
|---|
| 203 | } |
|---|
| 204 | |
|---|
| 205 | } |
|---|
| 206 | |
|---|