├── content ├── newsletter │ └── newsletter.txt ├── subscribe │ └── subscribe.txt └── unsubscribe │ └── unsubscribe.txt ├── site ├── widgets │ └── newsletter │ │ ├── newsletter.php │ │ └── template.php ├── languages │ ├── en.php │ └── de.php ├── templates │ ├── unsubscribe.php │ ├── subscribe.php │ └── newsletter.php └── config │ └── config.php ├── .gitignore ├── LICENSE ├── README.md └── assets └── phpinc ├── PHPMailerAutoload.php ├── class.pop3.php ├── class.smtp.php └── class.phpmailer.php /content/newsletter/newsletter.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /content/subscribe/subscribe.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /content/unsubscribe/unsubscribe.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/widgets/newsletter/newsletter.php: -------------------------------------------------------------------------------- 1 | 'Newsletter', 4 | 'html' => function() { 5 | return tpl::load(__DIR__ . DS . 'template.php'); 6 | }); -------------------------------------------------------------------------------- /site/languages/en.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Compiled source # 2 | ################### 3 | *.com 4 | *.class 5 | *.dll 6 | *.exe 7 | *.o 8 | *.so 9 | *.esproj 10 | 11 | # Packages # 12 | ############ 13 | # it's better to unpack these files and commit the raw source 14 | # git has its own built in compression methods 15 | *.7z 16 | *.dmg 17 | *.gz 18 | *.iso 19 | *.jar 20 | *.rar 21 | *.tar 22 | *.zip 23 | 24 | # Logs and databases # 25 | ###################### 26 | *.log 27 | *.sql 28 | *.sqlite 29 | 30 | # OS generated files # 31 | ###################### 32 | .DS_Store 33 | .DS_Store? 34 | ._* 35 | .Spotlight-V100 36 | .Trashes 37 | ehthumbs.db 38 | Thumbs.db 39 | -------------------------------------------------------------------------------- /site/languages/de.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /site/widgets/newsletter/template.php: -------------------------------------------------------------------------------- 1 |
';
372 | foreach ($this->errors as $error) {
373 | print_r($error);
374 | }
375 | echo '';
376 | }
377 | }
378 |
379 | /**
380 | * POP3 connection error handler.
381 | * @param integer $errno
382 | * @param string $errstr
383 | * @param string $errfile
384 | * @param integer $errline
385 | * @access private
386 | */
387 | private function catchWarning($errno, $errstr, $errfile, $errline)
388 | {
389 | $this->setError(array(
390 | 'error' => "Connecting to the POP3 server raised a PHP warning: ",
391 | 'errno' => $errno,
392 | 'errstr' => $errstr,
393 | 'errfile' => $errfile,
394 | 'errline' => $errline
395 | ));
396 | }
397 | }
398 |
--------------------------------------------------------------------------------
/assets/phpinc/class.smtp.php:
--------------------------------------------------------------------------------
1 |
8 | * @author Jim Jagielski (jimjag)
123 | * $smtp->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
124 | *
125 | * @type string|callable
126 | */
127 | public $Debugoutput = 'echo';
128 |
129 | /**
130 | * Whether to use VERP.
131 | * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path
132 | * @link http://www.postfix.org/VERP_README.html Info on VERP
133 | * @type boolean
134 | */
135 | public $do_verp = false;
136 |
137 | /**
138 | * The timeout value for connection, in seconds.
139 | * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
140 | * This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure.
141 | * @link http://tools.ietf.org/html/rfc2821#section-4.5.3.2
142 | * @type integer
143 | */
144 | public $Timeout = 300;
145 |
146 | /**
147 | * How long to wait for commands to complete, in seconds.
148 | * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
149 | * @type integer
150 | */
151 | public $Timelimit = 300;
152 |
153 | /**
154 | * The socket for the server connection.
155 | * @type resource
156 | */
157 | protected $smtp_conn;
158 |
159 | /**
160 | * Error message, if any, for the last call.
161 | * @type array
162 | */
163 | protected $error = array();
164 |
165 | /**
166 | * The reply the server sent to us for HELO.
167 | * If null, no HELO string has yet been received.
168 | * @type string|null
169 | */
170 | protected $helo_rply = null;
171 |
172 | /**
173 | * The most recent reply received from the server.
174 | * @type string
175 | */
176 | protected $last_reply = '';
177 |
178 | /**
179 | * Output debugging info via a user-selected method.
180 | * @see SMTP::$Debugoutput
181 | * @see SMTP::$do_debug
182 | * @param string $str Debug string to output
183 | * @param integer $level The debug level of this message; see DEBUG_* constants
184 | * @return void
185 | */
186 | protected function edebug($str, $level = 0)
187 | {
188 | if ($level > $this->do_debug) {
189 | return;
190 | }
191 | if (is_callable($this->Debugoutput)) {
192 | call_user_func($this->Debugoutput, $str, $this->do_debug);
193 | return;
194 | }
195 | switch ($this->Debugoutput) {
196 | case 'error_log':
197 | //Don't output, just log
198 | error_log($str);
199 | break;
200 | case 'html':
201 | //Cleans up output a bit for a better looking, HTML-safe output
202 | echo htmlentities(
203 | preg_replace('/[\r\n]+/', '', $str),
204 | ENT_QUOTES,
205 | 'UTF-8'
206 | )
207 | . "
320 | * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
321 | *
322 | * @type string|callable
323 | * @see SMTP::$Debugoutput
324 | */
325 | public $Debugoutput = 'echo';
326 |
327 | /**
328 | * Whether to keep SMTP connection open after each message.
329 | * If this is set to true then to close the connection
330 | * requires an explicit call to smtpClose().
331 | * @type boolean
332 | */
333 | public $SMTPKeepAlive = false;
334 |
335 | /**
336 | * Whether to split multiple to addresses into multiple messages
337 | * or send them all in one message.
338 | * @type boolean
339 | */
340 | public $SingleTo = false;
341 |
342 | /**
343 | * Storage for addresses when SingleTo is enabled.
344 | * @type array
345 | * @TODO This should really not be public
346 | */
347 | public $SingleToArray = array();
348 |
349 | /**
350 | * Whether to generate VERP addresses on send.
351 | * Only applicable when sending via SMTP.
352 | * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path
353 | * @link http://www.postfix.org/VERP_README.html Postfix VERP info
354 | * @type boolean
355 | */
356 | public $do_verp = false;
357 |
358 | /**
359 | * Whether to allow sending messages with an empty body.
360 | * @type boolean
361 | */
362 | public $AllowEmpty = false;
363 |
364 | /**
365 | * The default line ending.
366 | * @note The default remains "\n". We force CRLF where we know
367 | * it must be used via self::CRLF.
368 | * @type string
369 | */
370 | public $LE = "\n";
371 |
372 | /**
373 | * DKIM selector.
374 | * @type string
375 | */
376 | public $DKIM_selector = '';
377 |
378 | /**
379 | * DKIM Identity.
380 | * Usually the email address used as the source of the email
381 | * @type string
382 | */
383 | public $DKIM_identity = '';
384 |
385 | /**
386 | * DKIM passphrase.
387 | * Used if your key is encrypted.
388 | * @type string
389 | */
390 | public $DKIM_passphrase = '';
391 |
392 | /**
393 | * DKIM signing domain name.
394 | * @example 'example.com'
395 | * @type string
396 | */
397 | public $DKIM_domain = '';
398 |
399 | /**
400 | * DKIM private key file path.
401 | * @type string
402 | */
403 | public $DKIM_private = '';
404 |
405 | /**
406 | * Callback Action function name.
407 | *
408 | * The function that handles the result of the send email action.
409 | * It is called out by send() for each email sent.
410 | *
411 | * Value can be any php callable: http://www.php.net/is_callable
412 | *
413 | * Parameters:
414 | * boolean $result result of the send action
415 | * string $to email address of the recipient
416 | * string $cc cc email addresses
417 | * string $bcc bcc email addresses
418 | * string $subject the subject
419 | * string $body the email body
420 | * string $from email address of sender
421 | * @type string
422 | */
423 | public $action_function = '';
424 |
425 | /**
426 | * What to use in the X-Mailer header.
427 | * Options: null for default, whitespace for none, or a string to use
428 | * @type string
429 | */
430 | public $XMailer = '';
431 |
432 | /**
433 | * An instance of the SMTP sender class.
434 | * @type SMTP
435 | * @access protected
436 | */
437 | protected $smtp = null;
438 |
439 | /**
440 | * The array of 'to' addresses.
441 | * @type array
442 | * @access protected
443 | */
444 | protected $to = array();
445 |
446 | /**
447 | * The array of 'cc' addresses.
448 | * @type array
449 | * @access protected
450 | */
451 | protected $cc = array();
452 |
453 | /**
454 | * The array of 'bcc' addresses.
455 | * @type array
456 | * @access protected
457 | */
458 | protected $bcc = array();
459 |
460 | /**
461 | * The array of reply-to names and addresses.
462 | * @type array
463 | * @access protected
464 | */
465 | protected $ReplyTo = array();
466 |
467 | /**
468 | * An array of all kinds of addresses.
469 | * Includes all of $to, $cc, $bcc, $replyto
470 | * @type array
471 | * @access protected
472 | */
473 | protected $all_recipients = array();
474 |
475 | /**
476 | * The array of attachments.
477 | * @type array
478 | * @access protected
479 | */
480 | protected $attachment = array();
481 |
482 | /**
483 | * The array of custom headers.
484 | * @type array
485 | * @access protected
486 | */
487 | protected $CustomHeader = array();
488 |
489 | /**
490 | * The most recent Message-ID (including angular brackets).
491 | * @type string
492 | * @access protected
493 | */
494 | protected $lastMessageID = '';
495 |
496 | /**
497 | * The message's MIME type.
498 | * @type string
499 | * @access protected
500 | */
501 | protected $message_type = '';
502 |
503 | /**
504 | * The array of MIME boundary strings.
505 | * @type array
506 | * @access protected
507 | */
508 | protected $boundary = array();
509 |
510 | /**
511 | * The array of available languages.
512 | * @type array
513 | * @access protected
514 | */
515 | protected $language = array();
516 |
517 | /**
518 | * The number of errors encountered.
519 | * @type integer
520 | * @access protected
521 | */
522 | protected $error_count = 0;
523 |
524 | /**
525 | * The S/MIME certificate file path.
526 | * @type string
527 | * @access protected
528 | */
529 | protected $sign_cert_file = '';
530 |
531 | /**
532 | * The S/MIME key file path.
533 | * @type string
534 | * @access protected
535 | */
536 | protected $sign_key_file = '';
537 |
538 | /**
539 | * The S/MIME password for the key.
540 | * Used only if the key is encrypted.
541 | * @type string
542 | * @access protected
543 | */
544 | protected $sign_key_pass = '';
545 |
546 | /**
547 | * Whether to throw exceptions for errors.
548 | * @type boolean
549 | * @access protected
550 | */
551 | protected $exceptions = false;
552 |
553 | /**
554 | * Error severity: message only, continue processing.
555 | */
556 | const STOP_MESSAGE = 0;
557 |
558 | /**
559 | * Error severity: message, likely ok to continue processing.
560 | */
561 | const STOP_CONTINUE = 1;
562 |
563 | /**
564 | * Error severity: message, plus full stop, critical error reached.
565 | */
566 | const STOP_CRITICAL = 2;
567 |
568 | /**
569 | * SMTP RFC standard line ending.
570 | */
571 | const CRLF = "\r\n";
572 |
573 | /**
574 | * Constructor.
575 | * @param boolean $exceptions Should we throw external exceptions?
576 | */
577 | public function __construct($exceptions = false)
578 | {
579 | $this->exceptions = ($exceptions == true);
580 | }
581 |
582 | /**
583 | * Destructor.
584 | */
585 | public function __destruct()
586 | {
587 | if ($this->Mailer == 'smtp') { //close any open SMTP connection nicely
588 | $this->smtpClose();
589 | }
590 | }
591 |
592 | /**
593 | * Call mail() in a safe_mode-aware fashion.
594 | * Also, unless sendmail_path points to sendmail (or something that
595 | * claims to be sendmail), don't pass params (not a perfect fix,
596 | * but it will do)
597 | * @param string $to To
598 | * @param string $subject Subject
599 | * @param string $body Message Body
600 | * @param string $header Additional Header(s)
601 | * @param string $params Params
602 | * @access private
603 | * @return boolean
604 | */
605 | private function mailPassthru($to, $subject, $body, $header, $params)
606 | {
607 | //Check overloading of mail function to avoid double-encoding
608 | if (ini_get('mbstring.func_overload') & 1) {
609 | $subject = $this->secureHeader($subject);
610 | } else {
611 | $subject = $this->encodeHeader($this->secureHeader($subject));
612 | }
613 | if (ini_get('safe_mode') || !($this->UseSendmailOptions)) {
614 | $result = @mail($to, $subject, $body, $header);
615 | } else {
616 | $result = @mail($to, $subject, $body, $header, $params);
617 | }
618 | return $result;
619 | }
620 |
621 | /**
622 | * Output debugging info via user-defined method.
623 | * Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug).
624 | * @see PHPMailer::$Debugoutput
625 | * @see PHPMailer::$SMTPDebug
626 | * @param string $str
627 | */
628 | protected function edebug($str)
629 | {
630 | if ($this->SMTPDebug <= 0) {
631 | return;
632 | }
633 | if (is_callable($this->Debugoutput)) {
634 | call_user_func($this->Debugoutput, $str, $this->SMTPDebug);
635 | return;
636 | }
637 | switch ($this->Debugoutput) {
638 | case 'error_log':
639 | //Don't output, just log
640 | error_log($str);
641 | break;
642 | case 'html':
643 | //Cleans up output a bit for a better looking, HTML-safe output
644 | echo htmlentities(
645 | preg_replace('/[\r\n]+/', '', $str),
646 | ENT_QUOTES,
647 | 'UTF-8'
648 | )
649 | . "' . $this->lang('smtp_error') . $lasterror['smtp_msg'] . "
\n"; 2778 | } 2779 | } 2780 | $this->ErrorInfo = $msg; 2781 | } 2782 | 2783 | /** 2784 | * Return an RFC 822 formatted date. 2785 | * @access public 2786 | * @return string 2787 | * @static 2788 | */ 2789 | public static function rfcDate() 2790 | { 2791 | // Set the time zone to whatever the default is to avoid 500 errors 2792 | // Will default to UTC if it's not set properly in php.ini 2793 | date_default_timezone_set(@date_default_timezone_get()); 2794 | return date('D, j M Y H:i:s O'); 2795 | } 2796 | 2797 | /** 2798 | * Get the server hostname. 2799 | * Returns 'localhost.localdomain' if unknown. 2800 | * @access protected 2801 | * @return string 2802 | */ 2803 | protected function serverHostname() 2804 | { 2805 | $result = 'localhost.localdomain'; 2806 | if (!empty($this->Hostname)) { 2807 | $result = $this->Hostname; 2808 | } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) { 2809 | $result = $_SERVER['SERVER_NAME']; 2810 | } elseif (function_exists('gethostname') && gethostname() !== false) { 2811 | $result = gethostname(); 2812 | } elseif (php_uname('n') !== false) { 2813 | $result = php_uname('n'); 2814 | } 2815 | return $result; 2816 | } 2817 | 2818 | /** 2819 | * Get an error message in the current language. 2820 | * @access protected 2821 | * @param string $key 2822 | * @return string 2823 | */ 2824 | protected function lang($key) 2825 | { 2826 | if (count($this->language) < 1) { 2827 | $this->setLanguage('en'); // set the default language 2828 | } 2829 | 2830 | if (isset($this->language[$key])) { 2831 | return $this->language[$key]; 2832 | } else { 2833 | return 'Language string failed to load: ' . $key; 2834 | } 2835 | } 2836 | 2837 | /** 2838 | * Check if an error occurred. 2839 | * @access public 2840 | * @return boolean True if an error did occur. 2841 | */ 2842 | public function isError() 2843 | { 2844 | return ($this->error_count > 0); 2845 | } 2846 | 2847 | /** 2848 | * Ensure consistent line endings in a string. 2849 | * Changes every end of line from CRLF, CR or LF to $this->LE. 2850 | * @access public 2851 | * @param string $str String to fixEOL 2852 | * @return string 2853 | */ 2854 | public function fixEOL($str) 2855 | { 2856 | // Normalise to \n 2857 | $nstr = str_replace(array("\r\n", "\r"), "\n", $str); 2858 | // Now convert LE as needed 2859 | if ($this->LE !== "\n") { 2860 | $nstr = str_replace("\n", $this->LE, $nstr); 2861 | } 2862 | return $nstr; 2863 | } 2864 | 2865 | /** 2866 | * Add a custom header. 2867 | * $name value can be overloaded to contain 2868 | * both header name and value (name:value) 2869 | * @access public 2870 | * @param string $name Custom header name 2871 | * @param string $value Header value 2872 | * @return void 2873 | */ 2874 | public function addCustomHeader($name, $value = null) 2875 | { 2876 | if ($value === null) { 2877 | // Value passed in as name:value 2878 | $this->CustomHeader[] = explode(':', $name, 2); 2879 | } else { 2880 | $this->CustomHeader[] = array($name, $value); 2881 | } 2882 | } 2883 | 2884 | /** 2885 | * Create a message from an HTML string. 2886 | * Automatically makes modifications for inline images and backgrounds 2887 | * and creates a plain-text version by converting the HTML. 2888 | * Overwrites any existing values in $this->Body and $this->AltBody 2889 | * @access public 2890 | * @param string $message HTML message string 2891 | * @param string $basedir baseline directory for path 2892 | * @param boolean $advanced Whether to use the advanced HTML to text converter 2893 | * @return string $message 2894 | */ 2895 | public function msgHTML($message, $basedir = '', $advanced = false) 2896 | { 2897 | preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images); 2898 | if (isset($images[2])) { 2899 | foreach ($images[2] as $imgindex => $url) { 2900 | // Convert data URIs into embedded images 2901 | if (preg_match('#^data:(image[^;,]*)(;base64)?,#', $url, $match)) { 2902 | $data = substr($url, strpos($url, ',')); 2903 | if ($match[2]) { 2904 | $data = base64_decode($data); 2905 | } else { 2906 | $data = rawurldecode($data); 2907 | } 2908 | $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 2909 | if ($this->addStringEmbeddedImage($data, $cid, '', 'base64', $match[1])) { 2910 | $message = preg_replace( 2911 | '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui', 2912 | $images[1][$imgindex] . '="cid:' . $cid . '"', 2913 | $message 2914 | ); 2915 | } 2916 | } elseif (!preg_match('#^[A-z]+://#', $url)) { 2917 | // Do not change urls for absolute images (thanks to corvuscorax) 2918 | $filename = basename($url); 2919 | $directory = dirname($url); 2920 | if ($directory == '.') { 2921 | $directory = ''; 2922 | } 2923 | $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2 2924 | if (strlen($basedir) > 1 && substr($basedir, -1) != '/') { 2925 | $basedir .= '/'; 2926 | } 2927 | if (strlen($directory) > 1 && substr($directory, -1) != '/') { 2928 | $directory .= '/'; 2929 | } 2930 | if ($this->addEmbeddedImage( 2931 | $basedir . $directory . $filename, 2932 | $cid, 2933 | $filename, 2934 | 'base64', 2935 | self::_mime_types((string)self::mb_pathinfo($filename, PATHINFO_EXTENSION)) 2936 | ) 2937 | ) { 2938 | $message = preg_replace( 2939 | '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui', 2940 | $images[1][$imgindex] . '="cid:' . $cid . '"', 2941 | $message 2942 | ); 2943 | } 2944 | } 2945 | } 2946 | } 2947 | $this->isHTML(true); 2948 | // Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better 2949 | $this->Body = $this->normalizeBreaks($message); 2950 | $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced)); 2951 | if (empty($this->AltBody)) { 2952 | $this->AltBody = 'To view this email message, open it in a program that understands HTML!' . 2953 | self::CRLF . self::CRLF; 2954 | } 2955 | return $this->Body; 2956 | } 2957 | 2958 | /** 2959 | * Convert an HTML string into plain text. 2960 | * @param string $html The HTML text to convert 2961 | * @param boolean $advanced Should this use the more complex html2text converter or just a simple one? 2962 | * @return string 2963 | */ 2964 | public function html2text($html, $advanced = false) 2965 | { 2966 | if ($advanced) { 2967 | require_once 'extras/class.html2text.php'; 2968 | $htmlconverter = new html2text($html); 2969 | return $htmlconverter->get_text(); 2970 | } 2971 | return html_entity_decode( 2972 | trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))), 2973 | ENT_QUOTES, 2974 | $this->CharSet 2975 | ); 2976 | } 2977 | 2978 | /** 2979 | * Get the MIME type for a file extension. 2980 | * @param string $ext File extension 2981 | * @access public 2982 | * @return string MIME type of file. 2983 | * @static 2984 | */ 2985 | public static function _mime_types($ext = '') 2986 | { 2987 | $mimes = array( 2988 | 'xl' => 'application/excel', 2989 | 'js' => 'application/javascript', 2990 | 'hqx' => 'application/mac-binhex40', 2991 | 'cpt' => 'application/mac-compactpro', 2992 | 'bin' => 'application/macbinary', 2993 | 'doc' => 'application/msword', 2994 | 'word' => 'application/msword', 2995 | 'class' => 'application/octet-stream', 2996 | 'dll' => 'application/octet-stream', 2997 | 'dms' => 'application/octet-stream', 2998 | 'exe' => 'application/octet-stream', 2999 | 'lha' => 'application/octet-stream', 3000 | 'lzh' => 'application/octet-stream', 3001 | 'psd' => 'application/octet-stream', 3002 | 'sea' => 'application/octet-stream', 3003 | 'so' => 'application/octet-stream', 3004 | 'oda' => 'application/oda', 3005 | 'pdf' => 'application/pdf', 3006 | 'ai' => 'application/postscript', 3007 | 'eps' => 'application/postscript', 3008 | 'ps' => 'application/postscript', 3009 | 'smi' => 'application/smil', 3010 | 'smil' => 'application/smil', 3011 | 'mif' => 'application/vnd.mif', 3012 | 'xls' => 'application/vnd.ms-excel', 3013 | 'ppt' => 'application/vnd.ms-powerpoint', 3014 | 'wbxml' => 'application/vnd.wap.wbxml', 3015 | 'wmlc' => 'application/vnd.wap.wmlc', 3016 | 'dcr' => 'application/x-director', 3017 | 'dir' => 'application/x-director', 3018 | 'dxr' => 'application/x-director', 3019 | 'dvi' => 'application/x-dvi', 3020 | 'gtar' => 'application/x-gtar', 3021 | 'php3' => 'application/x-httpd-php', 3022 | 'php4' => 'application/x-httpd-php', 3023 | 'php' => 'application/x-httpd-php', 3024 | 'phtml' => 'application/x-httpd-php', 3025 | 'phps' => 'application/x-httpd-php-source', 3026 | 'swf' => 'application/x-shockwave-flash', 3027 | 'sit' => 'application/x-stuffit', 3028 | 'tar' => 'application/x-tar', 3029 | 'tgz' => 'application/x-tar', 3030 | 'xht' => 'application/xhtml+xml', 3031 | 'xhtml' => 'application/xhtml+xml', 3032 | 'zip' => 'application/zip', 3033 | 'mid' => 'audio/midi', 3034 | 'midi' => 'audio/midi', 3035 | 'mp2' => 'audio/mpeg', 3036 | 'mp3' => 'audio/mpeg', 3037 | 'mpga' => 'audio/mpeg', 3038 | 'aif' => 'audio/x-aiff', 3039 | 'aifc' => 'audio/x-aiff', 3040 | 'aiff' => 'audio/x-aiff', 3041 | 'ram' => 'audio/x-pn-realaudio', 3042 | 'rm' => 'audio/x-pn-realaudio', 3043 | 'rpm' => 'audio/x-pn-realaudio-plugin', 3044 | 'ra' => 'audio/x-realaudio', 3045 | 'wav' => 'audio/x-wav', 3046 | 'bmp' => 'image/bmp', 3047 | 'gif' => 'image/gif', 3048 | 'jpeg' => 'image/jpeg', 3049 | 'jpe' => 'image/jpeg', 3050 | 'jpg' => 'image/jpeg', 3051 | 'png' => 'image/png', 3052 | 'tiff' => 'image/tiff', 3053 | 'tif' => 'image/tiff', 3054 | 'eml' => 'message/rfc822', 3055 | 'css' => 'text/css', 3056 | 'html' => 'text/html', 3057 | 'htm' => 'text/html', 3058 | 'shtml' => 'text/html', 3059 | 'log' => 'text/plain', 3060 | 'text' => 'text/plain', 3061 | 'txt' => 'text/plain', 3062 | 'rtx' => 'text/richtext', 3063 | 'rtf' => 'text/rtf', 3064 | 'vcf' => 'text/vcard', 3065 | 'vcard' => 'text/vcard', 3066 | 'xml' => 'text/xml', 3067 | 'xsl' => 'text/xml', 3068 | 'mpeg' => 'video/mpeg', 3069 | 'mpe' => 'video/mpeg', 3070 | 'mpg' => 'video/mpeg', 3071 | 'mov' => 'video/quicktime', 3072 | 'qt' => 'video/quicktime', 3073 | 'rv' => 'video/vnd.rn-realvideo', 3074 | 'avi' => 'video/x-msvideo', 3075 | 'movie' => 'video/x-sgi-movie' 3076 | ); 3077 | return (array_key_exists(strtolower($ext), $mimes) ? $mimes[strtolower($ext)]: 'application/octet-stream'); 3078 | } 3079 | 3080 | /** 3081 | * Map a file name to a MIME type. 3082 | * Defaults to 'application/octet-stream', i.e.. arbitrary binary data. 3083 | * @param string $filename A file name or full path, does not need to exist as a file 3084 | * @return string 3085 | * @static 3086 | */ 3087 | public static function filenameToType($filename) 3088 | { 3089 | // In case the path is a URL, strip any query string before getting extension 3090 | $qpos = strpos($filename, '?'); 3091 | if ($qpos !== false) { 3092 | $filename = substr($filename, 0, $qpos); 3093 | } 3094 | $pathinfo = self::mb_pathinfo($filename); 3095 | return self::_mime_types($pathinfo['extension']); 3096 | } 3097 | 3098 | /** 3099 | * Multi-byte-safe pathinfo replacement. 3100 | * Drop-in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe. 3101 | * Works similarly to the one in PHP >= 5.2.0 3102 | * @link http://www.php.net/manual/en/function.pathinfo.php#107461 3103 | * @param string $path A filename or path, does not need to exist as a file 3104 | * @param integer|string $options Either a PATHINFO_* constant, 3105 | * or a string name to return only the specified piece, allows 'filename' to work on PHP < 5.2 3106 | * @return string|array 3107 | * @static 3108 | */ 3109 | public static function mb_pathinfo($path, $options = null) 3110 | { 3111 | $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => ''); 3112 | $pathinfo = array(); 3113 | if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) { 3114 | if (array_key_exists(1, $pathinfo)) { 3115 | $ret['dirname'] = $pathinfo[1]; 3116 | } 3117 | if (array_key_exists(2, $pathinfo)) { 3118 | $ret['basename'] = $pathinfo[2]; 3119 | } 3120 | if (array_key_exists(5, $pathinfo)) { 3121 | $ret['extension'] = $pathinfo[5]; 3122 | } 3123 | if (array_key_exists(3, $pathinfo)) { 3124 | $ret['filename'] = $pathinfo[3]; 3125 | } 3126 | } 3127 | switch ($options) { 3128 | case PATHINFO_DIRNAME: 3129 | case 'dirname': 3130 | return $ret['dirname']; 3131 | case PATHINFO_BASENAME: 3132 | case 'basename': 3133 | return $ret['basename']; 3134 | case PATHINFO_EXTENSION: 3135 | case 'extension': 3136 | return $ret['extension']; 3137 | case PATHINFO_FILENAME: 3138 | case 'filename': 3139 | return $ret['filename']; 3140 | default: 3141 | return $ret; 3142 | } 3143 | } 3144 | 3145 | /** 3146 | * Set or reset instance properties. 3147 | * 3148 | * Usage Example: 3149 | * $page->set('X-Priority', '3'); 3150 | * 3151 | * @access public 3152 | * @param string $name 3153 | * @param mixed $value 3154 | * NOTE: will not work with arrays, there are no arrays to set/reset 3155 | * @throws phpmailerException 3156 | * @return boolean 3157 | * @TODO Should this not be using __set() magic function? 3158 | */ 3159 | public function set($name, $value = '') 3160 | { 3161 | try { 3162 | if (isset($this->$name)) { 3163 | $this->$name = $value; 3164 | } else { 3165 | throw new phpmailerException($this->lang('variable_set') . $name, self::STOP_CRITICAL); 3166 | } 3167 | } catch (Exception $exc) { 3168 | $this->setError($exc->getMessage()); 3169 | if ($exc->getCode() == self::STOP_CRITICAL) { 3170 | return false; 3171 | } 3172 | } 3173 | return true; 3174 | } 3175 | 3176 | /** 3177 | * Strip newlines to prevent header injection. 3178 | * @access public 3179 | * @param string $str 3180 | * @return string 3181 | */ 3182 | public function secureHeader($str) 3183 | { 3184 | return trim(str_replace(array("\r", "\n"), '', $str)); 3185 | } 3186 | 3187 | /** 3188 | * Normalize line breaks in a string. 3189 | * Converts UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format. 3190 | * Defaults to CRLF (for message bodies) and preserves consecutive breaks. 3191 | * @param string $text 3192 | * @param string $breaktype What kind of line break to use, defaults to CRLF 3193 | * @return string 3194 | * @access public 3195 | * @static 3196 | */ 3197 | public static function normalizeBreaks($text, $breaktype = "\r\n") 3198 | { 3199 | return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text); 3200 | } 3201 | 3202 | 3203 | /** 3204 | * Set the public and private key files and password for S/MIME signing. 3205 | * @access public 3206 | * @param string $cert_filename 3207 | * @param string $key_filename 3208 | * @param string $key_pass Password for private key 3209 | */ 3210 | public function sign($cert_filename, $key_filename, $key_pass) 3211 | { 3212 | $this->sign_cert_file = $cert_filename; 3213 | $this->sign_key_file = $key_filename; 3214 | $this->sign_key_pass = $key_pass; 3215 | } 3216 | 3217 | /** 3218 | * Quoted-Printable-encode a DKIM header. 3219 | * @access public 3220 | * @param string $txt 3221 | * @return string 3222 | */ 3223 | public function DKIM_QP($txt) 3224 | { 3225 | $line = ''; 3226 | for ($i = 0; $i < strlen($txt); $i++) { 3227 | $ord = ord($txt[$i]); 3228 | if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) { 3229 | $line .= $txt[$i]; 3230 | } else { 3231 | $line .= '=' . sprintf('%02X', $ord); 3232 | } 3233 | } 3234 | return $line; 3235 | } 3236 | 3237 | /** 3238 | * Generate a DKIM signature. 3239 | * @access public 3240 | * @param string $signHeader 3241 | * @throws phpmailerException 3242 | * @return string 3243 | */ 3244 | public function DKIM_Sign($signHeader) 3245 | { 3246 | if (!defined('PKCS7_TEXT')) { 3247 | if ($this->exceptions) { 3248 | throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.'); 3249 | } 3250 | return ''; 3251 | } 3252 | $privKeyStr = file_get_contents($this->DKIM_private); 3253 | if ($this->DKIM_passphrase != '') { 3254 | $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase); 3255 | } else { 3256 | $privKey = $privKeyStr; 3257 | } 3258 | if (openssl_sign($signHeader, $signature, $privKey)) { 3259 | return base64_encode($signature); 3260 | } 3261 | return ''; 3262 | } 3263 | 3264 | /** 3265 | * Generate a DKIM canonicalization header. 3266 | * @access public 3267 | * @param string $signHeader Header 3268 | * @return string 3269 | */ 3270 | public function DKIM_HeaderC($signHeader) 3271 | { 3272 | $signHeader = preg_replace('/\r\n\s+/', ' ', $signHeader); 3273 | $lines = explode("\r\n", $signHeader); 3274 | foreach ($lines as $key => $line) { 3275 | list($heading, $value) = explode(':', $line, 2); 3276 | $heading = strtolower($heading); 3277 | $value = preg_replace('/\s+/', ' ', $value); // Compress useless spaces 3278 | $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value 3279 | } 3280 | $signHeader = implode("\r\n", $lines); 3281 | return $signHeader; 3282 | } 3283 | 3284 | /** 3285 | * Generate a DKIM canonicalization body. 3286 | * @access public 3287 | * @param string $body Message Body 3288 | * @return string 3289 | */ 3290 | public function DKIM_BodyC($body) 3291 | { 3292 | if ($body == '') { 3293 | return "\r\n"; 3294 | } 3295 | // stabilize line endings 3296 | $body = str_replace("\r\n", "\n", $body); 3297 | $body = str_replace("\n", "\r\n", $body); 3298 | // END stabilize line endings 3299 | while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") { 3300 | $body = substr($body, 0, strlen($body) - 2); 3301 | } 3302 | return $body; 3303 | } 3304 | 3305 | /** 3306 | * Create the DKIM header and body in a new message header. 3307 | * @access public 3308 | * @param string $headers_line Header lines 3309 | * @param string $subject Subject 3310 | * @param string $body Body 3311 | * @return string 3312 | */ 3313 | public function DKIM_Add($headers_line, $subject, $body) 3314 | { 3315 | $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms 3316 | $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body 3317 | $DKIMquery = 'dns/txt'; // Query method 3318 | $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone) 3319 | $subject_header = "Subject: $subject"; 3320 | $headers = explode($this->LE, $headers_line); 3321 | $from_header = ''; 3322 | $to_header = ''; 3323 | $current = ''; 3324 | foreach ($headers as $header) { 3325 | if (strpos($header, 'From:') === 0) { 3326 | $from_header = $header; 3327 | $current = 'from_header'; 3328 | } elseif (strpos($header, 'To:') === 0) { 3329 | $to_header = $header; 3330 | $current = 'to_header'; 3331 | } else { 3332 | if ($current && strpos($header, ' =?') === 0) { 3333 | $current .= $header; 3334 | } else { 3335 | $current = ''; 3336 | } 3337 | } 3338 | } 3339 | $from = str_replace('|', '=7C', $this->DKIM_QP($from_header)); 3340 | $to = str_replace('|', '=7C', $this->DKIM_QP($to_header)); 3341 | $subject = str_replace( 3342 | '|', 3343 | '=7C', 3344 | $this->DKIM_QP($subject_header) 3345 | ); // Copied header fields (dkim-quoted-printable) 3346 | $body = $this->DKIM_BodyC($body); 3347 | $DKIMlen = strlen($body); // Length of body 3348 | $DKIMb64 = base64_encode(pack('H*', sha1($body))); // Base64 of packed binary SHA-1 hash of body 3349 | $ident = ($this->DKIM_identity == '') ? '' : ' i=' . $this->DKIM_identity . ';'; 3350 | $dkimhdrs = 'DKIM-Signature: v=1; a=' . 3351 | $DKIMsignatureType . '; q=' . 3352 | $DKIMquery . '; l=' . 3353 | $DKIMlen . '; s=' . 3354 | $this->DKIM_selector . 3355 | ";\r\n" . 3356 | "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" . 3357 | "\th=From:To:Subject;\r\n" . 3358 | "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" . 3359 | "\tz=$from\r\n" . 3360 | "\t|$to\r\n" . 3361 | "\t|$subject;\r\n" . 3362 | "\tbh=" . $DKIMb64 . ";\r\n" . 3363 | "\tb="; 3364 | $toSign = $this->DKIM_HeaderC( 3365 | $from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs 3366 | ); 3367 | $signed = $this->DKIM_Sign($toSign); 3368 | return $dkimhdrs . $signed . "\r\n"; 3369 | } 3370 | 3371 | /** 3372 | * Allows for public read access to 'to' property. 3373 | * @access public 3374 | * @return array 3375 | */ 3376 | public function getToAddresses() 3377 | { 3378 | return $this->to; 3379 | } 3380 | 3381 | /** 3382 | * Allows for public read access to 'cc' property. 3383 | * @access public 3384 | * @return array 3385 | */ 3386 | public function getCcAddresses() 3387 | { 3388 | return $this->cc; 3389 | } 3390 | 3391 | /** 3392 | * Allows for public read access to 'bcc' property. 3393 | * @access public 3394 | * @return array 3395 | */ 3396 | public function getBccAddresses() 3397 | { 3398 | return $this->bcc; 3399 | } 3400 | 3401 | /** 3402 | * Allows for public read access to 'ReplyTo' property. 3403 | * @access public 3404 | * @return array 3405 | */ 3406 | public function getReplyToAddresses() 3407 | { 3408 | return $this->ReplyTo; 3409 | } 3410 | 3411 | /** 3412 | * Allows for public read access to 'all_recipients' property. 3413 | * @access public 3414 | * @return array 3415 | */ 3416 | public function getAllRecipientAddresses() 3417 | { 3418 | return $this->all_recipients; 3419 | } 3420 | 3421 | /** 3422 | * Perform a callback. 3423 | * @param boolean $isSent 3424 | * @param array $to 3425 | * @param array $cc 3426 | * @param array $bcc 3427 | * @param string $subject 3428 | * @param string $body 3429 | * @param string $from 3430 | */ 3431 | protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from) 3432 | { 3433 | if (!empty($this->action_function) && is_callable($this->action_function)) { 3434 | $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from); 3435 | call_user_func_array($this->action_function, $params); 3436 | } 3437 | } 3438 | } 3439 | 3440 | /** 3441 | * PHPMailer exception handler 3442 | * @package PHPMailer 3443 | */ 3444 | class phpmailerException extends Exception 3445 | { 3446 | /** 3447 | * Prettify error message output 3448 | * @return string 3449 | */ 3450 | public function errorMessage() 3451 | { 3452 | $errorMsg = '' . $this->getMessage() . "