This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | |||
3 | namespace Ddeboer\Imap; |
||
4 | |||
5 | use Ddeboer\Imap\Exception\MessageDoesNotExistException; |
||
6 | use Ddeboer\Imap\Message\EmailAddress; |
||
7 | use Ddeboer\Imap\Exception\MessageDeleteException; |
||
8 | use Ddeboer\Imap\Exception\MessageMoveException; |
||
9 | |||
10 | /** |
||
11 | * An IMAP message (e-mail) |
||
12 | */ |
||
13 | class Message extends Message\Part |
||
14 | { |
||
15 | private $headers; |
||
16 | private $attachments; |
||
17 | |||
18 | /** |
||
19 | * @var boolean |
||
20 | */ |
||
21 | private $keepUnseen = false; |
||
22 | |||
23 | /** |
||
24 | * Constructor |
||
25 | * |
||
26 | * @param resource $stream IMAP stream |
||
27 | * @param int $messageNumber Message number |
||
28 | */ |
||
29 | public function __construct($stream, $messageNumber) { |
||
30 | $this->stream = $stream; |
||
31 | $this->messageNumber = $messageNumber; |
||
32 | |||
33 | $this->loadStructure(); |
||
34 | } |
||
35 | |||
36 | /** |
||
37 | * Get message id |
||
38 | * |
||
39 | * A unique message id in the form <...> |
||
40 | * |
||
41 | * @return string |
||
42 | */ |
||
43 | public function getId() |
||
44 | { |
||
45 | return $this->getHeaders()->get('message_id'); |
||
46 | } |
||
47 | |||
48 | /** |
||
49 | * Get message sender (from headers) |
||
50 | * |
||
51 | * @return EmailAddress |
||
52 | */ |
||
53 | public function getFrom() |
||
54 | { |
||
55 | return $this->getHeaders()->get('from'); |
||
56 | } |
||
57 | |||
58 | /** |
||
59 | * Get To recipients |
||
60 | * |
||
61 | * @return EmailAddress[] Empty array in case message has no To: recipients |
||
62 | */ |
||
63 | public function getTo() |
||
64 | { |
||
65 | return $this->getHeaders()->get('to') ?: []; |
||
66 | } |
||
67 | |||
68 | /** |
||
69 | * Get Cc recipients |
||
70 | * |
||
71 | * @return EmailAddress[] Empty array in case message has no CC: recipients |
||
72 | */ |
||
73 | public function getCc() |
||
74 | { |
||
75 | return $this->getHeaders()->get('cc') ?: []; |
||
76 | } |
||
77 | |||
78 | /** |
||
79 | * Get message number (from headers) |
||
80 | * |
||
81 | * @return int |
||
82 | */ |
||
83 | public function getNumber() |
||
84 | { |
||
85 | return $this->messageNumber; |
||
86 | } |
||
87 | |||
88 | /** |
||
89 | * Get date (from headers) |
||
90 | * |
||
91 | * @return \DateTime |
||
92 | */ |
||
93 | public function getDate() |
||
94 | { |
||
95 | return $this->getHeaders()->get('date'); |
||
96 | } |
||
97 | |||
98 | /** |
||
99 | * Get message size (from headers) |
||
100 | * |
||
101 | * @return int |
||
102 | */ |
||
103 | public function getSize() |
||
104 | { |
||
105 | return $this->getHeaders()->get('size'); |
||
106 | } |
||
107 | |||
108 | /** |
||
109 | * Get raw part content |
||
110 | * |
||
111 | * @return string |
||
112 | */ |
||
113 | public function getContent($keepUnseen = false) |
||
114 | { |
||
115 | // Null headers, so subsequent calls to getHeaders() will return |
||
116 | // updated seen flag |
||
117 | $this->headers = null; |
||
118 | |||
119 | return $this->doGetContent($this->keepUnseen ? $this->keepUnseen : $keepUnseen); |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * Get message answered flag value (from headers) |
||
124 | * |
||
125 | * @return boolean |
||
126 | */ |
||
127 | public function isAnswered() |
||
128 | { |
||
129 | return $this->getHeaders()->get('answered'); |
||
130 | } |
||
131 | |||
132 | /** |
||
133 | * Get message deleted flag value (from headers) |
||
134 | * |
||
135 | * @return boolean |
||
136 | */ |
||
137 | public function isDeleted() |
||
138 | { |
||
139 | return $this->getHeaders()->get('deleted'); |
||
140 | } |
||
141 | |||
142 | /** |
||
143 | * Get message draft flag value (from headers) |
||
144 | * |
||
145 | * @return boolean |
||
146 | */ |
||
147 | public function isDraft() |
||
148 | { |
||
149 | return $this->getHeaders()->get('draft'); |
||
150 | } |
||
151 | |||
152 | /** |
||
153 | * Has the message been marked as read? |
||
154 | * |
||
155 | * @return boolean |
||
156 | */ |
||
157 | public function isSeen() |
||
158 | { |
||
159 | return 'U' != $this->getHeaders()->get('unseen'); |
||
160 | } |
||
161 | |||
162 | /** |
||
163 | * Get message subject (from headers) |
||
164 | * |
||
165 | * @return string |
||
166 | */ |
||
167 | public function getSubject() |
||
168 | { |
||
169 | return $this->getHeaders()->get('subject'); |
||
170 | } |
||
171 | |||
172 | /** |
||
173 | * Get message headers |
||
174 | * |
||
175 | * @return Message\Headers |
||
176 | */ |
||
177 | public function getHeaders() |
||
178 | { |
||
179 | if (null === $this->headers) { |
||
180 | // imap_header is much faster than imap_fetchheader |
||
181 | // imap_header returns only a subset of all mail headers, |
||
182 | // but it does include the message flags. |
||
183 | $headers = imap_header($this->stream, imap_msgno($this->stream, $this->messageNumber)); |
||
184 | $this->headers = new Message\Headers($headers); |
||
185 | } |
||
186 | |||
187 | return $this->headers; |
||
188 | } |
||
189 | |||
190 | /** |
||
191 | * Get body HTML |
||
192 | * |
||
193 | * @return string | null Null if message has no HTML message part |
||
194 | */ |
||
195 | View Code Duplication | public function getBodyHtml() |
|
0 ignored issues
–
show
|
|||
196 | { |
||
197 | $iterator = new \RecursiveIteratorIterator($this, \RecursiveIteratorIterator::SELF_FIRST); |
||
198 | foreach ($iterator as $part) { |
||
199 | if ($part->getSubtype() == 'HTML') { |
||
200 | return $part->getDecodedContent($this->keepUnseen); |
||
201 | } |
||
202 | } |
||
203 | } |
||
204 | |||
205 | /** |
||
206 | * Get body text |
||
207 | * |
||
208 | * @return string |
||
209 | */ |
||
210 | View Code Duplication | public function getBodyText() |
|
0 ignored issues
–
show
This method seems to be duplicated in your project.
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation. You can also find more detailed suggestions in the “Code” section of your repository. ![]() |
|||
211 | { |
||
212 | $iterator = new \RecursiveIteratorIterator($this, \RecursiveIteratorIterator::SELF_FIRST); |
||
213 | foreach ($iterator as $part) { |
||
214 | if ($part->getSubtype() == 'PLAIN') { |
||
215 | return $part->getDecodedContent($this->keepUnseen); |
||
216 | } |
||
217 | } |
||
218 | |||
219 | // If message has no parts, return content of message itself. |
||
220 | return $this->getDecodedContent($this->keepUnseen); |
||
221 | } |
||
222 | |||
223 | /** |
||
224 | * Get attachments (if any) linked to this e-mail |
||
225 | * |
||
226 | * @return Message\Attachment[] |
||
227 | */ |
||
228 | public function getAttachments() |
||
229 | { |
||
230 | if (null === $this->attachments) { |
||
231 | $this->attachments = array(); |
||
232 | foreach ($this->getParts() as $part) { |
||
233 | if ($part instanceof Message\Attachment) { |
||
234 | $this->attachments[] = $part; |
||
235 | } |
||
236 | if ($part->hasChildren()) { |
||
237 | foreach ($part->getParts() as $child_part) { |
||
238 | if ($child_part instanceof Message\Attachment) { |
||
239 | $this->attachments[] = $child_part; |
||
240 | } |
||
241 | } |
||
242 | } |
||
243 | } |
||
244 | } |
||
245 | |||
246 | return $this->attachments; |
||
247 | } |
||
248 | |||
249 | /** |
||
250 | * Does this message have attachments? |
||
251 | * |
||
252 | * @return bool |
||
253 | */ |
||
254 | public function hasAttachments() |
||
255 | { |
||
256 | return count($this->getAttachments()) > 0; |
||
257 | } |
||
258 | |||
259 | /** |
||
260 | * Delete message |
||
261 | * |
||
262 | * @throws MessageDeleteException |
||
263 | */ |
||
264 | public function delete() |
||
265 | { |
||
266 | // 'deleted' header changed, force to reload headers, would be better to set deleted flag to true on header |
||
267 | $this->headers = null; |
||
268 | |||
269 | if (!imap_delete($this->stream, $this->messageNumber, \FT_UID)) { |
||
270 | throw new MessageDeleteException($this->messageNumber); |
||
271 | } |
||
272 | |||
273 | imap_expunge($this->stream); |
||
274 | } |
||
275 | |||
276 | /** |
||
277 | * Move message to another mailbox |
||
278 | * @param Mailbox $mailbox |
||
279 | * |
||
280 | * @throws MessageMoveException |
||
281 | * @return Message |
||
282 | */ |
||
283 | public function move(Mailbox $mailbox) |
||
284 | { |
||
285 | if (!imap_mail_move($this->stream, $this->messageNumber, $mailbox->getName(), \CP_UID)) { |
||
286 | throw new MessageMoveException($this->messageNumber, $mailbox->getName()); |
||
287 | } |
||
288 | |||
289 | imap_expunge($this->stream); |
||
290 | |||
291 | return $this; |
||
292 | } |
||
293 | |||
294 | /** |
||
295 | * Prevent the message from being marked as seen |
||
296 | * |
||
297 | * Defaults to true, so messages that are read will be still marked as unseen. |
||
298 | * |
||
299 | * @param bool $bool |
||
300 | * |
||
301 | * @return Message |
||
302 | */ |
||
303 | public function keepUnseen($bool = true) |
||
304 | { |
||
305 | $this->keepUnseen = (bool) $bool; |
||
306 | |||
307 | return $this; |
||
308 | } |
||
309 | |||
310 | /** |
||
311 | * Load message structure |
||
312 | */ |
||
313 | private function loadStructure() |
||
314 | { |
||
315 | set_error_handler( |
||
316 | function ($nr, $error) { |
||
317 | throw new MessageDoesNotExistException( |
||
318 | $this->messageNumber, |
||
319 | $error |
||
320 | ); |
||
321 | } |
||
322 | ); |
||
323 | |||
324 | $structure = imap_fetchstructure( |
||
325 | $this->stream, |
||
326 | $this->messageNumber, |
||
327 | \FT_UID |
||
328 | ); |
||
329 | |||
330 | restore_error_handler(); |
||
331 | |||
332 | $this->parseStructure($structure); |
||
333 | } |
||
334 | } |
||
335 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.