jacobemerick /
archangel
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
| 1 | <?php |
||
| 2 | |||
| 3 | /** |
||
| 4 | * This is the main class for Archangel mailer |
||
| 5 | * For licensing and examples: |
||
| 6 | * |
||
| 7 | * @see https://github.com/jacobemerick/archangel |
||
| 8 | * |
||
| 9 | * @author jacobemerick (http://home.jacobemerick.com/) |
||
| 10 | * @version 1.0 (2013-04-12) |
||
| 11 | */ |
||
| 12 | |||
| 13 | final class Archangel |
||
| 14 | { |
||
| 15 | |||
| 16 | /** |
||
| 17 | * These variables are set with setter methods below |
||
| 18 | */ |
||
| 19 | private $subject; |
||
| 20 | private $reply_to; |
||
| 21 | private $plain_message; |
||
| 22 | private $html_message; |
||
| 23 | |||
| 24 | /** |
||
| 25 | * Holder for error handling and validation |
||
| 26 | */ |
||
| 27 | private $passed_validation = TRUE; |
||
| 28 | private $validation_error = array(); |
||
| 29 | |||
| 30 | /** |
||
| 31 | * Holders for some of the more list-y variable handling |
||
| 32 | */ |
||
| 33 | private $to_array = array(); |
||
| 34 | private $cc_array = array(); |
||
| 35 | private $bcc_array = array(); |
||
| 36 | private $header_array = array(); |
||
| 37 | private $attachment_array = array(); |
||
| 38 | |||
| 39 | /** |
||
| 40 | * Static pieces that really don't need to change |
||
| 41 | */ |
||
| 42 | private static $MAILER = 'PHP/%s'; |
||
| 43 | private static $LINE_BREAK = "\r\n"; |
||
| 44 | private static $BOUNDARY_FORMAT = 'PHP-mixed-%s'; |
||
| 45 | private static $BOUNDARY_SALT = 'Boundary Salt'; |
||
| 46 | private static $ALTERNATIVE_BOUNDARY_FORMAT = 'PHP-alternative-%s'; |
||
| 47 | private static $ALTERNATIVE_BOUNDARY_SALT = 'Alternative Boundary Salt'; |
||
| 48 | |||
| 49 | /** |
||
| 50 | * Standard constructor, sets some of the base (unchanging) fields |
||
| 51 | */ |
||
| 52 | public function __construct() |
||
| 53 | { |
||
| 54 | $this->header_array['X-Mailer'] = sprintf(self::$MAILER, phpversion()); |
||
| 55 | } |
||
| 56 | |||
| 57 | /** |
||
| 58 | * Setter method for adding recipients |
||
| 59 | * This class only sends a single email, so all recipients can see each other |
||
| 60 | * |
||
| 61 | * @param string $address email address for the recipient |
||
| 62 | * @param string $title name of the recipient (optional) |
||
| 63 | * @return object instantiated $this |
||
| 64 | */ |
||
| 65 | View Code Duplication | public function addTo($address, $title = '') |
|
| 66 | { |
||
| 67 | if($this->is_valid_email_address($address) && $this->is_valid_email_title($title)) |
||
| 68 | $this->to_array[] = ($title != '') ? "\"{$title}\" <{$address}>" : "{$address}"; |
||
| 69 | |||
| 70 | return $this; |
||
| 71 | } |
||
| 72 | |||
| 73 | /** |
||
| 74 | * Setter method for adding cc recipients |
||
| 75 | * |
||
| 76 | * @param string $address email address for the cc recipient |
||
| 77 | * @param string $title name of the cc recipient (optional) |
||
| 78 | * @return object instantiated $this |
||
| 79 | */ |
||
| 80 | View Code Duplication | public function addCC($address, $title = '') |
|
| 81 | { |
||
| 82 | if($this->is_valid_email_address($address) && $this->is_valid_email_title($title)) |
||
| 83 | $this->cc_array[] = ($title != '') ? "\"{$title}\" <{$address}>" : "{$address}"; |
||
| 84 | |||
| 85 | return $this; |
||
| 86 | } |
||
| 87 | |||
| 88 | /** |
||
| 89 | * Setter method for adding bcc recipients |
||
| 90 | * |
||
| 91 | * @param string $address email address for the bcc recipient |
||
| 92 | * @param string $title name of the bcc recipient (optional) |
||
| 93 | * @return object instantiated $this |
||
| 94 | */ |
||
| 95 | View Code Duplication | public function addBCC($address, $title = '') |
|
| 96 | { |
||
| 97 | if($this->is_valid_email_address($address) && $this->is_valid_email_title($title)) |
||
| 98 | $this->bcc_array[] = ($title != '') ? "\"{$title}\" <{$address}>" : "{$address}"; |
||
| 99 | |||
| 100 | return $this; |
||
| 101 | } |
||
| 102 | |||
| 103 | /** |
||
| 104 | * Setter method for setting the single 'from' field |
||
| 105 | * |
||
| 106 | * @param string $address email address for the sender |
||
| 107 | * @param string $title name of the sender (optional) |
||
| 108 | * @return object instantiated $this |
||
| 109 | */ |
||
| 110 | View Code Duplication | public function setFrom($address, $title = '') |
|
| 111 | { |
||
| 112 | if($this->is_valid_email_address($address) && $this->is_valid_email_title($title)) |
||
| 113 | $this->header_array['From'] = ($title != '') ? "\"{$title}\" <{$address}>" : "{$address}"; |
||
| 114 | |||
| 115 | return $this; |
||
| 116 | } |
||
| 117 | |||
| 118 | /** |
||
| 119 | * Setter method for setting the single 'reply-to' field |
||
| 120 | * |
||
| 121 | * @param string $address email address for the reply-to |
||
| 122 | * @param string $title name of the reply-to (optional) |
||
| 123 | * @return object instantiated $this |
||
| 124 | */ |
||
| 125 | View Code Duplication | public function setReplyTo($address, $title = '') |
|
| 126 | { |
||
| 127 | if($this->is_valid_email_address($address) && $this->is_valid_email_title($title)) |
||
| 128 | $this->header_array['Reply-To'] = ($title != '') ? "\"{$title}\" <{$address}>" : "{$address}"; |
||
| 129 | |||
| 130 | return $this; |
||
| 131 | } |
||
| 132 | |||
| 133 | /** |
||
| 134 | * Setter method for setting a subject |
||
| 135 | * |
||
| 136 | * @param string $subject subject for the email |
||
| 137 | * @return object instantiated $this |
||
| 138 | */ |
||
| 139 | public function setSubject($subject) |
||
| 140 | { |
||
| 141 | if($this->is_valid_subject($subject)) |
||
| 142 | $this->subject = $subject; |
||
| 143 | |||
| 144 | return $this; |
||
| 145 | } |
||
| 146 | |||
| 147 | /** |
||
| 148 | * Setter method for the plain text message |
||
| 149 | * |
||
| 150 | * @param string $message the plain-text message |
||
| 151 | * @return object insantiated $this |
||
| 152 | */ |
||
| 153 | public function setPlainMessage($message) |
||
| 154 | { |
||
| 155 | $this->plain_message = $message; |
||
| 156 | |||
| 157 | return $this; |
||
| 158 | } |
||
| 159 | |||
| 160 | /** |
||
| 161 | * Setter method for the html message |
||
| 162 | * |
||
| 163 | * @param string $message the html message |
||
| 164 | * @return object insantiated $this |
||
| 165 | */ |
||
| 166 | public function setHTMLMessage($message) |
||
| 167 | { |
||
| 168 | $this->html_message = $message; |
||
| 169 | |||
| 170 | return $this; |
||
| 171 | } |
||
| 172 | |||
| 173 | /** |
||
| 174 | * Setter method for adding attachments |
||
| 175 | * |
||
| 176 | * @param string $path the full path of the attachment |
||
| 177 | * @param string $type mime type of the file |
||
| 178 | * @param string $title the title of the attachment (optional) |
||
| 179 | * @return object insantiated $this |
||
| 180 | */ |
||
| 181 | public function addAttachment($path, $type, $title = '') |
||
| 182 | { |
||
| 183 | $this->attachment_array[] = (object) array( |
||
| 184 | 'path' => $path, |
||
| 185 | 'type' => $type, |
||
| 186 | 'title' => $title); |
||
| 187 | |||
| 188 | return $this; |
||
| 189 | } |
||
| 190 | |||
| 191 | /** |
||
| 192 | * The executing step, the actual sending of the email |
||
| 193 | * First checks to make sure the minimum fields are set (returns false if they are not) |
||
| 194 | * Second it attempts to send the mail with php's mail() (returns false if it fails) |
||
| 195 | * |
||
| 196 | * return boolean whether or not the email was valid & sent |
||
| 197 | */ |
||
| 198 | public function send() |
||
| 199 | { |
||
| 200 | if($this->passed_validation === FALSE) |
||
| 201 | return false; |
||
| 202 | |||
| 203 | if(!$this->check_required_fields()) |
||
| 204 | return false; |
||
| 205 | |||
| 206 | $to = $this->get_to(); |
||
| 207 | $subject = $this->subject; |
||
| 208 | $message = $this->get_message(); |
||
| 209 | $additional_headers = $this->get_additional_headers(); |
||
| 210 | |||
| 211 | return mail($to, $subject, $message, $additional_headers); |
||
| 212 | } |
||
| 213 | |||
| 214 | /** |
||
| 215 | * Main instantiator for the class |
||
| 216 | * |
||
| 217 | * @return object instantiated $this |
||
| 218 | */ |
||
| 219 | public static function instance() |
||
| 220 | { |
||
| 221 | return new Archangel(); |
||
| 222 | } |
||
| 223 | |||
| 224 | /** |
||
| 225 | * Private call to check the minimum required fields |
||
| 226 | * |
||
| 227 | * @return boolean whether or not the email meets the minimum required fields |
||
| 228 | */ |
||
| 229 | private function check_required_fields() |
||
| 230 | { |
||
| 231 | return ( |
||
| 232 | count($this->to_array) > 0 && |
||
| 233 | (isset($this->subject) && strlen($this->subject) > 0) && |
||
| 234 | ( |
||
| 235 | (isset($this->plain_message) && strlen($this->plain_message) > 0) || |
||
| 236 | (isset($this->html_message) && strlen($this->html_message) > 0) || |
||
| 237 | (isset($this->attachment_array) && count($this->attachment_array) > 0))); |
||
| 238 | } |
||
| 239 | |||
| 240 | /** |
||
| 241 | * Private function to collect the recipients from to_array |
||
| 242 | * |
||
| 243 | * @return string comma-separated lit of recipients |
||
| 244 | */ |
||
| 245 | private function get_to() |
||
| 246 | { |
||
| 247 | return implode(', ', $this->to_array); |
||
| 248 | } |
||
| 249 | |||
| 250 | /** |
||
| 251 | * Long, nasty creater of the actual message, with all the multipart logic you'd never want to see |
||
| 252 | * |
||
| 253 | * @return string email message |
||
| 254 | */ |
||
| 255 | private function get_message() |
||
| 256 | { |
||
| 257 | $message = ''; |
||
| 258 | |||
| 259 | if(isset($this->attachment_array) && count($this->attachment_array) > 0) |
||
| 260 | $message .= "--{$this->get_boundary()}" . self::$LINE_BREAK; |
||
| 261 | |||
| 262 | if( |
||
| 263 | isset($this->plain_message) && strlen($this->plain_message) > 0 && |
||
| 264 | isset($this->html_message) && strlen($this->html_message) > 0) |
||
| 265 | { |
||
| 266 | View Code Duplication | if(isset($this->attachment_array) && count($this->attachment_array) > 0) |
|
| 267 | { |
||
| 268 | $message .= "Content-Type: multipart/alternative; boundary={$this->get_alternative_boundary()}" . self::$LINE_BREAK; |
||
| 269 | $message .= self::$LINE_BREAK; |
||
| 270 | } |
||
| 271 | $message .= "--{$this->get_alternative_boundary()}" . self::$LINE_BREAK; |
||
| 272 | $message .= 'Content-Type: text/plain; charset="iso-8859"' . self::$LINE_BREAK; |
||
| 273 | $message .= 'Content-Transfer-Encoding: 7bit' . self::$LINE_BREAK; |
||
| 274 | $message .= self::$LINE_BREAK; |
||
| 275 | $message .= $this->plain_message; |
||
| 276 | $message .= self::$LINE_BREAK; |
||
| 277 | $message .= "--{$this->get_alternative_boundary()}" . self::$LINE_BREAK; |
||
| 278 | $message .= 'Content-Type: text/html; charset="iso-8859-1"' . self::$LINE_BREAK; |
||
| 279 | $message .= 'Content-Transfer-Encoding: 7bit' . self::$LINE_BREAK; |
||
| 280 | $message .= self::$LINE_BREAK; |
||
| 281 | $message .= $this->html_message; |
||
| 282 | $message .= self::$LINE_BREAK; |
||
| 283 | $message .= "--{$this->get_alternative_boundary()}--" . self::$LINE_BREAK; |
||
| 284 | $message .= self::$LINE_BREAK; |
||
| 285 | } |
||
| 286 | else if(isset($this->plain_message) && strlen($this->plain_message)) |
||
| 287 | { |
||
| 288 | View Code Duplication | if(isset($this->attachment_array) && count($this->attachment_array) > 0) |
|
| 289 | { |
||
| 290 | $message .= 'Content-Type: text/plain; charset="iso-8859"' . self::$LINE_BREAK; |
||
| 291 | $message .= 'Content-Transfer-Encoding: 7bit' . self::$LINE_BREAK; |
||
| 292 | $message .= self::$LINE_BREAK; |
||
| 293 | } |
||
| 294 | $message .= $this->plain_message; |
||
| 295 | $message .= self::$LINE_BREAK; |
||
| 296 | } |
||
| 297 | else if(isset($this->html_message) && strlen($this->html_message)) |
||
| 298 | { |
||
| 299 | View Code Duplication | if(isset($this->attachment_array) && count($this->attachment_array) > 0) |
|
| 300 | { |
||
| 301 | $message .= 'Content-Type: text/html; charset="iso-8859-1"' . self::$LINE_BREAK; |
||
| 302 | $message .= 'Content-Transfer-Encoding: 7bit' . self::$LINE_BREAK; |
||
| 303 | $message .= self::$LINE_BREAK; |
||
| 304 | } |
||
| 305 | $message .= $this->html_message; |
||
| 306 | $message .= self::$LINE_BREAK; |
||
| 307 | } |
||
| 308 | if(isset($this->attachment_array) && count($this->attachment_array) > 0) |
||
| 309 | { |
||
| 310 | foreach($this->attachment_array as $attachment) |
||
| 311 | { |
||
| 312 | $message .= "--{$this->get_boundary()}" . self::$LINE_BREAK; |
||
| 313 | $message .= "Content-Type: {$attachment->type}; name=\"{$attachment->title}\"" . self::$LINE_BREAK; |
||
| 314 | $message .= 'Content-Transfer-Encoding: base64' . self::$LINE_BREAK; |
||
| 315 | $message .= 'Content-Disposition: attachment' . self::$LINE_BREAK; |
||
| 316 | $message .= self::$LINE_BREAK; |
||
| 317 | $message .= $this->get_attachment_content($attachment); |
||
| 318 | $message .= self::$LINE_BREAK; |
||
| 319 | } |
||
| 320 | $message .= "--{$this->get_boundary()}--" . self::$LINE_BREAK; |
||
| 321 | } |
||
| 322 | return $message; |
||
| 323 | } |
||
| 324 | |||
| 325 | /** |
||
| 326 | * Private holder for the boundry logic |
||
| 327 | * Not called/created unless it's needed |
||
| 328 | * |
||
| 329 | * @return string boundary |
||
| 330 | */ |
||
| 331 | private $boundary; |
||
| 332 | private function get_boundary() |
||
| 333 | { |
||
| 334 | if(!isset($this->boundary)) |
||
| 335 | $this->boundary = sprintf(self::$BOUNDARY_FORMAT, md5(date('r', time()) . self::$BOUNDARY_SALT)); |
||
| 336 | return $this->boundary; |
||
| 337 | } |
||
| 338 | |||
| 339 | /** |
||
| 340 | * Private holder for the alternative boundry logic |
||
| 341 | * Not called/created unless it's needed |
||
| 342 | * |
||
| 343 | * @return string alternative boundary |
||
| 344 | */ |
||
| 345 | private $alternative_boundary; |
||
| 346 | private function get_alternative_boundary() |
||
| 347 | { |
||
| 348 | if(!isset($this->alternative_boundary)) |
||
| 349 | $this->alternative_boundary = sprintf(self::$ALTERNATIVE_BOUNDARY_FORMAT, md5(date('r', time()) . self::$ALTERNATIVE_BOUNDARY_SALT)); |
||
| 350 | return $this->alternative_boundary; |
||
| 351 | } |
||
| 352 | |||
| 353 | /** |
||
| 354 | * Fetcher for the additional headers needed for multipart emails |
||
| 355 | * |
||
| 356 | * @return string headers needed for multipart |
||
| 357 | */ |
||
| 358 | private function get_additional_headers() |
||
| 359 | { |
||
| 360 | $headers = ''; |
||
| 361 | foreach($this->header_array as $key => $value) |
||
| 362 | { |
||
| 363 | $headers .= "{$key}: {$value}" . self::$LINE_BREAK; |
||
| 364 | } |
||
| 365 | |||
| 366 | if(count($this->cc_array) > 0) |
||
| 367 | $headers .= 'CC: ' . implode(', ', $this->cc_array) . self::$LINE_BREAK; |
||
| 368 | if(count($this->bcc_array) > 0) |
||
| 369 | $headers .= 'BCC: ' . implode(', ', $this->bcc_array) . self::$LINE_BREAK; |
||
| 370 | |||
| 371 | if(isset($this->attachment_array) && count($this->attachment_array) > 0) |
||
| 372 | $headers .= "Content-Type: multipart/mixed; boundary=\"{$this->get_boundary()}\""; |
||
| 373 | else if( |
||
| 374 | isset($this->plain_message) && strlen($this->plain_message) > 0 && |
||
| 375 | isset($this->html_message) && strlen($this->html_message) > 0) |
||
| 376 | { |
||
| 377 | $headers .= "Content-Type: multipart/alternative; boundary=\"{$this->get_alternative_boundary()}\""; |
||
| 378 | } |
||
| 379 | else if(isset($this->html_message) && strlen($this->html_message) > 0) |
||
| 380 | $headers .= 'Content-type: text/html; charset="iso-8859-1"'; |
||
| 381 | |||
| 382 | return $headers; |
||
| 383 | } |
||
| 384 | |||
| 385 | /** |
||
| 386 | * File reader for attachments |
||
| 387 | * |
||
| 388 | * @return string binary representation of file, base64'd |
||
| 389 | */ |
||
| 390 | private function get_attachment_content($attachment) |
||
| 391 | { |
||
| 392 | $handle = fopen($attachment->path, 'r'); |
||
| 393 | $contents = fread($handle, filesize($attachment->path)); |
||
| 394 | fclose($handle); |
||
| 395 | |||
| 396 | $contents = base64_encode($contents); |
||
| 397 | $contents = chunk_split($contents); |
||
| 398 | return $contents; |
||
| 399 | } |
||
| 400 | |||
| 401 | /** |
||
| 402 | * stub for email address checking |
||
| 403 | */ |
||
| 404 | private function is_valid_email_address($string) |
||
| 405 | { |
||
| 406 | if(strlen($string) < 1) |
||
| 407 | return $this->fail_validation("{$string} is an invalid email address!"); |
||
| 408 | |||
| 409 | return true; |
||
| 410 | } |
||
| 411 | |||
| 412 | /** |
||
| 413 | * stub for email title checking |
||
| 414 | */ |
||
| 415 | private function is_valid_email_title($string) |
||
| 416 | { |
||
| 417 | return true; |
||
| 418 | } |
||
| 419 | |||
| 420 | /** |
||
| 421 | * stub for subject checking |
||
| 422 | */ |
||
| 423 | private function is_valid_subject($string) |
||
| 424 | { |
||
| 425 | if(strlen($string) < 1) |
||
| 426 | return $this->fail_validation("{$string} is an invalid email subject!"); |
||
| 427 | |||
| 428 | return true; |
||
| 429 | } |
||
| 430 | |||
| 431 | /** |
||
| 432 | * holder for all validation fails |
||
| 433 | */ |
||
| 434 | private function fail_validation($message) |
||
| 435 | { |
||
| 436 | $this->passed_validation = FALSE; |
||
| 437 | $this->validation_error[] = $message; |
||
| 438 | |||
| 439 | return false; |
||
| 440 | } |
||
| 441 | |||
| 442 | public function get_validation_errors() |
||
| 443 | { |
||
| 444 | return $this->validation_error(); |
||
|
0 ignored issues
–
show
|
|||
| 445 | } |
||
| 446 | |||
| 447 | } |
This check marks calls to methods that do not seem to exist on an object.
This is most likely the result of a method being renamed without all references to it being renamed likewise.