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 Jacobemerick\Archangel; |
||
4 | |||
5 | use Psr\Log\LoggerAwareInterface; |
||
6 | use Psr\Log\LoggerInterface; |
||
7 | use Psr\Log\NullLogger; |
||
8 | |||
9 | /** |
||
10 | * This is the main class for Archangel mailer |
||
11 | * For licensing and examples: |
||
12 | * @see https://github.com/jacobemerick/archangel |
||
13 | * |
||
14 | * @author jacobemerick (http://home.jacobemerick.com/) |
||
15 | */ |
||
16 | class Archangel implements LoggerAwareInterface |
||
17 | { |
||
18 | |||
19 | /** @var boolean $isTestMode */ |
||
20 | protected $isTestMode; |
||
21 | |||
22 | /** @var string $subject */ |
||
23 | protected $subject; |
||
24 | |||
25 | /** @var array $toAddresses */ |
||
26 | protected $toAddresses = array(); |
||
27 | |||
28 | /** @var array $headers */ |
||
29 | protected $headers = array(); |
||
30 | |||
31 | /** @var string $plainMessage */ |
||
32 | protected $plainMessage; |
||
33 | |||
34 | /** @var string $htmlMessage */ |
||
35 | protected $htmlMessage; |
||
36 | |||
37 | /** @var array $attachments */ |
||
38 | protected $attachments = array(); |
||
39 | |||
40 | /** @var string $boundaryMixed */ |
||
41 | protected $boundaryMixed; |
||
42 | |||
43 | /** @var string $boundaryAlternative */ |
||
44 | protected $boundaryAlternative; |
||
45 | |||
46 | /** @var LoggerInterface */ |
||
47 | protected $logger; |
||
48 | |||
49 | /** @var string LINE_BREAK */ |
||
50 | const LINE_BREAK = "\r\n"; |
||
51 | |||
52 | /** |
||
53 | * @param string $mailer |
||
54 | * @param boolean $isTestMode |
||
55 | */ |
||
56 | public function __construct($mailer = null, $isTestMode = false) |
||
57 | { |
||
58 | if (is_null($mailer)) { |
||
59 | $mailer = sprintf('PHP/%s', phpversion()); |
||
60 | } |
||
61 | $this->headers['X-Mailer'] = $mailer; |
||
62 | $this->isTestMode = $isTestMode; |
||
63 | |||
64 | $this->logger = new NullLogger(); |
||
65 | $this->boundaryMixed = sprintf('PHP-mixed-%s', uniqid()); |
||
66 | $this->boundaryAlternative = sprintf('PHP-alternative-%s', uniqid()); |
||
67 | } |
||
68 | |||
69 | /** |
||
70 | * @param LoggerInterface $logger |
||
71 | * |
||
72 | * @return object instantiated $this |
||
73 | */ |
||
74 | public function setLogger(LoggerInterface $logger) |
||
75 | { |
||
76 | $this->logger = $logger; |
||
77 | |||
78 | return $this; |
||
79 | } |
||
80 | |||
81 | /** |
||
82 | * Setter method for adding recipients |
||
83 | * |
||
84 | * @param string $address email address for the recipient |
||
85 | * @param string $title name of the recipient (optional) |
||
86 | |||
87 | * @return object instantiated $this |
||
88 | */ |
||
89 | public function addTo($address, $title = '') |
||
90 | { |
||
91 | array_push( |
||
92 | $this->toAddresses, |
||
93 | $this->formatEmailAddress($address, $title) |
||
94 | ); |
||
95 | |||
96 | return $this; |
||
97 | } |
||
98 | |||
99 | /** |
||
100 | * Setter method for adding cc recipients |
||
101 | * |
||
102 | * @param string $address email address for the cc recipient |
||
103 | * @param string $title name of the cc recipient (optional) |
||
104 | * |
||
105 | * @return object instantiated $this |
||
106 | */ |
||
107 | View Code Duplication | public function addCC($address, $title = '') |
|
0 ignored issues
–
show
|
|||
108 | { |
||
109 | if (!isset($this->headers['CC'])) { |
||
110 | $this->headers['CC'] = array(); |
||
111 | } |
||
112 | |||
113 | array_push( |
||
114 | $this->headers['CC'], |
||
115 | $this->formatEmailAddress($address, $title) |
||
116 | ); |
||
117 | |||
118 | return $this; |
||
119 | } |
||
120 | |||
121 | /** |
||
122 | * Setter method for adding bcc recipients |
||
123 | * |
||
124 | * @param string $address email address for the bcc recipient |
||
125 | * @param string $title name of the bcc recipient (optional) |
||
126 | * |
||
127 | * @return object instantiated $this |
||
128 | */ |
||
129 | View Code Duplication | public function addBCC($address, $title = '') |
|
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. ![]() |
|||
130 | { |
||
131 | if (!isset($this->headers['BCC'])) { |
||
132 | $this->headers['BCC'] = array(); |
||
133 | } |
||
134 | |||
135 | array_push( |
||
136 | $this->headers['BCC'], |
||
137 | $this->formatEmailAddress($address, $title) |
||
138 | ); |
||
139 | |||
140 | return $this; |
||
141 | } |
||
142 | |||
143 | /** |
||
144 | * Setter method for setting the single 'from' field |
||
145 | * |
||
146 | * @param string $address email address for the sender |
||
147 | * @param string $title name of the sender (optional) |
||
148 | * |
||
149 | * @return object instantiated $this |
||
150 | */ |
||
151 | public function setFrom($address, $title = '') |
||
152 | { |
||
153 | $this->headers['From'] = $this->formatEmailAddress($address, $title); |
||
154 | |||
155 | return $this; |
||
156 | } |
||
157 | |||
158 | /** |
||
159 | * Setter method for setting the single 'reply-to' field |
||
160 | * |
||
161 | * @param string $address email address for the reply-to |
||
162 | * @param string $title name of the reply-to (optional) |
||
163 | * |
||
164 | * @return object instantiated $this |
||
165 | */ |
||
166 | public function setReplyTo($address, $title = '') |
||
167 | { |
||
168 | $this->headers['Reply-To'] = $this->formatEmailAddress($address, $title); |
||
169 | |||
170 | return $this; |
||
171 | } |
||
172 | |||
173 | /** |
||
174 | * @param string $address |
||
175 | * @param string $title |
||
176 | * |
||
177 | * @return string |
||
178 | */ |
||
179 | protected function formatEmailAddress($address, $title) |
||
180 | { |
||
181 | if (!empty($title)) { |
||
182 | $address = sprintf('"%s" <%s>', $title, $address); |
||
183 | } |
||
184 | return $address; |
||
185 | } |
||
186 | |||
187 | /** |
||
188 | * Setter method for setting a subject |
||
189 | * |
||
190 | * @param string $subject subject for the email |
||
191 | * |
||
192 | * @return object instantiated $this |
||
193 | */ |
||
194 | public function setSubject($subject) |
||
195 | { |
||
196 | $this->subject = $subject; |
||
197 | |||
198 | return $this; |
||
199 | } |
||
200 | |||
201 | /** |
||
202 | * Setter method for the plain text message |
||
203 | * |
||
204 | * @param string $message the plain-text message |
||
205 | * |
||
206 | * @return object instantiated $this |
||
207 | */ |
||
208 | public function setPlainMessage($message) |
||
209 | { |
||
210 | $this->plainMessage = $message; |
||
211 | |||
212 | return $this; |
||
213 | } |
||
214 | |||
215 | /** |
||
216 | * Setter method for the html message |
||
217 | * |
||
218 | * @param string $message the html message |
||
219 | * |
||
220 | * @return object instantiated $this |
||
221 | */ |
||
222 | public function setHTMLMessage($message) |
||
223 | { |
||
224 | $this->htmlMessage = $message; |
||
225 | |||
226 | return $this; |
||
227 | } |
||
228 | |||
229 | /** |
||
230 | * Setter method for adding attachments |
||
231 | * |
||
232 | * @param string $path the full path of the attachment |
||
233 | * @param string $type mime type of the file |
||
234 | * @param string $title the title of the attachment (optional) |
||
235 | * |
||
236 | * @return object instantiated $this |
||
237 | */ |
||
238 | public function addAttachment($path, $type, $title = '') |
||
239 | { |
||
240 | array_push($this->attachments, array( |
||
241 | 'path' => $path, |
||
242 | 'type' => $type, |
||
243 | 'title' => $title, |
||
244 | )); |
||
245 | |||
246 | return $this; |
||
247 | } |
||
248 | |||
249 | /** |
||
250 | * The executing step, the actual sending of the email |
||
251 | * First checks to make sure the minimum fields are set (returns false if they are not) |
||
252 | * Second it attempts to send the mail with php's mail() (returns false if it fails) |
||
253 | * |
||
254 | * @return boolean whether or not the email was valid & sent |
||
255 | */ |
||
256 | public function send() |
||
257 | { |
||
258 | if (!$this->checkRequiredFields()) { |
||
259 | $this->logger->error('Minimum required fields not filled out, cannot send Archangel mail.'); |
||
260 | return false; |
||
261 | } |
||
262 | |||
263 | $recipients = $this->buildTo(); |
||
264 | $subject = $this->subject; |
||
265 | $message = (empty($this->attachments)) ? $this->buildMessage() : $this->buildMessageWithAttachments(); |
||
266 | $headers = $this->buildHeaders(); |
||
267 | |||
268 | $debugMessage = array( |
||
269 | 'Triggered send on Archangel mail.', |
||
270 | "Recipients: {$recipients}", |
||
271 | "Subject: {$subject}", |
||
272 | "Message: {$message}", |
||
273 | "Headers: {$headers}", |
||
274 | ); |
||
275 | $this->logger->debug(implode(' || ', $debugMessage)); |
||
276 | |||
277 | if ($this->isTestMode) { |
||
278 | return true; |
||
279 | } |
||
280 | return mail($recipients, $subject, $message, $headers); |
||
281 | } |
||
282 | |||
283 | /** |
||
284 | * Call to check the minimum required fields |
||
285 | * |
||
286 | * @return boolean whether or not the email meets the minimum required fields |
||
287 | */ |
||
288 | protected function checkRequiredFields() |
||
289 | { |
||
290 | if (empty($this->toAddresses)) { |
||
291 | return false; |
||
292 | } |
||
293 | if (empty($this->subject)) { |
||
294 | return false; |
||
295 | } |
||
296 | |||
297 | if (empty($this->plainMessage) && empty($this->htmlMessage) && empty($this->attachments)) { |
||
298 | return false; |
||
299 | } |
||
300 | |||
301 | return true; |
||
302 | } |
||
303 | |||
304 | /** |
||
305 | * Build the recipients from 'to' |
||
306 | * |
||
307 | * @return string comma-separated lit of recipients |
||
308 | */ |
||
309 | protected function buildTo() |
||
310 | { |
||
311 | return implode(', ', $this->toAddresses); |
||
312 | } |
||
313 | |||
314 | /** |
||
315 | * Returns a simple email message without attachments |
||
316 | * |
||
317 | * @return string email message |
||
318 | */ |
||
319 | protected function buildMessage() |
||
320 | { |
||
321 | if (empty($this->plainMessage) && empty($this->htmlMessage)) { |
||
322 | return ''; |
||
323 | } |
||
324 | if (!empty($this->plainMessage) && empty($this->htmlMessage)) { |
||
325 | return $this->plainMessage; |
||
326 | } |
||
327 | if (empty($this->plainMessage) && !empty($this->htmlMessage)) { |
||
328 | return $this->htmlMessage; |
||
329 | } |
||
330 | |||
331 | $message = array(); |
||
332 | array_push($message, "--{$this->boundaryAlternative}"); |
||
333 | $message = array_merge($message, $this->buildPlainMessageHeader()); |
||
334 | array_push($message, $this->plainMessage); |
||
335 | array_push($message, "--{$this->boundaryAlternative}"); |
||
336 | $message = array_merge($message, $this->buildHtmlMessageHeader()); |
||
337 | array_push($message, $this->htmlMessage); |
||
338 | array_push($message, "--{$this->boundaryAlternative}--"); |
||
339 | |||
340 | return implode(self::LINE_BREAK, $message); |
||
341 | } |
||
342 | |||
343 | /** |
||
344 | * Build multi-part message with attachments |
||
345 | * |
||
346 | * @return string email message |
||
347 | */ |
||
348 | protected function buildMessageWithAttachments() |
||
349 | { |
||
350 | $message = array(); |
||
351 | |||
352 | View Code Duplication | if (!empty($this->plainMessage) || !empty($this->htmlMessage)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
353 | array_push($message, "--{$this->boundaryMixed}"); |
||
354 | } |
||
355 | |||
356 | if (!empty($this->plainMessage) && !empty($this->htmlMessage)) { |
||
357 | array_push($message, "Content-Type: multipart/alternative; boundary={$this->boundaryAlternative}"); |
||
358 | array_push($message, ''); |
||
359 | array_push($message, "--{$this->boundaryAlternative}"); |
||
360 | $message = array_merge($message, $this->buildPlainMessageHeader()); |
||
361 | array_push($message, $this->plainMessage); |
||
362 | array_push($message, "--{$this->boundaryAlternative}"); |
||
363 | $message = array_merge($message, $this->buildHtmlMessageHeader()); |
||
364 | array_push($message, $this->htmlMessage); |
||
365 | array_push($message, "--{$this->boundaryAlternative}--"); |
||
366 | array_push($message, ''); |
||
367 | } elseif (!empty($this->plainMessage)) { |
||
368 | $message = array_merge($message, $this->buildPlainMessageHeader()); |
||
369 | array_push($message, $this->plainMessage); |
||
370 | } elseif (!empty($this->htmlMessage)) { |
||
371 | $message = array_merge($message, $this->buildHtmlMessageHeader()); |
||
372 | array_push($message, $this->htmlMessage); |
||
373 | } |
||
374 | foreach ($this->attachments as $attachment) { |
||
375 | array_push($message, "--{$this->boundaryMixed}"); |
||
376 | array_push($message, "Content-Type: {$attachment['type']}; name=\"{$attachment['title']}\""); |
||
377 | array_push($message, 'Content-Transfer-Encoding: base64'); |
||
378 | array_push($message, 'Content-Disposition: attachment'); |
||
379 | array_push($message, ''); |
||
380 | array_push($message, $this->buildAttachmentContent($attachment['path'])); |
||
381 | } |
||
382 | array_push($message, "--{$this->boundaryMixed}--"); |
||
383 | |||
384 | return implode(self::LINE_BREAK, $message); |
||
385 | } |
||
386 | |||
387 | |||
388 | /** |
||
389 | * Shared holder for the plain message header |
||
390 | * |
||
391 | * @return array |
||
392 | */ |
||
393 | protected function buildPlainMessageHeader() |
||
394 | { |
||
395 | return array( |
||
396 | 'Content-Type: text/plain; charset="iso-8859"', |
||
397 | 'Content-Transfer-Encoding: 7bit', |
||
398 | '', |
||
399 | ); |
||
400 | } |
||
401 | |||
402 | /** |
||
403 | * Shared holder for the html message header |
||
404 | * |
||
405 | * @return array |
||
406 | */ |
||
407 | protected function buildHtmlMessageHeader() |
||
408 | { |
||
409 | return array( |
||
410 | 'Content-Type: text/html; charset="iso-8859-1"', |
||
411 | 'Content-Transfer-Encoding: 7bit', |
||
412 | '', |
||
413 | ); |
||
414 | } |
||
415 | |||
416 | /** |
||
417 | * Builder for the additional headers needed for multipart emails |
||
418 | * |
||
419 | * @return string headers needed for multipart |
||
420 | */ |
||
421 | protected function buildHeaders() |
||
422 | { |
||
423 | $headers = array(); |
||
424 | foreach ($this->headers as $key => $value) { |
||
425 | if ($key == 'CC' || $key == 'BCC') { |
||
426 | $value = implode(', ', $value); |
||
427 | } |
||
428 | array_push($headers, sprintf('%s: %s', $key, $value)); |
||
429 | } |
||
430 | |||
431 | if (!empty($this->attachments)) { |
||
432 | array_push( |
||
433 | $headers, |
||
434 | "Content-Type: multipart/mixed; boundary=\"{$this->boundaryMixed}\"" |
||
435 | ); |
||
436 | View Code Duplication | } elseif (!empty($this->plainMessage) && !empty($this->htmlMessage)) { |
|
0 ignored issues
–
show
This code seems to be duplicated across 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. ![]() |
|||
437 | array_push( |
||
438 | $headers, |
||
439 | "Content-Type: multipart/alternative; boundary=\"{$this->boundaryAlternative}\"" |
||
440 | ); |
||
441 | } elseif (!empty($this->htmlMessage)) { |
||
442 | array_push( |
||
443 | $headers, |
||
444 | 'Content-type: text/html; charset="iso-8859-1"' |
||
445 | ); |
||
446 | } |
||
447 | |||
448 | return implode(self::LINE_BREAK, $headers); |
||
449 | } |
||
450 | |||
451 | /** |
||
452 | * File reader for attachments |
||
453 | * |
||
454 | * @param string $path filepath of the attachment |
||
455 | * |
||
456 | * @return string binary representation of file, base64'd |
||
457 | */ |
||
458 | protected function buildAttachmentContent($path) |
||
459 | { |
||
460 | if (!file_exists($path)) { |
||
461 | $this->logger->error("Could not find file {$path} for attaching to Archangel mail."); |
||
462 | return ''; |
||
463 | } |
||
464 | |||
465 | $handle = fopen($path, 'r'); |
||
466 | $contents = fread($handle, filesize($path)); |
||
467 | fclose($handle); |
||
468 | |||
469 | $contents = base64_encode($contents); |
||
470 | $contents = chunk_split($contents); |
||
471 | return $contents; |
||
472 | } |
||
473 | } |
||
474 |
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.