|
1 <?php |
|
2 /** |
|
3 * Zend Framework |
|
4 * |
|
5 * LICENSE |
|
6 * |
|
7 * This source file is subject to the new BSD license that is bundled |
|
8 * with this package in the file LICENSE.txt. |
|
9 * It is also available through the world-wide-web at this URL: |
|
10 * http://framework.zend.com/license/new-bsd |
|
11 * If you did not receive a copy of the license and are unable to |
|
12 * obtain it through the world-wide-web, please send an email |
|
13 * to license@zend.com so we can send you a copy immediately. |
|
14 * |
|
15 * @category Zend |
|
16 * @package Zend_Mime |
|
17 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
18 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
19 * @version $Id: Message.php 20096 2010-01-06 02:05:09Z bkarwin $ |
|
20 */ |
|
21 |
|
22 |
|
23 /** |
|
24 * Zend_Mime |
|
25 */ |
|
26 require_once 'Zend/Mime.php'; |
|
27 |
|
28 /** |
|
29 * Zend_Mime_Part |
|
30 */ |
|
31 require_once 'Zend/Mime/Part.php'; |
|
32 |
|
33 |
|
34 /** |
|
35 * @category Zend |
|
36 * @package Zend_Mime |
|
37 * @copyright Copyright (c) 2005-2010 Zend Technologies USA Inc. (http://www.zend.com) |
|
38 * @license http://framework.zend.com/license/new-bsd New BSD License |
|
39 */ |
|
40 class Zend_Mime_Message |
|
41 { |
|
42 |
|
43 protected $_parts = array(); |
|
44 protected $_mime = null; |
|
45 |
|
46 /** |
|
47 * Returns the list of all Zend_Mime_Parts in the message |
|
48 * |
|
49 * @return array of Zend_Mime_Part |
|
50 */ |
|
51 public function getParts() |
|
52 { |
|
53 return $this->_parts; |
|
54 } |
|
55 |
|
56 /** |
|
57 * Sets the given array of Zend_Mime_Parts as the array for the message |
|
58 * |
|
59 * @param array $parts |
|
60 */ |
|
61 public function setParts($parts) |
|
62 { |
|
63 $this->_parts = $parts; |
|
64 } |
|
65 |
|
66 /** |
|
67 * Append a new Zend_Mime_Part to the current message |
|
68 * |
|
69 * @param Zend_Mime_Part $part |
|
70 */ |
|
71 public function addPart(Zend_Mime_Part $part) |
|
72 { |
|
73 /** |
|
74 * @todo check for duplicate object handle |
|
75 */ |
|
76 $this->_parts[] = $part; |
|
77 } |
|
78 |
|
79 /** |
|
80 * Check if message needs to be sent as multipart |
|
81 * MIME message or if it has only one part. |
|
82 * |
|
83 * @return boolean |
|
84 */ |
|
85 public function isMultiPart() |
|
86 { |
|
87 return (count($this->_parts) > 1); |
|
88 } |
|
89 |
|
90 /** |
|
91 * Set Zend_Mime object for the message |
|
92 * |
|
93 * This can be used to set the boundary specifically or to use a subclass of |
|
94 * Zend_Mime for generating the boundary. |
|
95 * |
|
96 * @param Zend_Mime $mime |
|
97 */ |
|
98 public function setMime(Zend_Mime $mime) |
|
99 { |
|
100 $this->_mime = $mime; |
|
101 } |
|
102 |
|
103 /** |
|
104 * Returns the Zend_Mime object in use by the message |
|
105 * |
|
106 * If the object was not present, it is created and returned. Can be used to |
|
107 * determine the boundary used in this message. |
|
108 * |
|
109 * @return Zend_Mime |
|
110 */ |
|
111 public function getMime() |
|
112 { |
|
113 if ($this->_mime === null) { |
|
114 $this->_mime = new Zend_Mime(); |
|
115 } |
|
116 |
|
117 return $this->_mime; |
|
118 } |
|
119 |
|
120 /** |
|
121 * Generate MIME-compliant message from the current configuration |
|
122 * |
|
123 * This can be a multipart message if more than one MIME part was added. If |
|
124 * only one part is present, the content of this part is returned. If no |
|
125 * part had been added, an empty string is returned. |
|
126 * |
|
127 * Parts are seperated by the mime boundary as defined in Zend_Mime. If |
|
128 * {@link setMime()} has been called before this method, the Zend_Mime |
|
129 * object set by this call will be used. Otherwise, a new Zend_Mime object |
|
130 * is generated and used. |
|
131 * |
|
132 * @param string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND} |
|
133 * @return string |
|
134 */ |
|
135 public function generateMessage($EOL = Zend_Mime::LINEEND) |
|
136 { |
|
137 if (! $this->isMultiPart()) { |
|
138 $body = array_shift($this->_parts); |
|
139 $body = $body->getContent($EOL); |
|
140 } else { |
|
141 $mime = $this->getMime(); |
|
142 |
|
143 $boundaryLine = $mime->boundaryLine($EOL); |
|
144 $body = 'This is a message in Mime Format. If you see this, ' |
|
145 . "your mail reader does not support this format." . $EOL; |
|
146 |
|
147 foreach (array_keys($this->_parts) as $p) { |
|
148 $body .= $boundaryLine |
|
149 . $this->getPartHeaders($p, $EOL) |
|
150 . $EOL |
|
151 . $this->getPartContent($p, $EOL); |
|
152 } |
|
153 |
|
154 $body .= $mime->mimeEnd($EOL); |
|
155 } |
|
156 |
|
157 return trim($body); |
|
158 } |
|
159 |
|
160 /** |
|
161 * Get the headers of a given part as an array |
|
162 * |
|
163 * @param int $partnum |
|
164 * @return array |
|
165 */ |
|
166 public function getPartHeadersArray($partnum) |
|
167 { |
|
168 return $this->_parts[$partnum]->getHeadersArray(); |
|
169 } |
|
170 |
|
171 /** |
|
172 * Get the headers of a given part as a string |
|
173 * |
|
174 * @param int $partnum |
|
175 * @return string |
|
176 */ |
|
177 public function getPartHeaders($partnum, $EOL = Zend_Mime::LINEEND) |
|
178 { |
|
179 return $this->_parts[$partnum]->getHeaders($EOL); |
|
180 } |
|
181 |
|
182 /** |
|
183 * Get the (encoded) content of a given part as a string |
|
184 * |
|
185 * @param int $partnum |
|
186 * @return string |
|
187 */ |
|
188 public function getPartContent($partnum, $EOL = Zend_Mime::LINEEND) |
|
189 { |
|
190 return $this->_parts[$partnum]->getContent($EOL); |
|
191 } |
|
192 |
|
193 /** |
|
194 * Explode MIME multipart string into seperate parts |
|
195 * |
|
196 * Parts consist of the header and the body of each MIME part. |
|
197 * |
|
198 * @param string $body |
|
199 * @param string $boundary |
|
200 * @return array |
|
201 */ |
|
202 protected static function _disassembleMime($body, $boundary) |
|
203 { |
|
204 $start = 0; |
|
205 $res = array(); |
|
206 // find every mime part limiter and cut out the |
|
207 // string before it. |
|
208 // the part before the first boundary string is discarded: |
|
209 $p = strpos($body, '--'.$boundary."\n", $start); |
|
210 if ($p === false) { |
|
211 // no parts found! |
|
212 return array(); |
|
213 } |
|
214 |
|
215 // position after first boundary line |
|
216 $start = $p + 3 + strlen($boundary); |
|
217 |
|
218 while (($p = strpos($body, '--' . $boundary . "\n", $start)) !== false) { |
|
219 $res[] = substr($body, $start, $p-$start); |
|
220 $start = $p + 3 + strlen($boundary); |
|
221 } |
|
222 |
|
223 // no more parts, find end boundary |
|
224 $p = strpos($body, '--' . $boundary . '--', $start); |
|
225 if ($p===false) { |
|
226 throw new Zend_Exception('Not a valid Mime Message: End Missing'); |
|
227 } |
|
228 |
|
229 // the remaining part also needs to be parsed: |
|
230 $res[] = substr($body, $start, $p-$start); |
|
231 return $res; |
|
232 } |
|
233 |
|
234 /** |
|
235 * Decodes a MIME encoded string and returns a Zend_Mime_Message object with |
|
236 * all the MIME parts set according to the given string |
|
237 * |
|
238 * @param string $message |
|
239 * @param string $boundary |
|
240 * @param string $EOL EOL string; defaults to {@link Zend_Mime::LINEEND} |
|
241 * @return Zend_Mime_Message |
|
242 */ |
|
243 public static function createFromMessage($message, $boundary, $EOL = Zend_Mime::LINEEND) |
|
244 { |
|
245 require_once 'Zend/Mime/Decode.php'; |
|
246 $parts = Zend_Mime_Decode::splitMessageStruct($message, $boundary, $EOL); |
|
247 |
|
248 $res = new self(); |
|
249 foreach ($parts as $part) { |
|
250 // now we build a new MimePart for the current Message Part: |
|
251 $newPart = new Zend_Mime_Part($part['body']); |
|
252 foreach ($part['header'] as $key => $value) { |
|
253 /** |
|
254 * @todo check for characterset and filename |
|
255 */ |
|
256 switch(strtolower($key)) { |
|
257 case 'content-type': |
|
258 $newPart->type = $value; |
|
259 break; |
|
260 case 'content-transfer-encoding': |
|
261 $newPart->encoding = $value; |
|
262 break; |
|
263 case 'content-id': |
|
264 $newPart->id = trim($value,'<>'); |
|
265 break; |
|
266 case 'content-disposition': |
|
267 $newPart->disposition = $value; |
|
268 break; |
|
269 case 'content-description': |
|
270 $newPart->description = $value; |
|
271 break; |
|
272 case 'content-location': |
|
273 $newPart->location = $value; |
|
274 break; |
|
275 case 'content-language': |
|
276 $newPart->language = $value; |
|
277 break; |
|
278 default: |
|
279 throw new Zend_Exception('Unknown header ignored for MimePart:' . $key); |
|
280 } |
|
281 } |
|
282 $res->addPart($newPart); |
|
283 } |
|
284 return $res; |
|
285 } |
|
286 } |