· 8 years ago · Nov 30, 2017, 12:06 PM
1<?php
2error_reporting(E_ALL);
3ini_set('display_errors',1);
4
5
6
7 //include('dbcon.php');
8
9 if($_REQUEST['code'] || strtolower($_REQUEST['code']) == strtolower($_SESSION['random_number']))
10 {
11
12 // insert your name , email and text message to your table in db
13
14 echo 1;// submitted
15
16 }
17 else
18 {
19 echo 0; // invalid code
20 }
21
22
23
24$recipients = 'redakcja@poloniawholandii.com';
25//$recipients = '#';
26
27 require '../phpmailer/PHPMailerAutoload.php';
28
29 preg_match_all("/([\w-]+(?:\.[\w-]+)*)@((?:[\w-]+\.)*\w[\w-]{0,66})\.([a-z]{2,6}(?:\.[a-z]{2})?)/", $recipients, $addresses, PREG_OFFSET_CAPTURE);
30 /**
31 * PHPMailer - PHP email creation and transport class.
32 * PHP Version 5
33 * @package PHPMailer
34 * @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
35 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
36 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
37 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
38 * @author Brent R. Matzelle (original founder)
39 * @copyright 2012 - 2014 Marcus Bointon
40 * @copyright 2010 - 2012 Jim Jagielski
41 * @copyright 2004 - 2009 Andy Prevost
42 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
43 * @note This program is distributed in the hope that it will be useful - WITHOUT
44 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
45 * FITNESS FOR A PARTICULAR PURPOSE.
46 */
47
48/**
49 * PHPMailer - PHP email creation and transport class.
50 * @package PHPMailer
51 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
52 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
53 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
54 * @author Brent R. Matzelle (original founder)
55 */
56class PHPMailer
57{
58 /**
59 * The PHPMailer Version number.
60 * @type string
61 */
62 public $Version = '5.2.9';
63
64 /**
65 * Email priority.
66 * Options: 1 = High, 3 = Normal, 5 = low.
67 * @type integer
68 */
69 public $Priority = 3;
70
71 /**
72 * The character set of the message.
73 * @type string
74 */
75 public $CharSet = 'iso-8859-1';
76
77 /**
78 * The MIME Content-type of the message.
79 * @type string
80 */
81 public $ContentType = 'text/plain';
82
83 /**
84 * The message encoding.
85 * Options: "8bit", "7bit", "binary", "base64", and "quoted-printable".
86 * @type string
87 */
88 public $Encoding = '8bit';
89
90 /**
91 * Holds the most recent mailer error message.
92 * @type string
93 */
94 public $ErrorInfo = '';
95
96 /**
97 * The From email address for the message.
98 * @type string
99 */
100 public $From = 'root@localhost';
101
102 /**
103 * The From name of the message.
104 * @type string
105 */
106 public $FromName = 'Root User';
107
108 /**
109 * The Sender email (Return-Path) of the message.
110 * If not empty, will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
111 * @type string
112 */
113 public $Sender = '';
114
115 /**
116 * The Return-Path of the message.
117 * If empty, it will be set to either From or Sender.
118 * @type string
119 * @deprecated Email senders should never set a return-path header;
120 * it's the receiver's job (RFC5321 section 4.4), so this no longer does anything.
121 * @link https://tools.ietf.org/html/rfc5321#section-4.4 RFC5321 reference
122 */
123 public $ReturnPath = '';
124
125 /**
126 * The Subject of the message.
127 * @type string
128 */
129 public $Subject = '';
130
131 /**
132 * An HTML or plain text message body.
133 * If HTML then call isHTML(true).
134 * @type string
135 */
136 public $Body = '';
137
138 /**
139 * The plain-text message body.
140 * This body can be read by mail clients that do not have HTML email
141 * capability such as mutt & Eudora.
142 * Clients that can read HTML will view the normal Body.
143 * @type string
144 */
145 public $AltBody = '';
146
147 /**
148 * An iCal message part body.
149 * Only supported in simple alt or alt_inline message types
150 * To generate iCal events, use the bundled extras/EasyPeasyICS.php class or iCalcreator
151 * @link http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/
152 * @link http://kigkonsult.se/iCalcreator/
153 * @type string
154 */
155 public $Ical = '';
156
157 /**
158 * The complete compiled MIME message body.
159 * @access protected
160 * @type string
161 */
162 protected $MIMEBody = '';
163
164 /**
165 * The complete compiled MIME message headers.
166 * @type string
167 * @access protected
168 */
169 protected $MIMEHeader = '';
170
171 /**
172 * Extra headers that createHeader() doesn't fold in.
173 * @type string
174 * @access protected
175 */
176 protected $mailHeader = '';
177
178 /**
179 * Word-wrap the message body to this number of chars.
180 * Set to 0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance.
181 * @type integer
182 */
183 public $WordWrap = 0;
184
185 /**
186 * Which method to use to send mail.
187 * Options: "mail", "sendmail", or "smtp".
188 * @type string
189 */
190 public $Mailer = 'mail';
191
192 /**
193 * The path to the sendmail program.
194 * @type string
195 */
196 public $Sendmail = '/usr/sbin/sendmail';
197
198 /**
199 * Whether mail() uses a fully sendmail-compatible MTA.
200 * One which supports sendmail's "-oi -f" options.
201 * @type boolean
202 */
203 public $UseSendmailOptions = true;
204
205 /**
206 * Path to PHPMailer plugins.
207 * Useful if the SMTP class is not in the PHP include path.
208 * @type string
209 * @deprecated Should not be needed now there is an autoloader.
210 */
211 public $PluginDir = '';
212
213 /**
214 * The email address that a reading confirmation should be sent to.
215 * @type string
216 */
217 public $ConfirmReadingTo = '';
218
219 /**
220 * The hostname to use in Message-Id and Received headers
221 * and as default HELO string.
222 * If empty, the value returned
223 * by SERVER_NAME is used or 'localhost.localdomain'.
224 * @type string
225 */
226 public $Hostname = '';
227
228 /**
229 * An ID to be used in the Message-Id header.
230 * If empty, a unique id will be generated.
231 * @type string
232 */
233 public $MessageID = '';
234
235 /**
236 * The message Date to be used in the Date header.
237 * If empty, the current date will be added.
238 * @type string
239 */
240 public $MessageDate = '';
241
242 /**
243 * SMTP hosts.
244 * Either a single hostname or multiple semicolon-delimited hostnames.
245 * You can also specify a different port
246 * for each host by using this format: [hostname:port]
247 * (e.g. "smtp1.example.com:25;smtp2.example.com").
248 * You can also specify encryption type, for example:
249 * (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465").
250 * Hosts will be tried in order.
251 * @type string
252 */
253 public $Host = 'localhost';
254
255 /**
256 * The default SMTP server port.
257 * @type integer
258 * @TODO Why is this needed when the SMTP class takes care of it?
259 */
260 public $Port = 25;
261
262 /**
263 * The SMTP HELO of the message.
264 * Default is $Hostname.
265 * @type string
266 * @see PHPMailer::$Hostname
267 */
268 public $Helo = '';
269
270 /**
271 * The secure connection prefix.
272 * Options: "", "ssl" or "tls"
273 * @type string
274 */
275 public $SMTPSecure = '';
276
277 /**
278 * Whether to use SMTP authentication.
279 * Uses the Username and Password properties.
280 * @type boolean
281 * @see PHPMailer::$Username
282 * @see PHPMailer::$Password
283 */
284 public $SMTPAuth = false;
285
286 /**
287 * SMTP username.
288 * @type string
289 */
290 public $Username = '';
291
292 /**
293 * SMTP password.
294 * @type string
295 */
296 public $Password = '';
297
298 /**
299 * SMTP auth type.
300 * Options are LOGIN (default), PLAIN, NTLM, CRAM-MD5
301 * @type string
302 */
303 public $AuthType = '';
304
305 /**
306 * SMTP realm.
307 * Used for NTLM auth
308 * @type string
309 */
310 public $Realm = '';
311
312 /**
313 * SMTP workstation.
314 * Used for NTLM auth
315 * @type string
316 */
317 public $Workstation = '';
318
319 /**
320 * The SMTP server timeout in seconds.
321 * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
322 * @type integer
323 */
324 public $Timeout = 300;
325
326 /**
327 * SMTP class debug output mode.
328 * Debug output level.
329 * Options:
330 * * `0` No output
331 * * `1` Commands
332 * * `2` Data and commands
333 * * `3` As 2 plus connection status
334 * * `4` Low-level data output
335 * @type integer
336 * @see SMTP::$do_debug
337 */
338 public $SMTPDebug = 0;
339
340 /**
341 * How to handle debug output.
342 * Options:
343 * * `echo` Output plain-text as-is, appropriate for CLI
344 * * `html` Output escaped, line breaks converted to `<br>`, appropriate for browser output
345 * * `error_log` Output to error log as configured in php.ini
346 *
347 * Alternatively, you can provide a callable expecting two params: a message string and the debug level:
348 * <code>
349 * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
350 * </code>
351 * @type string|callable
352 * @see SMTP::$Debugoutput
353 */
354 public $Debugoutput = 'echo';
355
356 /**
357 * Whether to keep SMTP connection open after each message.
358 * If this is set to true then to close the connection
359 * requires an explicit call to smtpClose().
360 * @type boolean
361 */
362 public $SMTPKeepAlive = false;
363
364 /**
365 * Whether to split multiple to addresses into multiple messages
366 * or send them all in one message.
367 * @type boolean
368 */
369 public $SingleTo = false;
370
371 /**
372 * Storage for addresses when SingleTo is enabled.
373 * @type array
374 * @TODO This should really not be public
375 */
376 public $SingleToArray = array();
377
378 /**
379 * Whether to generate VERP addresses on send.
380 * Only applicable when sending via SMTP.
381 * @link http://en.wikipedia.org/wiki/Variable_envelope_return_path
382 * @link http://www.postfix.org/VERP_README.html Postfix VERP info
383 * @type boolean
384 */
385 public $do_verp = false;
386
387 /**
388 * Whether to allow sending messages with an empty body.
389 * @type boolean
390 */
391 public $AllowEmpty = false;
392
393 /**
394 * The default line ending.
395 * @note The default remains "\n". We force CRLF where we know
396 * it must be used via self::CRLF.
397 * @type string
398 */
399 public $LE = "\n";
400
401 /**
402 * DKIM selector.
403 * @type string
404 */
405 public $DKIM_selector = '';
406
407 /**
408 * DKIM Identity.
409 * Usually the email address used as the source of the email
410 * @type string
411 */
412 public $DKIM_identity = '';
413
414 /**
415 * DKIM passphrase.
416 * Used if your key is encrypted.
417 * @type string
418 */
419 public $DKIM_passphrase = '';
420
421 /**
422 * DKIM signing domain name.
423 * @example 'example.com'
424 * @type string
425 */
426 public $DKIM_domain = '';
427
428 /**
429 * DKIM private key file path.
430 * @type string
431 */
432 public $DKIM_private = '';
433
434 /**
435 * Callback Action function name.
436 *
437 * The function that handles the result of the send email action.
438 * It is called out by send() for each email sent.
439 *
440 * Value can be any php callable: http://www.php.net/is_callable
441 *
442 * Parameters:
443 * boolean $result result of the send action
444 * string $to email address of the recipient
445 * string $cc cc email addresses
446 * string $bcc bcc email addresses
447 * string $subject the subject
448 * string $body the email body
449 * string $from email address of sender
450 * @type string
451 */
452 public $action_function = '';
453
454 /**
455 * What to put in the X-Mailer header.
456 * Options: An empty string for PHPMailer default, whitespace for none, or a string to use
457 * @type string
458 */
459 public $XMailer = '';
460
461 /**
462 * An instance of the SMTP sender class.
463 * @type SMTP
464 * @access protected
465 */
466 protected $smtp = null;
467
468 /**
469 * The array of 'to' addresses.
470 * @type array
471 * @access protected
472 */
473 protected $to = array();
474
475 /**
476 * The array of 'cc' addresses.
477 * @type array
478 * @access protected
479 */
480 protected $cc = array();
481
482 /**
483 * The array of 'bcc' addresses.
484 * @type array
485 * @access protected
486 */
487 protected $bcc = array();
488
489 /**
490 * The array of reply-to names and addresses.
491 * @type array
492 * @access protected
493 */
494 protected $ReplyTo = array();
495
496 /**
497 * An array of all kinds of addresses.
498 * Includes all of $to, $cc, $bcc, $replyto
499 * @type array
500 * @access protected
501 */
502 protected $all_recipients = array();
503
504 /**
505 * The array of attachments.
506 * @type array
507 * @access protected
508 */
509 protected $attachment = array();
510
511 /**
512 * The array of custom headers.
513 * @type array
514 * @access protected
515 */
516 protected $CustomHeader = array();
517
518 /**
519 * The most recent Message-ID (including angular brackets).
520 * @type string
521 * @access protected
522 */
523 protected $lastMessageID = '';
524
525 /**
526 * The message's MIME type.
527 * @type string
528 * @access protected
529 */
530 protected $message_type = '';
531
532 /**
533 * The array of MIME boundary strings.
534 * @type array
535 * @access protected
536 */
537 protected $boundary = array();
538
539 /**
540 * The array of available languages.
541 * @type array
542 * @access protected
543 */
544 protected $language = array();
545
546 /**
547 * The number of errors encountered.
548 * @type integer
549 * @access protected
550 */
551 protected $error_count = 0;
552
553 /**
554 * The S/MIME certificate file path.
555 * @type string
556 * @access protected
557 */
558 protected $sign_cert_file = '';
559
560 /**
561 * The S/MIME key file path.
562 * @type string
563 * @access protected
564 */
565 protected $sign_key_file = '';
566
567 /**
568 * The optional S/MIME extra certificates ("CA Chain") file path.
569 * @type string
570 * @access protected
571 */
572 protected $sign_extracerts_file = '';
573
574 /**
575 * The S/MIME password for the key.
576 * Used only if the key is encrypted.
577 * @type string
578 * @access protected
579 */
580 protected $sign_key_pass = '';
581
582 /**
583 * Whether to throw exceptions for errors.
584 * @type boolean
585 * @access protected
586 */
587 protected $exceptions = false;
588
589 /**
590 * Error severity: message only, continue processing.
591 */
592 const STOP_MESSAGE = 0;
593
594 /**
595 * Error severity: message, likely ok to continue processing.
596 */
597 const STOP_CONTINUE = 1;
598
599 /**
600 * Error severity: message, plus full stop, critical error reached.
601 */
602 const STOP_CRITICAL = 2;
603
604 /**
605 * SMTP RFC standard line ending.
606 */
607 const CRLF = "\r\n";
608
609 /**
610 * Constructor.
611 * @param boolean $exceptions Should we throw external exceptions?
612 */
613 public function __construct($exceptions = false)
614 {
615 $this->exceptions = (boolean)$exceptions;
616 }
617
618 /**
619 * Destructor.
620 */
621 public function __destruct()
622 {
623 //Close any open SMTP connection nicely
624 if ($this->Mailer == 'smtp') {
625 $this->smtpClose();
626 }
627 }
628
629 /**
630 * Call mail() in a safe_mode-aware fashion.
631 * Also, unless sendmail_path points to sendmail (or something that
632 * claims to be sendmail), don't pass params (not a perfect fix,
633 * but it will do)
634 * @param string $to To
635 * @param string $subject Subject
636 * @param string $body Message Body
637 * @param string $header Additional Header(s)
638 * @param string $params Params
639 * @access private
640 * @return boolean
641 */
642 private function mailPassthru($to, $subject, $body, $header, $params)
643 {
644 //Check overloading of mail function to avoid double-encoding
645 if (ini_get('mbstring.func_overload') & 1) {
646 $subject = $this->secureHeader($subject);
647 } else {
648 $subject = $this->encodeHeader($this->secureHeader($subject));
649 }
650 if (ini_get('safe_mode') || !($this->UseSendmailOptions)) {
651 $result = @mail($to, $subject, $body, $header);
652 } else {
653 $result = @mail($to, $subject, $body, $header, $params);
654 }
655 return $result;
656 }
657
658 /**
659 * Output debugging info via user-defined method.
660 * Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug).
661 * @see PHPMailer::$Debugoutput
662 * @see PHPMailer::$SMTPDebug
663 * @param string $str
664 */
665 protected function edebug($str)
666 {
667 if ($this->SMTPDebug <= 0) {
668 return;
669 }
670 //Avoid clash with built-in function names
671 if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
672 call_user_func($this->Debugoutput, $str, $this->SMTPDebug);
673 return;
674 }
675 switch ($this->Debugoutput) {
676 case 'error_log':
677 //Don't output, just log
678 error_log($str);
679 break;
680 case 'html':
681 //Cleans up output a bit for a better looking, HTML-safe output
682 echo htmlentities(
683 preg_replace('/[\r\n]+/', '', $str),
684 ENT_QUOTES,
685 'UTF-8'
686 )
687 . "<br>\n";
688 break;
689 case 'echo':
690 default:
691 //Normalize line breaks
692 $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str);
693 echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
694 "\n",
695 "\n \t ",
696 trim($str)
697 ) . "\n";
698 }
699 }
700
701 /**
702 * Sets message type to HTML or plain.
703 * @param boolean $isHtml True for HTML mode.
704 * @return void
705 */
706 public function isHTML($isHtml = true)
707 {
708 if ($isHtml) {
709 $this->ContentType = 'text/html';
710 } else {
711 $this->ContentType = 'text/plain';
712 }
713 }
714
715 /**
716 * Send messages using SMTP.
717 * @return void
718 */
719 public function isSMTP()
720 {
721 $this->Mailer = 'smtp';
722 }
723
724 /**
725 * Send messages using PHP's mail() function.
726 * @return void
727 */
728 public function isMail()
729 {
730 $this->Mailer = 'mail';
731 }
732
733 /**
734 * Send messages using $Sendmail.
735 * @return void
736 */
737 public function isSendmail()
738 {
739 $ini_sendmail_path = ini_get('sendmail_path');
740
741 if (!stristr($ini_sendmail_path, 'sendmail')) {
742 $this->Sendmail = '/usr/sbin/sendmail';
743 } else {
744 $this->Sendmail = $ini_sendmail_path;
745 }
746 $this->Mailer = 'sendmail';
747 }
748
749 /**
750 * Send messages using qmail.
751 * @return void
752 */
753 public function isQmail()
754 {
755 $ini_sendmail_path = ini_get('sendmail_path');
756
757 if (!stristr($ini_sendmail_path, 'qmail')) {
758 $this->Sendmail = '/var/qmail/bin/qmail-inject';
759 } else {
760 $this->Sendmail = $ini_sendmail_path;
761 }
762 $this->Mailer = 'qmail';
763 }
764
765 /**
766 * Add a "To" address.
767 * @param string $address
768 * @param string $name
769 * @return boolean true on success, false if address already used
770 */
771 public function addAddress($address, $name = '')
772 {
773 return $this->addAnAddress('to', $address, $name);
774 }
775
776 /**
777 * Add a "CC" address.
778 * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer.
779 * @param string $address
780 * @param string $name
781 * @return boolean true on success, false if address already used
782 */
783 public function addCC($address, $name = '')
784 {
785 return $this->addAnAddress('cc', $address, $name);
786 }
787
788 /**
789 * Add a "BCC" address.
790 * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer.
791 * @param string $address
792 * @param string $name
793 * @return boolean true on success, false if address already used
794 */
795 public function addBCC($address, $name = '')
796 {
797 return $this->addAnAddress('bcc', $address, $name);
798 }
799
800 /**
801 * Add a "Reply-to" address.
802 * @param string $address
803 * @param string $name
804 * @return boolean
805 */
806 public function addReplyTo($address, $name = '')
807 {
808 return $this->addAnAddress('Reply-To', $address, $name);
809 }
810
811 /**
812 * Add an address to one of the recipient arrays.
813 * Addresses that have been added already return false, but do not throw exceptions
814 * @param string $kind One of 'to', 'cc', 'bcc', 'ReplyTo'
815 * @param string $address The email address to send to
816 * @param string $name
817 * @throws phpmailerException
818 * @return boolean true on success, false if address already used or invalid in some way
819 * @access protected
820 */
821 protected function addAnAddress($kind, $address, $name = '')
822 {
823 if (!preg_match('/^(to|cc|bcc|Reply-To)$/', $kind)) {
824 $this->setError($this->lang('Invalid recipient array') . ': ' . $kind);
825 $this->edebug($this->lang('Invalid recipient array') . ': ' . $kind);
826 if ($this->exceptions) {
827 throw new phpmailerException('Invalid recipient array: ' . $kind);
828 }
829 return false;
830 }
831 $address = trim($address);
832 $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
833 if (!$this->validateAddress($address)) {
834 $this->setError($this->lang('invalid_address') . ': ' . $address);
835 $this->edebug($this->lang('invalid_address') . ': ' . $address);
836 if ($this->exceptions) {
837 throw new phpmailerException($this->lang('invalid_address') . ': ' . $address);
838 }
839 return false;
840 }
841 if ($kind != 'Reply-To') {
842 if (!isset($this->all_recipients[strtolower($address)])) {
843 array_push($this->$kind, array($address, $name));
844 $this->all_recipients[strtolower($address)] = true;
845 return true;
846 }
847 } else {
848 if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
849 $this->ReplyTo[strtolower($address)] = array($address, $name);
850 return true;
851 }
852 }
853 return false;
854 }
855
856 /**
857 * Set the From and FromName properties.
858 * @param string $address
859 * @param string $name
860 * @param boolean $auto Whether to also set the Sender address, defaults to true
861 * @throws phpmailerException
862 * @return boolean
863 */
864 public function setFrom($address, $name = '', $auto = true)
865 {
866 $address = trim($address);
867 $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
868 if (!$this->validateAddress($address)) {
869 $this->setError($this->lang('invalid_address') . ': ' . $address);
870 $this->edebug($this->lang('invalid_address') . ': ' . $address);
871 if ($this->exceptions) {
872 throw new phpmailerException($this->lang('invalid_address') . ': ' . $address);
873 }
874 return false;
875 }
876 $this->From = $address;
877 $this->FromName = $name;
878 if ($auto) {
879 if (empty($this->Sender)) {
880 $this->Sender = $address;
881 }
882 }
883 return true;
884 }
885
886 /**
887 * Return the Message-ID header of the last email.
888 * Technically this is the value from the last time the headers were created,
889 * but it's also the message ID of the last sent message except in
890 * pathological cases.
891 * @return string
892 */
893 public function getLastMessageID()
894 {
895 return $this->lastMessageID;
896 }
897
898 /**
899 * Check that a string looks like an email address.
900 * @param string $address The email address to check
901 * @param string $patternselect A selector for the validation pattern to use :
902 * * `auto` Pick strictest one automatically;
903 * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
904 * * `pcre` Use old PCRE implementation;
905 * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL; same as pcre8 but does not allow 'dotless' domains;
906 * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
907 * * `noregex` Don't use a regex: super fast, really dumb.
908 * @return boolean
909 * @static
910 * @access public
911 */
912 public static function validateAddress($address, $patternselect = 'auto')
913 {
914 if (!$patternselect or $patternselect == 'auto') {
915 //Check this constant first so it works when extension_loaded() is disabled by safe mode
916 //Constant was added in PHP 5.2.4
917 if (defined('PCRE_VERSION')) {
918 //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2
919 if (version_compare(PCRE_VERSION, '8.0.3') >= 0) {
920 $patternselect = 'pcre8';
921 } else {
922 $patternselect = 'pcre';
923 }
924 } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) {
925 //Fall back to older PCRE
926 $patternselect = 'pcre';
927 } else {
928 //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension
929 if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
930 $patternselect = 'php';
931 } else {
932 $patternselect = 'noregex';
933 }
934 }
935 }
936 switch ($patternselect) {
937 case 'pcre8':
938 /**
939 * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains.
940 * @link http://squiloople.com/2009/12/20/email-address-validation/
941 * @copyright 2009-2010 Michael Rushton
942 * Feel free to use and redistribute this code. But please keep this copyright notice.
943 */
944 return (boolean)preg_match(
945 '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
946 '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
947 '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
948 '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
949 '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
950 '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
951 '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
952 '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
953 '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
954 $address
955 );
956 case 'pcre':
957 //An older regex that doesn't need a recent PCRE
958 return (boolean)preg_match(
959 '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' .
960 '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' .
961 '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' .
962 '@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' .
963 '(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' .
964 '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' .
965 '::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' .
966 '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' .
967 '::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
968 '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD',
969 $address
970 );
971 case 'html5':
972 /**
973 * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements.
974 * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email)
975 */
976 return (boolean)preg_match(
977 '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
978 '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
979 $address
980 );
981 case 'noregex':
982 //No PCRE! Do something _very_ approximate!
983 //Check the address is 3 chars or longer and contains an @ that's not the first or last char
984 return (strlen($address) >= 3
985 and strpos($address, '@') >= 1
986 and strpos($address, '@') != strlen($address) - 1);
987 case 'php':
988 default:
989 return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL);
990 }
991 }
992
993 /**
994 * Create a message and send it.
995 * Uses the sending method specified by $Mailer.
996 * @throws phpmailerException
997 * @return boolean false on error - See the ErrorInfo property for details of the error.
998 */
999 public function send()
1000 {
1001 try {
1002 if (!$this->preSend()) {
1003 return false;
1004 }
1005 return $this->postSend();
1006 } catch (phpmailerException $exc) {
1007 $this->mailHeader = '';
1008 $this->setError($exc->getMessage());
1009 if ($this->exceptions) {
1010 throw $exc;
1011 }
1012 return false;
1013 }
1014 }
1015
1016 /**
1017 * Prepare a message for sending.
1018 * @throws phpmailerException
1019 * @return boolean
1020 */
1021 public function preSend()
1022 {
1023 try {
1024 $this->mailHeader = '';
1025 if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
1026 throw new phpmailerException($this->lang('provide_address'), self::STOP_CRITICAL);
1027 }
1028
1029 // Set whether the message is multipart/alternative
1030 if (!empty($this->AltBody)) {
1031 $this->ContentType = 'multipart/alternative';
1032 }
1033
1034 $this->error_count = 0; // reset errors
1035 $this->setMessageType();
1036 // Refuse to send an empty message unless we are specifically allowing it
1037 if (!$this->AllowEmpty and empty($this->Body)) {
1038 throw new phpmailerException($this->lang('empty_message'), self::STOP_CRITICAL);
1039 }
1040
1041 $this->MIMEHeader = $this->createHeader();
1042 $this->MIMEBody = $this->createBody();
1043
1044 // To capture the complete message when using mail(), create
1045 // an extra header list which createHeader() doesn't fold in
1046 if ($this->Mailer == 'mail') {
1047 if (count($this->to) > 0) {
1048 $this->mailHeader .= $this->addrAppend('To', $this->to);
1049 } else {
1050 $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;');
1051 }
1052 $this->mailHeader .= $this->headerLine(
1053 'Subject',
1054 $this->encodeHeader($this->secureHeader(trim($this->Subject)))
1055 );
1056 }
1057
1058 // Sign with DKIM if enabled
1059 if (!empty($this->DKIM_domain)
1060 && !empty($this->DKIM_private)
1061 && !empty($this->DKIM_selector)
1062 && file_exists($this->DKIM_private)) {
1063 $header_dkim = $this->DKIM_Add(
1064 $this->MIMEHeader . $this->mailHeader,
1065 $this->encodeHeader($this->secureHeader($this->Subject)),
1066 $this->MIMEBody
1067 );
1068 $this->MIMEHeader = rtrim($this->MIMEHeader, "\r\n ") . self::CRLF .
1069 str_replace("\r\n", "\n", $header_dkim) . self::CRLF;
1070 }
1071 return true;
1072
1073 } catch (phpmailerException $exc) {
1074 $this->setError($exc->getMessage());
1075 if ($this->exceptions) {
1076 throw $exc;
1077 }
1078 return false;
1079 }
1080 }
1081
1082 /**
1083 * Actually send a message.
1084 * Send the email via the selected mechanism
1085 * @throws phpmailerException
1086 * @return boolean
1087 */
1088 public function postSend()
1089 {
1090 try {
1091 // Choose the mailer and send through it
1092 switch ($this->Mailer) {
1093 case 'sendmail':
1094 case 'qmail':
1095 return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody);
1096 case 'smtp':
1097 return $this->smtpSend($this->MIMEHeader, $this->MIMEBody);
1098 case 'mail':
1099 return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
1100 default:
1101 $sendMethod = $this->Mailer.'Send';
1102 if (method_exists($this, $sendMethod)) {
1103 return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody);
1104 }
1105
1106 return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
1107 }
1108 } catch (phpmailerException $exc) {
1109 $this->setError($exc->getMessage());
1110 $this->edebug($exc->getMessage());
1111 if ($this->exceptions) {
1112 throw $exc;
1113 }
1114 }
1115 return false;
1116 }
1117
1118 /**
1119 * Send mail using the $Sendmail program.
1120 * @param string $header The message headers
1121 * @param string $body The message body
1122 * @see PHPMailer::$Sendmail
1123 * @throws phpmailerException
1124 * @access protected
1125 * @return boolean
1126 */
1127 protected function sendmailSend($header, $body)
1128 {
1129 if ($this->Sender != '') {
1130 if ($this->Mailer == 'qmail') {
1131 $sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
1132 } else {
1133 $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
1134 }
1135 } else {
1136 if ($this->Mailer == 'qmail') {
1137 $sendmail = sprintf('%s', escapeshellcmd($this->Sendmail));
1138 } else {
1139 $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail));
1140 }
1141 }
1142 if ($this->SingleTo) {
1143 foreach ($this->SingleToArray as $toAddr) {
1144 if (!@$mail = popen($sendmail, 'w')) {
1145 throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1146 }
1147 fputs($mail, 'To: ' . $toAddr . "\n");
1148 fputs($mail, $header);
1149 fputs($mail, $body);
1150 $result = pclose($mail);
1151 $this->doCallback(
1152 ($result == 0),
1153 array($toAddr),
1154 $this->cc,
1155 $this->bcc,
1156 $this->Subject,
1157 $body,
1158 $this->From
1159 );
1160 if ($result != 0) {
1161 throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1162 }
1163 }
1164 } else {
1165 if (!@$mail = popen($sendmail, 'w')) {
1166 throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1167 }
1168 fputs($mail, $header);
1169 fputs($mail, $body);
1170 $result = pclose($mail);
1171 $this->doCallback(($result == 0), $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From);
1172 if ($result != 0) {
1173 throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1174 }
1175 }
1176 return true;
1177 }
1178
1179 /**
1180 * Send mail using the PHP mail() function.
1181 * @param string $header The message headers
1182 * @param string $body The message body
1183 * @link http://www.php.net/manual/en/book.mail.php
1184 * @throws phpmailerException
1185 * @access protected
1186 * @return boolean
1187 */
1188 protected function mailSend($header, $body)
1189 {
1190 $toArr = array();
1191 foreach ($this->to as $toaddr) {
1192 $toArr[] = $this->addrFormat($toaddr);
1193 }
1194 $to = implode(', ', $toArr);
1195
1196 if (empty($this->Sender)) {
1197 $params = ' ';
1198 } else {
1199 $params = sprintf('-f%s', $this->Sender);
1200 }
1201 if ($this->Sender != '' and !ini_get('safe_mode')) {
1202 $old_from = ini_get('sendmail_from');
1203 ini_set('sendmail_from', $this->Sender);
1204 }
1205 $result = false;
1206 if ($this->SingleTo && count($toArr) > 1) {
1207 foreach ($toArr as $toAddr) {
1208 $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
1209 $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From);
1210 }
1211 } else {
1212 $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params);
1213 $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From);
1214 }
1215 if (isset($old_from)) {
1216 ini_set('sendmail_from', $old_from);
1217 }
1218 if (!$result) {
1219 throw new phpmailerException($this->lang('instantiate'), self::STOP_CRITICAL);
1220 }
1221 return true;
1222 }
1223
1224 /**
1225 * Get an instance to use for SMTP operations.
1226 * Override this function to load your own SMTP implementation
1227 * @return SMTP
1228 */
1229 public function getSMTPInstance()
1230 {
1231 if (!is_object($this->smtp)) {
1232 $this->smtp = new SMTP;
1233 }
1234 return $this->smtp;
1235 }
1236
1237 /**
1238 * Send mail via SMTP.
1239 * Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
1240 * Uses the PHPMailerSMTP class by default.
1241 * @see PHPMailer::getSMTPInstance() to use a different class.
1242 * @param string $header The message headers
1243 * @param string $body The message body
1244 * @throws phpmailerException
1245 * @uses SMTP
1246 * @access protected
1247 * @return boolean
1248 */
1249 protected function smtpSend($header, $body)
1250 {
1251 $bad_rcpt = array();
1252
1253 if (!$this->smtpConnect()) {
1254 throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
1255 }
1256 if ('' == $this->Sender) {
1257 $smtp_from = $this->From;
1258 } else {
1259 $smtp_from = $this->Sender;
1260 }
1261 if (!$this->smtp->mail($smtp_from)) {
1262 $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
1263 throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL);
1264 }
1265
1266 // Attempt to send to all recipients
1267 foreach ($this->to as $to) {
1268 if (!$this->smtp->recipient($to[0])) {
1269 $bad_rcpt[] = $to[0];
1270 $isSent = false;
1271 } else {
1272 $isSent = true;
1273 }
1274 $this->doCallback($isSent, array($to[0]), array(), array(), $this->Subject, $body, $this->From);
1275 }
1276 foreach ($this->cc as $cc) {
1277 if (!$this->smtp->recipient($cc[0])) {
1278 $bad_rcpt[] = $cc[0];
1279 $isSent = false;
1280 } else {
1281 $isSent = true;
1282 }
1283 $this->doCallback($isSent, array(), array($cc[0]), array(), $this->Subject, $body, $this->From);
1284 }
1285 foreach ($this->bcc as $bcc) {
1286 if (!$this->smtp->recipient($bcc[0])) {
1287 $bad_rcpt[] = $bcc[0];
1288 $isSent = false;
1289 } else {
1290 $isSent = true;
1291 }
1292 $this->doCallback($isSent, array(), array(), array($bcc[0]), $this->Subject, $body, $this->From);
1293 }
1294
1295 // Only send the DATA command if we have viable recipients
1296 if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) {
1297 throw new phpmailerException($this->lang('data_not_accepted'), self::STOP_CRITICAL);
1298 }
1299 if ($this->SMTPKeepAlive) {
1300 $this->smtp->reset();
1301 } else {
1302 $this->smtp->quit();
1303 $this->smtp->close();
1304 }
1305 //Create error message for any bad addresses
1306 if (count($bad_rcpt) > 0) {
1307 throw new phpmailerException(
1308 $this->lang('recipients_failed') . implode(', ', $bad_rcpt),
1309 self::STOP_CONTINUE
1310 );
1311 }
1312 return true;
1313 }
1314
1315 /**
1316 * Initiate a connection to an SMTP server.
1317 * Returns false if the operation failed.
1318 * @param array $options An array of options compatible with stream_context_create()
1319 * @uses SMTP
1320 * @access public
1321 * @throws phpmailerException
1322 * @return boolean
1323 */
1324 public function smtpConnect($options = array())
1325 {
1326 if (is_null($this->smtp)) {
1327 $this->smtp = $this->getSMTPInstance();
1328 }
1329
1330 // Already connected?
1331 if ($this->smtp->connected()) {
1332 return true;
1333 }
1334
1335 $this->smtp->setTimeout($this->Timeout);
1336 $this->smtp->setDebugLevel($this->SMTPDebug);
1337 $this->smtp->setDebugOutput($this->Debugoutput);
1338 $this->smtp->setVerp($this->do_verp);
1339 $hosts = explode(';', $this->Host);
1340 $lastexception = null;
1341
1342 foreach ($hosts as $hostentry) {
1343 $hostinfo = array();
1344 if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) {
1345 // Not a valid host entry
1346 continue;
1347 }
1348 // $hostinfo[2]: optional ssl or tls prefix
1349 // $hostinfo[3]: the hostname
1350 // $hostinfo[4]: optional port number
1351 // The host string prefix can temporarily override the current setting for SMTPSecure
1352 // If it's not specified, the default value is used
1353 $prefix = '';
1354 $tls = ($this->SMTPSecure == 'tls');
1355 if ($hostinfo[2] == 'ssl' or ($hostinfo[2] == '' and $this->SMTPSecure == 'ssl')) {
1356 $prefix = 'ssl://';
1357 $tls = false; // Can't have SSL and TLS at once
1358 } elseif ($hostinfo[2] == 'tls') {
1359 $tls = true;
1360 // tls doesn't use a prefix
1361 }
1362 $host = $hostinfo[3];
1363 $port = $this->Port;
1364 $tport = (integer)$hostinfo[4];
1365 if ($tport > 0 and $tport < 65536) {
1366 $port = $tport;
1367 }
1368 if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
1369 try {
1370 if ($this->Helo) {
1371 $hello = $this->Helo;
1372 } else {
1373 $hello = $this->serverHostname();
1374 }
1375 $this->smtp->hello($hello);
1376
1377 if ($tls) {
1378 if (!$this->smtp->startTLS()) {
1379 throw new phpmailerException($this->lang('connect_host'));
1380 }
1381 // We must resend HELO after tls negotiation
1382 $this->smtp->hello($hello);
1383 }
1384 if ($this->SMTPAuth) {
1385 if (!$this->smtp->authenticate(
1386 $this->Username,
1387 $this->Password,
1388 $this->AuthType,
1389 $this->Realm,
1390 $this->Workstation
1391 )
1392 ) {
1393 throw new phpmailerException($this->lang('authenticate'));
1394 }
1395 }
1396 return true;
1397 } catch (phpmailerException $exc) {
1398 $lastexception = $exc;
1399 // We must have connected, but then failed TLS or Auth, so close connection nicely
1400 $this->smtp->quit();
1401 }
1402 }
1403 }
1404 // If we get here, all connection attempts have failed, so close connection hard
1405 $this->smtp->close();
1406 // As we've caught all exceptions, just report whatever the last one was
1407 if ($this->exceptions and !is_null($lastexception)) {
1408 throw $lastexception;
1409 }
1410 return false;
1411 }
1412
1413 /**
1414 * Close the active SMTP session if one exists.
1415 * @return void
1416 */
1417 public function smtpClose()
1418 {
1419 if ($this->smtp !== null) {
1420 if ($this->smtp->connected()) {
1421 $this->smtp->quit();
1422 $this->smtp->close();
1423 }
1424 }
1425 }
1426
1427 /**
1428 * Set the language for error messages.
1429 * Returns false if it cannot load the language file.
1430 * The default language is English.
1431 * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr")
1432 * @param string $lang_path Path to the language file directory, with trailing separator (slash)
1433 * @return boolean
1434 * @access public
1435 */
1436 public function setLanguage($langcode = 'en', $lang_path = '')
1437 {
1438 // Define full set of translatable strings in English
1439 $PHPMAILER_LANG = array(
1440 'authenticate' => 'SMTP Error: Could not authenticate.',
1441 'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
1442 'data_not_accepted' => 'SMTP Error: data not accepted.',
1443 'empty_message' => 'Message body empty',
1444 'encoding' => 'Unknown encoding: ',
1445 'execute' => 'Could not execute: ',
1446 'file_access' => 'Could not access file: ',
1447 'file_open' => 'File Error: Could not open file: ',
1448 'from_failed' => 'The following From address failed: ',
1449 'instantiate' => 'Could not instantiate mail function.',
1450 'invalid_address' => 'Invalid address',
1451 'mailer_not_supported' => ' mailer is not supported.',
1452 'provide_address' => 'You must provide at least one recipient email address.',
1453 'recipients_failed' => 'SMTP Error: The following recipients failed: ',
1454 'signing' => 'Signing Error: ',
1455 'smtp_connect_failed' => 'SMTP connect() failed.',
1456 'smtp_error' => 'SMTP server error: ',
1457 'variable_set' => 'Cannot set or reset variable: '
1458 );
1459 if (empty($lang_path)) {
1460 // Calculate an absolute path so it can work if CWD is not here
1461 $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR;
1462 }
1463 $foundlang = true;
1464 $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php';
1465 if ($langcode != 'en') { // There is no English translation file
1466 // Make sure language file path is readable
1467 if (!is_readable($lang_file)) {
1468 $foundlang = false;
1469 } else {
1470 // Overwrite language-specific strings.
1471 // This way we'll never have missing translations.
1472 $foundlang = include $lang_file;
1473 }
1474 }
1475 $this->language = $PHPMAILER_LANG;
1476 return (boolean)$foundlang; // Returns false if language not found
1477 }
1478
1479 /**
1480 * Get the array of strings for the current language.
1481 * @return array
1482 */
1483 public function getTranslations()
1484 {
1485 return $this->language;
1486 }
1487
1488 /**
1489 * Create recipient headers.
1490 * @access public
1491 * @param string $type
1492 * @param array $addr An array of recipient,
1493 * where each recipient is a 2-element indexed array with element 0 containing an address
1494 * and element 1 containing a name, like:
1495 * array(array('joe@example.com', 'Joe User'), array('zoe@example.com', 'Zoe User'))
1496 * @return string
1497 */
1498 public function addrAppend($type, $addr)
1499 {
1500 $addresses = array();
1501 foreach ($addr as $address) {
1502 $addresses[] = $this->addrFormat($address);
1503 }
1504 return $type . ': ' . implode(', ', $addresses) . $this->LE;
1505 }
1506
1507 /**
1508 * Format an address for use in a message header.
1509 * @access public
1510 * @param array $addr A 2-element indexed array, element 0 containing an address, element 1 containing a name
1511 * like array('joe@example.com', 'Joe User')
1512 * @return string
1513 */
1514 public function addrFormat($addr)
1515 {
1516 if (empty($addr[1])) { // No name provided
1517 return $this->secureHeader($addr[0]);
1518 } else {
1519 return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader(
1520 $addr[0]
1521 ) . '>';
1522 }
1523 }
1524
1525 /**
1526 * Word-wrap message.
1527 * For use with mailers that do not automatically perform wrapping
1528 * and for quoted-printable encoded messages.
1529 * Original written by philippe.
1530 * @param string $message The message to wrap
1531 * @param integer $length The line length to wrap to
1532 * @param boolean $qp_mode Whether to run in Quoted-Printable mode
1533 * @access public
1534 * @return string
1535 */
1536 public function wrapText($message, $length, $qp_mode = false)
1537 {
1538 if ($qp_mode) {
1539 $soft_break = sprintf(' =%s', $this->LE);
1540 } else {
1541 $soft_break = $this->LE;
1542 }
1543 // If utf-8 encoding is used, we will need to make sure we don't
1544 // split multibyte characters when we wrap
1545 $is_utf8 = (strtolower($this->CharSet) == 'utf-8');
1546 $lelen = strlen($this->LE);
1547 $crlflen = strlen(self::CRLF);
1548
1549 $message = $this->fixEOL($message);
1550 //Remove a trailing line break
1551 if (substr($message, -$lelen) == $this->LE) {
1552 $message = substr($message, 0, -$lelen);
1553 }
1554
1555 //Split message into lines
1556 $lines = explode($this->LE, $message);
1557 //Message will be rebuilt in here
1558 $message = '';
1559 foreach ($lines as $line) {
1560 $words = explode(' ', $line);
1561 $buf = '';
1562 $firstword = true;
1563 foreach ($words as $word) {
1564 if ($qp_mode and (strlen($word) > $length)) {
1565 $space_left = $length - strlen($buf) - $crlflen;
1566 if (!$firstword) {
1567 if ($space_left > 20) {
1568 $len = $space_left;
1569 if ($is_utf8) {
1570 $len = $this->utf8CharBoundary($word, $len);
1571 } elseif (substr($word, $len - 1, 1) == '=') {
1572 $len--;
1573 } elseif (substr($word, $len - 2, 1) == '=') {
1574 $len -= 2;
1575 }
1576 $part = substr($word, 0, $len);
1577 $word = substr($word, $len);
1578 $buf .= ' ' . $part;
1579 $message .= $buf . sprintf('=%s', self::CRLF);
1580 } else {
1581 $message .= $buf . $soft_break;
1582 }
1583 $buf = '';
1584 }
1585 while (strlen($word) > 0) {
1586 if ($length <= 0) {
1587 break;
1588 }
1589 $len = $length;
1590 if ($is_utf8) {
1591 $len = $this->utf8CharBoundary($word, $len);
1592 } elseif (substr($word, $len - 1, 1) == '=') {
1593 $len--;
1594 } elseif (substr($word, $len - 2, 1) == '=') {
1595 $len -= 2;
1596 }
1597 $part = substr($word, 0, $len);
1598 $word = substr($word, $len);
1599
1600 if (strlen($word) > 0) {
1601 $message .= $part . sprintf('=%s', self::CRLF);
1602 } else {
1603 $buf = $part;
1604 }
1605 }
1606 } else {
1607 $buf_o = $buf;
1608 if (!$firstword) {
1609 $buf .= ' ';
1610 }
1611 $buf .= $word;
1612
1613 if (strlen($buf) > $length and $buf_o != '') {
1614 $message .= $buf_o . $soft_break;
1615 $buf = $word;
1616 }
1617 }
1618 $firstword = false;
1619 }
1620 $message .= $buf . self::CRLF;
1621 }
1622
1623 return $message;
1624 }
1625
1626 /**
1627 * Find the last character boundary prior to $maxLength in a utf-8
1628 * quoted-printable encoded string.
1629 * Original written by Colin Brown.
1630 * @access public
1631 * @param string $encodedText utf-8 QP text
1632 * @param integer $maxLength Find the last character boundary prior to this length
1633 * @return integer
1634 */
1635 public function utf8CharBoundary($encodedText, $maxLength)
1636 {
1637 $foundSplitPos = false;
1638 $lookBack = 3;
1639 while (!$foundSplitPos) {
1640 $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
1641 $encodedCharPos = strpos($lastChunk, '=');
1642 if (false !== $encodedCharPos) {
1643 // Found start of encoded character byte within $lookBack block.
1644 // Check the encoded byte value (the 2 chars after the '=')
1645 $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
1646 $dec = hexdec($hex);
1647 if ($dec < 128) {
1648 // Single byte character.
1649 // If the encoded char was found at pos 0, it will fit
1650 // otherwise reduce maxLength to start of the encoded char
1651 if ($encodedCharPos > 0) {
1652 $maxLength = $maxLength - ($lookBack - $encodedCharPos);
1653 }
1654 $foundSplitPos = true;
1655 } elseif ($dec >= 192) {
1656 // First byte of a multi byte character
1657 // Reduce maxLength to split at start of character
1658 $maxLength = $maxLength - ($lookBack - $encodedCharPos);
1659 $foundSplitPos = true;
1660 } elseif ($dec < 192) {
1661 // Middle byte of a multi byte character, look further back
1662 $lookBack += 3;
1663 }
1664 } else {
1665 // No encoded character found
1666 $foundSplitPos = true;
1667 }
1668 }
1669 return $maxLength;
1670 }
1671
1672 /**
1673 * Apply word wrapping to the message body.
1674 * Wraps the message body to the number of chars set in the WordWrap property.
1675 * You should only do this to plain-text bodies as wrapping HTML tags may break them.
1676 * This is called automatically by createBody(), so you don't need to call it yourself.
1677 * @access public
1678 * @return void
1679 */
1680 public function setWordWrap()
1681 {
1682 if ($this->WordWrap < 1) {
1683 return;
1684 }
1685
1686 switch ($this->message_type) {
1687 case 'alt':
1688 case 'alt_inline':
1689 case 'alt_attach':
1690 case 'alt_inline_attach':
1691 $this->AltBody = $this->wrapText($this->AltBody, $this->WordWrap);
1692 break;
1693 default:
1694 $this->Body = $this->wrapText($this->Body, $this->WordWrap);
1695 break;
1696 }
1697 }
1698
1699 /**
1700 * Assemble message headers.
1701 * @access public
1702 * @return string The assembled headers
1703 */
1704 public function createHeader()
1705 {
1706 $result = '';
1707
1708 // Set the boundaries
1709 $uniq_id = md5(uniqid(time()));
1710 $this->boundary[1] = 'b1_' . $uniq_id;
1711 $this->boundary[2] = 'b2_' . $uniq_id;
1712 $this->boundary[3] = 'b3_' . $uniq_id;
1713
1714 if ($this->MessageDate == '') {
1715 $this->MessageDate = self::rfcDate();
1716 }
1717 $result .= $this->headerLine('Date', $this->MessageDate);
1718
1719
1720 // To be created automatically by mail()
1721 if ($this->SingleTo) {
1722 if ($this->Mailer != 'mail') {
1723 foreach ($this->to as $toaddr) {
1724 $this->SingleToArray[] = $this->addrFormat($toaddr);
1725 }
1726 }
1727 } else {
1728 if (count($this->to) > 0) {
1729 if ($this->Mailer != 'mail') {
1730 $result .= $this->addrAppend('To', $this->to);
1731 }
1732 } elseif (count($this->cc) == 0) {
1733 $result .= $this->headerLine('To', 'undisclosed-recipients:;');
1734 }
1735 }
1736
1737 $result .= $this->addrAppend('From', array(array(trim($this->From), $this->FromName)));
1738
1739 // sendmail and mail() extract Cc from the header before sending
1740 if (count($this->cc) > 0) {
1741 $result .= $this->addrAppend('Cc', $this->cc);
1742 }
1743
1744 // sendmail and mail() extract Bcc from the header before sending
1745 if ((
1746 $this->Mailer == 'sendmail' or $this->Mailer == 'qmail' or $this->Mailer == 'mail'
1747 )
1748 and count($this->bcc) > 0
1749 ) {
1750 $result .= $this->addrAppend('Bcc', $this->bcc);
1751 }
1752
1753 if (count($this->ReplyTo) > 0) {
1754 $result .= $this->addrAppend('Reply-To', $this->ReplyTo);
1755 }
1756
1757 // mail() sets the subject itself
1758 if ($this->Mailer != 'mail') {
1759 $result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject)));
1760 }
1761
1762 if ($this->MessageID != '') {
1763 $this->lastMessageID = $this->MessageID;
1764 } else {
1765 $this->lastMessageID = sprintf('<%s@%s>', $uniq_id, $this->ServerHostname());
1766 }
1767 $result .= $this->HeaderLine('Message-ID', $this->lastMessageID);
1768 $result .= $this->headerLine('X-Priority', $this->Priority);
1769 if ($this->XMailer == '') {
1770 $result .= $this->headerLine(
1771 'X-Mailer',
1772 'PHPMailer ' . $this->Version . ' (https://github.com/PHPMailer/PHPMailer/)'
1773 );
1774 } else {
1775 $myXmailer = trim($this->XMailer);
1776 if ($myXmailer) {
1777 $result .= $this->headerLine('X-Mailer', $myXmailer);
1778 }
1779 }
1780
1781 if ($this->ConfirmReadingTo != '') {
1782 $result .= $this->headerLine('Disposition-Notification-To', '<' . trim($this->ConfirmReadingTo) . '>');
1783 }
1784
1785 // Add custom headers
1786 foreach ($this->CustomHeader as $header) {
1787 $result .= $this->headerLine(
1788 trim($header[0]),
1789 $this->encodeHeader(trim($header[1]))
1790 );
1791 }
1792 if (!$this->sign_key_file) {
1793 $result .= $this->headerLine('MIME-Version', '1.0');
1794 $result .= $this->getMailMIME();
1795 }
1796
1797 return $result;
1798 }
1799
1800 /**
1801 * Get the message MIME type headers.
1802 * @access public
1803 * @return string
1804 */
1805 public function getMailMIME()
1806 {
1807 $result = '';
1808 $ismultipart = true;
1809 switch ($this->message_type) {
1810 case 'inline':
1811 $result .= $this->headerLine('Content-Type', 'multipart/related;');
1812 $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
1813 break;
1814 case 'attach':
1815 case 'inline_attach':
1816 case 'alt_attach':
1817 case 'alt_inline_attach':
1818 $result .= $this->headerLine('Content-Type', 'multipart/mixed;');
1819 $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
1820 break;
1821 case 'alt':
1822 case 'alt_inline':
1823 $result .= $this->headerLine('Content-Type', 'multipart/alternative;');
1824 $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
1825 break;
1826 default:
1827 // Catches case 'plain': and case '':
1828 $result .= $this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet);
1829 $ismultipart = false;
1830 break;
1831 }
1832 // RFC1341 part 5 says 7bit is assumed if not specified
1833 if ($this->Encoding != '7bit') {
1834 // RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
1835 if ($ismultipart) {
1836 if ($this->Encoding == '8bit') {
1837 $result .= $this->headerLine('Content-Transfer-Encoding', '8bit');
1838 }
1839 // The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible
1840 } else {
1841 $result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding);
1842 }
1843 }
1844
1845 if ($this->Mailer != 'mail') {
1846 $result .= $this->LE;
1847 }
1848
1849 return $result;
1850 }
1851
1852 /**
1853 * Returns the whole MIME message.
1854 * Includes complete headers and body.
1855 * Only valid post preSend().
1856 * @see PHPMailer::preSend()
1857 * @access public
1858 * @return string
1859 */
1860 public function getSentMIMEMessage()
1861 {
1862 return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody;
1863 }
1864
1865 /**
1866 * Assemble the message body.
1867 * Returns an empty string on failure.
1868 * @access public
1869 * @throws phpmailerException
1870 * @return string The assembled message body
1871 */
1872 public function createBody()
1873 {
1874 $body = '';
1875
1876 if ($this->sign_key_file) {
1877 $body .= $this->getMailMIME() . $this->LE;
1878 }
1879
1880 $this->setWordWrap();
1881
1882 $bodyEncoding = $this->Encoding;
1883 $bodyCharSet = $this->CharSet;
1884 if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) {
1885 $bodyEncoding = '7bit';
1886 $bodyCharSet = 'us-ascii';
1887 }
1888 $altBodyEncoding = $this->Encoding;
1889 $altBodyCharSet = $this->CharSet;
1890 if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) {
1891 $altBodyEncoding = '7bit';
1892 $altBodyCharSet = 'us-ascii';
1893 }
1894 switch ($this->message_type) {
1895 case 'inline':
1896 $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
1897 $body .= $this->encodeString($this->Body, $bodyEncoding);
1898 $body .= $this->LE . $this->LE;
1899 $body .= $this->attachAll('inline', $this->boundary[1]);
1900 break;
1901 case 'attach':
1902 $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
1903 $body .= $this->encodeString($this->Body, $bodyEncoding);
1904 $body .= $this->LE . $this->LE;
1905 $body .= $this->attachAll('attachment', $this->boundary[1]);
1906 break;
1907 case 'inline_attach':
1908 $body .= $this->textLine('--' . $this->boundary[1]);
1909 $body .= $this->headerLine('Content-Type', 'multipart/related;');
1910 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
1911 $body .= $this->LE;
1912 $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding);
1913 $body .= $this->encodeString($this->Body, $bodyEncoding);
1914 $body .= $this->LE . $this->LE;
1915 $body .= $this->attachAll('inline', $this->boundary[2]);
1916 $body .= $this->LE;
1917 $body .= $this->attachAll('attachment', $this->boundary[1]);
1918 break;
1919 case 'alt':
1920 $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
1921 $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
1922 $body .= $this->LE . $this->LE;
1923 $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, 'text/html', $bodyEncoding);
1924 $body .= $this->encodeString($this->Body, $bodyEncoding);
1925 $body .= $this->LE . $this->LE;
1926 if (!empty($this->Ical)) {
1927 $body .= $this->getBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', '');
1928 $body .= $this->encodeString($this->Ical, $this->Encoding);
1929 $body .= $this->LE . $this->LE;
1930 }
1931 $body .= $this->endBoundary($this->boundary[1]);
1932 break;
1933 case 'alt_inline':
1934 $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
1935 $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
1936 $body .= $this->LE . $this->LE;
1937 $body .= $this->textLine('--' . $this->boundary[1]);
1938 $body .= $this->headerLine('Content-Type', 'multipart/related;');
1939 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
1940 $body .= $this->LE;
1941 $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
1942 $body .= $this->encodeString($this->Body, $bodyEncoding);
1943 $body .= $this->LE . $this->LE;
1944 $body .= $this->attachAll('inline', $this->boundary[2]);
1945 $body .= $this->LE;
1946 $body .= $this->endBoundary($this->boundary[1]);
1947 break;
1948 case 'alt_attach':
1949 $body .= $this->textLine('--' . $this->boundary[1]);
1950 $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
1951 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
1952 $body .= $this->LE;
1953 $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
1954 $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
1955 $body .= $this->LE . $this->LE;
1956 $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
1957 $body .= $this->encodeString($this->Body, $bodyEncoding);
1958 $body .= $this->LE . $this->LE;
1959 $body .= $this->endBoundary($this->boundary[2]);
1960 $body .= $this->LE;
1961 $body .= $this->attachAll('attachment', $this->boundary[1]);
1962 break;
1963 case 'alt_inline_attach':
1964 $body .= $this->textLine('--' . $this->boundary[1]);
1965 $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
1966 $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
1967 $body .= $this->LE;
1968 $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
1969 $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
1970 $body .= $this->LE . $this->LE;
1971 $body .= $this->textLine('--' . $this->boundary[2]);
1972 $body .= $this->headerLine('Content-Type', 'multipart/related;');
1973 $body .= $this->textLine("\tboundary=\"" . $this->boundary[3] . '"');
1974 $body .= $this->LE;
1975 $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, 'text/html', $bodyEncoding);
1976 $body .= $this->encodeString($this->Body, $bodyEncoding);
1977 $body .= $this->LE . $this->LE;
1978 $body .= $this->attachAll('inline', $this->boundary[3]);
1979 $body .= $this->LE;
1980 $body .= $this->endBoundary($this->boundary[2]);
1981 $body .= $this->LE;
1982 $body .= $this->attachAll('attachment', $this->boundary[1]);
1983 break;
1984 default:
1985 // catch case 'plain' and case ''
1986 $body .= $this->encodeString($this->Body, $bodyEncoding);
1987 break;
1988 }
1989
1990 if ($this->isError()) {
1991 $body = '';
1992 } elseif ($this->sign_key_file) {
1993 try {
1994 if (!defined('PKCS7_TEXT')) {
1995 throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.');
1996 }
1997 // @TODO would be nice to use php://temp streams here, but need to wrap for PHP < 5.1
1998 $file = tempnam(sys_get_temp_dir(), 'mail');
1999 if (false === file_put_contents($file, $body)) {
2000 throw new phpmailerException($this->lang('signing') . ' Could not write temp file');
2001 }
2002 $signed = tempnam(sys_get_temp_dir(), 'signed');
2003 //Workaround for PHP bug https://bugs.php.net/bug.php?id=69197
2004 if (empty($this->sign_extracerts_file)) {
2005 $sign = @openssl_pkcs7_sign(
2006 $file,
2007 $signed,
2008 'file://' . realpath($this->sign_cert_file),
2009 array('file://' . realpath($this->sign_key_file), $this->sign_key_pass),
2010 null
2011 );
2012 } else {
2013 $sign = @openssl_pkcs7_sign(
2014 $file,
2015 $signed,
2016 'file://' . realpath($this->sign_cert_file),
2017 array('file://' . realpath($this->sign_key_file), $this->sign_key_pass),
2018 null,
2019 PKCS7_DETACHED,
2020 $this->sign_extracerts_file
2021 );
2022 }
2023 if ($sign) {
2024 @unlink($file);
2025 $body = file_get_contents($signed);
2026 @unlink($signed);
2027 } else {
2028 @unlink($file);
2029 @unlink($signed);
2030 throw new phpmailerException($this->lang('signing') . openssl_error_string());
2031 }
2032 } catch (phpmailerException $exc) {
2033 $body = '';
2034 if ($this->exceptions) {
2035 throw $exc;
2036 }
2037 }
2038 }
2039 return $body;
2040 }
2041
2042 /**
2043 * Return the start of a message boundary.
2044 * @access protected
2045 * @param string $boundary
2046 * @param string $charSet
2047 * @param string $contentType
2048 * @param string $encoding
2049 * @return string
2050 */
2051 protected function getBoundary($boundary, $charSet, $contentType, $encoding)
2052 {
2053 $result = '';
2054 if ($charSet == '') {
2055 $charSet = $this->CharSet;
2056 }
2057 if ($contentType == '') {
2058 $contentType = $this->ContentType;
2059 }
2060 if ($encoding == '') {
2061 $encoding = $this->Encoding;
2062 }
2063 $result .= $this->textLine('--' . $boundary);
2064 $result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet);
2065 $result .= $this->LE;
2066 // RFC1341 part 5 says 7bit is assumed if not specified
2067 if ($encoding != '7bit') {
2068 $result .= $this->headerLine('Content-Transfer-Encoding', $encoding);
2069 }
2070 $result .= $this->LE;
2071
2072 return $result;
2073 }
2074
2075 /**
2076 * Return the end of a message boundary.
2077 * @access protected
2078 * @param string $boundary
2079 * @return string
2080 */
2081 protected function endBoundary($boundary)
2082 {
2083 return $this->LE . '--' . $boundary . '--' . $this->LE;
2084 }
2085
2086 /**
2087 * Set the message type.
2088 * PHPMailer only supports some preset message types,
2089 * not arbitrary MIME structures.
2090 * @access protected
2091 * @return void
2092 */
2093 protected function setMessageType()
2094 {
2095 $type = array();
2096 if ($this->alternativeExists()) {
2097 $type[] = 'alt';
2098 }
2099 if ($this->inlineImageExists()) {
2100 $type[] = 'inline';
2101 }
2102 if ($this->attachmentExists()) {
2103 $type[] = 'attach';
2104 }
2105 $this->message_type = implode('_', $type);
2106 if ($this->message_type == '') {
2107 $this->message_type = 'plain';
2108 }
2109 }
2110
2111 /**
2112 * Format a header line.
2113 * @access public
2114 * @param string $name
2115 * @param string $value
2116 * @return string
2117 */
2118 public function headerLine($name, $value)
2119 {
2120 return $name . ': ' . $value . $this->LE;
2121 }
2122
2123 /**
2124 * Return a formatted mail line.
2125 * @access public
2126 * @param string $value
2127 * @return string
2128 */
2129 public function textLine($value)
2130 {
2131 return $value . $this->LE;
2132 }
2133
2134 /**
2135 * Add an attachment from a path on the filesystem.
2136 * Returns false if the file could not be found or read.
2137 * @param string $path Path to the attachment.
2138 * @param string $name Overrides the attachment name.
2139 * @param string $encoding File encoding (see $Encoding).
2140 * @param string $type File extension (MIME) type.
2141 * @param string $disposition Disposition to use
2142 * @throws phpmailerException
2143 * @return boolean
2144 */
2145 public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment')
2146 {
2147 try {
2148 if (!@is_file($path)) {
2149 throw new phpmailerException($this->lang('file_access') . $path, self::STOP_CONTINUE);
2150 }
2151
2152 // If a MIME type is not specified, try to work it out from the file name
2153 if ($type == '') {
2154 $type = self::filenameToType($path);
2155 }
2156
2157 $filename = basename($path);
2158 if ($name == '') {
2159 $name = $filename;
2160 }
2161
2162 $this->attachment[] = array(
2163 0 => $path,
2164 1 => $filename,
2165 2 => $name,
2166 3 => $encoding,
2167 4 => $type,
2168 5 => false, // isStringAttachment
2169 6 => $disposition,
2170 7 => 0
2171 );
2172
2173 } catch (phpmailerException $exc) {
2174 $this->setError($exc->getMessage());
2175 $this->edebug($exc->getMessage());
2176 if ($this->exceptions) {
2177 throw $exc;
2178 }
2179 return false;
2180 }
2181 return true;
2182 }
2183
2184 /**
2185 * Return the array of attachments.
2186 * @return array
2187 */
2188 public function getAttachments()
2189 {
2190 return $this->attachment;
2191 }
2192
2193 /**
2194 * Attach all file, string, and binary attachments to the message.
2195 * Returns an empty string on failure.
2196 * @access protected
2197 * @param string $disposition_type
2198 * @param string $boundary
2199 * @return string
2200 */
2201 protected function attachAll($disposition_type, $boundary)
2202 {
2203 // Return text of body
2204 $mime = array();
2205 $cidUniq = array();
2206 $incl = array();
2207
2208 // Add all attachments
2209 foreach ($this->attachment as $attachment) {
2210 // Check if it is a valid disposition_filter
2211 if ($attachment[6] == $disposition_type) {
2212 // Check for string attachment
2213 $string = '';
2214 $path = '';
2215 $bString = $attachment[5];
2216 if ($bString) {
2217 $string = $attachment[0];
2218 } else {
2219 $path = $attachment[0];
2220 }
2221
2222 $inclhash = md5(serialize($attachment));
2223 if (in_array($inclhash, $incl)) {
2224 continue;
2225 }
2226 $incl[] = $inclhash;
2227 $name = $attachment[2];
2228 $encoding = $attachment[3];
2229 $type = $attachment[4];
2230 $disposition = $attachment[6];
2231 $cid = $attachment[7];
2232 if ($disposition == 'inline' && isset($cidUniq[$cid])) {
2233 continue;
2234 }
2235 $cidUniq[$cid] = true;
2236
2237 $mime[] = sprintf('--%s%s', $boundary, $this->LE);
2238 $mime[] = sprintf(
2239 'Content-Type: %s; name="%s"%s',
2240 $type,
2241 $this->encodeHeader($this->secureHeader($name)),
2242 $this->LE
2243 );
2244 // RFC1341 part 5 says 7bit is assumed if not specified
2245 if ($encoding != '7bit') {
2246 $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, $this->LE);
2247 }
2248
2249 if ($disposition == 'inline') {
2250 $mime[] = sprintf('Content-ID: <%s>%s', $cid, $this->LE);
2251 }
2252
2253 // If a filename contains any of these chars, it should be quoted,
2254 // but not otherwise: RFC2183 & RFC2045 5.1
2255 // Fixes a warning in IETF's msglint MIME checker
2256 // Allow for bypassing the Content-Disposition header totally
2257 if (!(empty($disposition))) {
2258 $encoded_name = $this->encodeHeader($this->secureHeader($name));
2259 if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $encoded_name)) {
2260 $mime[] = sprintf(
2261 'Content-Disposition: %s; filename="%s"%s',
2262 $disposition,
2263 $encoded_name,
2264 $this->LE . $this->LE
2265 );
2266 } else {
2267 $mime[] = sprintf(
2268 'Content-Disposition: %s; filename=%s%s',
2269 $disposition,
2270 $encoded_name,
2271 $this->LE . $this->LE
2272 );
2273 }
2274 } else {
2275 $mime[] = $this->LE;
2276 }
2277
2278 // Encode as string attachment
2279 if ($bString) {
2280 $mime[] = $this->encodeString($string, $encoding);
2281 if ($this->isError()) {
2282 return '';
2283 }
2284 $mime[] = $this->LE . $this->LE;
2285 } else {
2286 $mime[] = $this->encodeFile($path, $encoding);
2287 if ($this->isError()) {
2288 return '';
2289 }
2290 $mime[] = $this->LE . $this->LE;
2291 }
2292 }
2293 }
2294
2295 $mime[] = sprintf('--%s--%s', $boundary, $this->LE);
2296
2297 return implode('', $mime);
2298 }
2299
2300 /**
2301 * Encode a file attachment in requested format.
2302 * Returns an empty string on failure.
2303 * @param string $path The full path to the file
2304 * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
2305 * @throws phpmailerException
2306 * @see EncodeFile(encodeFile
2307 * @access protected
2308 * @return string
2309 */
2310 protected function encodeFile($path, $encoding = 'base64')
2311 {
2312 try {
2313 if (!is_readable($path)) {
2314 throw new phpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE);
2315 }
2316 $magic_quotes = get_magic_quotes_runtime();
2317 if ($magic_quotes) {
2318 if (version_compare(PHP_VERSION, '5.3.0', '<')) {
2319 set_magic_quotes_runtime(false);
2320 } else {
2321 //Doesn't exist in PHP 5.4, but we don't need to check because
2322 //get_magic_quotes_runtime always returns false in 5.4+
2323 //so it will never get here
2324 ini_set('magic_quotes_runtime', false);
2325 }
2326 }
2327 $file_buffer = file_get_contents($path);
2328 $file_buffer = $this->encodeString($file_buffer, $encoding);
2329 if ($magic_quotes) {
2330 if (version_compare(PHP_VERSION, '5.3.0', '<')) {
2331 set_magic_quotes_runtime($magic_quotes);
2332 } else {
2333 ini_set('magic_quotes_runtime', $magic_quotes);
2334 }
2335 }
2336 return $file_buffer;
2337 } catch (Exception $exc) {
2338 $this->setError($exc->getMessage());
2339 return '';
2340 }
2341 }
2342
2343 /**
2344 * Encode a string in requested format.
2345 * Returns an empty string on failure.
2346 * @param string $str The text to encode
2347 * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable'
2348 * @access public
2349 * @return string
2350 */
2351 public function encodeString($str, $encoding = 'base64')
2352 {
2353 $encoded = '';
2354 switch (strtolower($encoding)) {
2355 case 'base64':
2356 $encoded = chunk_split(base64_encode($str), 76, $this->LE);
2357 break;
2358 case '7bit':
2359 case '8bit':
2360 $encoded = $this->fixEOL($str);
2361 // Make sure it ends with a line break
2362 if (substr($encoded, -(strlen($this->LE))) != $this->LE) {
2363 $encoded .= $this->LE;
2364 }
2365 break;
2366 case 'binary':
2367 $encoded = $str;
2368 break;
2369 case 'quoted-printable':
2370 $encoded = $this->encodeQP($str);
2371 break;
2372 default:
2373 $this->setError($this->lang('encoding') . $encoding);
2374 break;
2375 }
2376 return $encoded;
2377 }
2378
2379 /**
2380 * Encode a header string optimally.
2381 * Picks shortest of Q, B, quoted-printable or none.
2382 * @access public
2383 * @param string $str
2384 * @param string $position
2385 * @return string
2386 */
2387 public function encodeHeader($str, $position = 'text')
2388 {
2389 $matchcount = 0;
2390 switch (strtolower($position)) {
2391 case 'phrase':
2392 if (!preg_match('/[\200-\377]/', $str)) {
2393 // Can't use addslashes as we don't know the value of magic_quotes_sybase
2394 $encoded = addcslashes($str, "\0..\37\177\\\"");
2395 if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
2396 return ($encoded);
2397 } else {
2398 return ("\"$encoded\"");
2399 }
2400 }
2401 $matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
2402 break;
2403 /** @noinspection PhpMissingBreakStatementInspection */
2404 case 'comment':
2405 $matchcount = preg_match_all('/[()"]/', $str, $matches);
2406 // Intentional fall-through
2407 case 'text':
2408 default:
2409 $matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
2410 break;
2411 }
2412
2413 //There are no chars that need encoding
2414 if ($matchcount == 0) {
2415 return ($str);
2416 }
2417
2418 $maxlen = 75 - 7 - strlen($this->CharSet);
2419 // Try to select the encoding which should produce the shortest output
2420 if ($matchcount > strlen($str) / 3) {
2421 // More than a third of the content will need encoding, so B encoding will be most efficient
2422 $encoding = 'B';
2423 if (function_exists('mb_strlen') && $this->hasMultiBytes($str)) {
2424 // Use a custom function which correctly encodes and wraps long
2425 // multibyte strings without breaking lines within a character
2426 $encoded = $this->base64EncodeWrapMB($str, "\n");
2427 } else {
2428 $encoded = base64_encode($str);
2429 $maxlen -= $maxlen % 4;
2430 $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
2431 }
2432 } else {
2433 $encoding = 'Q';
2434 $encoded = $this->encodeQ($str, $position);
2435 $encoded = $this->wrapText($encoded, $maxlen, true);
2436 $encoded = str_replace('=' . self::CRLF, "\n", trim($encoded));
2437 }
2438
2439 $encoded = preg_replace('/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded);
2440 $encoded = trim(str_replace("\n", $this->LE, $encoded));
2441
2442 return $encoded;
2443 }
2444
2445 /**
2446 * Check if a string contains multi-byte characters.
2447 * @access public
2448 * @param string $str multi-byte text to wrap encode
2449 * @return boolean
2450 */
2451 public function hasMultiBytes($str)
2452 {
2453 if (function_exists('mb_strlen')) {
2454 return (strlen($str) > mb_strlen($str, $this->CharSet));
2455 } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
2456 return false;
2457 }
2458 }
2459
2460 /**
2461 * Does a string contain any 8-bit chars (in any charset)?
2462 * @param string $text
2463 * @return boolean
2464 */
2465 public function has8bitChars($text)
2466 {
2467 return (boolean)preg_match('/[\x80-\xFF]/', $text);
2468 }
2469
2470 /**
2471 * Encode and wrap long multibyte strings for mail headers
2472 * without breaking lines within a character.
2473 * Adapted from a function by paravoid
2474 * @link http://www.php.net/manual/en/function.mb-encode-mimeheader.php#60283
2475 * @access public
2476 * @param string $str multi-byte text to wrap encode
2477 * @param string $linebreak string to use as linefeed/end-of-line
2478 * @return string
2479 */
2480 public function base64EncodeWrapMB($str, $linebreak = null)
2481 {
2482 $start = '=?' . $this->CharSet . '?B?';
2483 $end = '?=';
2484 $encoded = '';
2485 if ($linebreak === null) {
2486 $linebreak = $this->LE;
2487 }
2488
2489 $mb_length = mb_strlen($str, $this->CharSet);
2490 // Each line must have length <= 75, including $start and $end
2491 $length = 75 - strlen($start) - strlen($end);
2492 // Average multi-byte ratio
2493 $ratio = $mb_length / strlen($str);
2494 // Base64 has a 4:3 ratio
2495 $avgLength = floor($length * $ratio * .75);
2496
2497 for ($i = 0; $i < $mb_length; $i += $offset) {
2498 $lookBack = 0;
2499 do {
2500 $offset = $avgLength - $lookBack;
2501 $chunk = mb_substr($str, $i, $offset, $this->CharSet);
2502 $chunk = base64_encode($chunk);
2503 $lookBack++;
2504 } while (strlen($chunk) > $length);
2505 $encoded .= $chunk . $linebreak;
2506 }
2507
2508 // Chomp the last linefeed
2509 $encoded = substr($encoded, 0, -strlen($linebreak));
2510 return $encoded;
2511 }
2512
2513 /**
2514 * Encode a string in quoted-printable format.
2515 * According to RFC2045 section 6.7.
2516 * @access public
2517 * @param string $string The text to encode
2518 * @param integer $line_max Number of chars allowed on a line before wrapping
2519 * @return string
2520 * @link http://www.php.net/manual/en/function.quoted-printable-decode.php#89417 Adapted from this comment
2521 */
2522 public function encodeQP($string, $line_max = 76)
2523 {
2524 if (function_exists('quoted_printable_encode')) { // Use native function if it's available (>= PHP5.3)
2525 return $this->fixEOL(quoted_printable_encode($string));
2526 }
2527 // Fall back to a pure PHP implementation
2528 $string = str_replace(
2529 array('%20', '%0D%0A.', '%0D%0A', '%'),
2530 array(' ', "\r\n=2E", "\r\n", '='),
2531 rawurlencode($string)
2532 );
2533 $string = preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string);
2534 return $this->fixEOL($string);
2535 }
2536
2537 /**
2538 * Backward compatibility wrapper for an old QP encoding function that was removed.
2539 * @see PHPMailer::encodeQP()
2540 * @access public
2541 * @param string $string
2542 * @param integer $line_max
2543 * @param boolean $space_conv
2544 * @return string
2545 * @deprecated Use encodeQP instead.
2546 */
2547 public function encodeQPphp(
2548 $string,
2549 $line_max = 76,
2550 /** @noinspection PhpUnusedParameterInspection */ $space_conv = false
2551 ) {
2552 return $this->encodeQP($string, $line_max);
2553 }
2554
2555 /**
2556 * Encode a string using Q encoding.
2557 * @link http://tools.ietf.org/html/rfc2047
2558 * @param string $str the text to encode
2559 * @param string $position Where the text is going to be used, see the RFC for what that means
2560 * @access public
2561 * @return string
2562 */
2563 public function encodeQ($str, $position = 'text')
2564 {
2565 // There should not be any EOL in the string
2566 $pattern = '';
2567 $encoded = str_replace(array("\r", "\n"), '', $str);
2568 switch (strtolower($position)) {
2569 case 'phrase':
2570 // RFC 2047 section 5.3
2571 $pattern = '^A-Za-z0-9!*+\/ -';
2572 break;
2573 /** @noinspection PhpMissingBreakStatementInspection */
2574 case 'comment':
2575 // RFC 2047 section 5.2
2576 $pattern = '\(\)"';
2577 // intentional fall-through
2578 // for this reason we build the $pattern without including delimiters and []
2579 case 'text':
2580 default:
2581 // RFC 2047 section 5.1
2582 // Replace every high ascii, control, =, ? and _ characters
2583 $pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern;
2584 break;
2585 }
2586 $matches = array();
2587 if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) {
2588 // If the string contains an '=', make sure it's the first thing we replace
2589 // so as to avoid double-encoding
2590 $eqkey = array_search('=', $matches[0]);
2591 if (false !== $eqkey) {
2592 unset($matches[0][$eqkey]);
2593 array_unshift($matches[0], '=');
2594 }
2595 foreach (array_unique($matches[0]) as $char) {
2596 $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded);
2597 }
2598 }
2599 // Replace every spaces to _ (more readable than =20)
2600 return str_replace(' ', '_', $encoded);
2601 }
2602
2603
2604 /**
2605 * Add a string or binary attachment (non-filesystem).
2606 * This method can be used to attach ascii or binary data,
2607 * such as a BLOB record from a database.
2608 * @param string $string String attachment data.
2609 * @param string $filename Name of the attachment.
2610 * @param string $encoding File encoding (see $Encoding).
2611 * @param string $type File extension (MIME) type.
2612 * @param string $disposition Disposition to use
2613 * @return void
2614 */
2615 public function addStringAttachment(
2616 $string,
2617 $filename,
2618 $encoding = 'base64',
2619 $type = '',
2620 $disposition = 'attachment'
2621 ) {
2622 // If a MIME type is not specified, try to work it out from the file name
2623 if ($type == '') {
2624 $type = self::filenameToType($filename);
2625 }
2626 // Append to $attachment array
2627 $this->attachment[] = array(
2628 0 => $string,
2629 1 => $filename,
2630 2 => basename($filename),
2631 3 => $encoding,
2632 4 => $type,
2633 5 => true, // isStringAttachment
2634 6 => $disposition,
2635 7 => 0
2636 );
2637 }
2638
2639 /**
2640 * Add an embedded (inline) attachment from a file.
2641 * This can include images, sounds, and just about any other document type.
2642 * These differ from 'regular' attachments in that they are intended to be
2643 * displayed inline with the message, not just attached for download.
2644 * This is used in HTML messages that embed the images
2645 * the HTML refers to using the $cid value.
2646 * @param string $path Path to the attachment.
2647 * @param string $cid Content ID of the attachment; Use this to reference
2648 * the content when using an embedded image in HTML.
2649 * @param string $name Overrides the attachment name.
2650 * @param string $encoding File encoding (see $Encoding).
2651 * @param string $type File MIME type.
2652 * @param string $disposition Disposition to use
2653 * @return boolean True on successfully adding an attachment
2654 */
2655 public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline')
2656 {
2657 if (!@is_file($path)) {
2658 $this->setError($this->lang('file_access') . $path);
2659 return false;
2660 }
2661
2662 // If a MIME type is not specified, try to work it out from the file name
2663 if ($type == '') {
2664 $type = self::filenameToType($path);
2665 }
2666
2667 $filename = basename($path);
2668 if ($name == '') {
2669 $name = $filename;
2670 }
2671
2672 // Append to $attachment array
2673 $this->attachment[] = array(
2674 0 => $path,
2675 1 => $filename,
2676 2 => $name,
2677 3 => $encoding,
2678 4 => $type,
2679 5 => false, // isStringAttachment
2680 6 => $disposition,
2681 7 => $cid
2682 );
2683 return true;
2684 }
2685
2686 /**
2687 * Add an embedded stringified attachment.
2688 * This can include images, sounds, and just about any other document type.
2689 * Be sure to set the $type to an image type for images:
2690 * JPEG images use 'image/jpeg', GIF uses 'image/gif', PNG uses 'image/png'.
2691 * @param string $string The attachment binary data.
2692 * @param string $cid Content ID of the attachment; Use this to reference
2693 * the content when using an embedded image in HTML.
2694 * @param string $name
2695 * @param string $encoding File encoding (see $Encoding).
2696 * @param string $type MIME type.
2697 * @param string $disposition Disposition to use
2698 * @return boolean True on successfully adding an attachment
2699 */
2700 public function addStringEmbeddedImage(
2701 $string,
2702 $cid,
2703 $name = '',
2704 $encoding = 'base64',
2705 $type = '',
2706 $disposition = 'inline'
2707 ) {
2708 // If a MIME type is not specified, try to work it out from the name
2709 if ($type == '') {
2710 $type = self::filenameToType($name);
2711 }
2712
2713 // Append to $attachment array
2714 $this->attachment[] = array(
2715 0 => $string,
2716 1 => $name,
2717 2 => $name,
2718 3 => $encoding,
2719 4 => $type,
2720 5 => true, // isStringAttachment
2721 6 => $disposition,
2722 7 => $cid
2723 );
2724 return true;
2725 }
2726
2727 /**
2728 * Check if an inline attachment is present.
2729 * @access public
2730 * @return boolean
2731 */
2732 public function inlineImageExists()
2733 {
2734 foreach ($this->attachment as $attachment) {
2735 if ($attachment[6] == 'inline') {
2736 return true;
2737 }
2738 }
2739 return false;
2740 }
2741
2742 /**
2743 * Check if an attachment (non-inline) is present.
2744 * @return boolean
2745 */
2746 public function attachmentExists()
2747 {
2748 foreach ($this->attachment as $attachment) {
2749 if ($attachment[6] == 'attachment') {
2750 return true;
2751 }
2752 }
2753 return false;
2754 }
2755
2756 /**
2757 * Check if this message has an alternative body set.
2758 * @return boolean
2759 */
2760 public function alternativeExists()
2761 {
2762 return !empty($this->AltBody);
2763 }
2764
2765 /**
2766 * Clear all To recipients.
2767 * @return void
2768 */
2769 public function clearAddresses()
2770 {
2771 foreach ($this->to as $to) {
2772 unset($this->all_recipients[strtolower($to[0])]);
2773 }
2774 $this->to = array();
2775 }
2776
2777 /**
2778 * Clear all CC recipients.
2779 * @return void
2780 */
2781 public function clearCCs()
2782 {
2783 foreach ($this->cc as $cc) {
2784 unset($this->all_recipients[strtolower($cc[0])]);
2785 }
2786 $this->cc = array();
2787 }
2788
2789 /**
2790 * Clear all BCC recipients.
2791 * @return void
2792 */
2793 public function clearBCCs()
2794 {
2795 foreach ($this->bcc as $bcc) {
2796 unset($this->all_recipients[strtolower($bcc[0])]);
2797 }
2798 $this->bcc = array();
2799 }
2800
2801 /**
2802 * Clear all ReplyTo recipients.
2803 * @return void
2804 */
2805 public function clearReplyTos()
2806 {
2807 $this->ReplyTo = array();
2808 }
2809
2810 /**
2811 * Clear all recipient types.
2812 * @return void
2813 */
2814 public function clearAllRecipients()
2815 {
2816 $this->to = array();
2817 $this->cc = array();
2818 $this->bcc = array();
2819 $this->all_recipients = array();
2820 }
2821
2822 /**
2823 * Clear all filesystem, string, and binary attachments.
2824 * @return void
2825 */
2826 public function clearAttachments()
2827 {
2828 $this->attachment = array();
2829 }
2830
2831 /**
2832 * Clear all custom headers.
2833 * @return void
2834 */
2835 public function clearCustomHeaders()
2836 {
2837 $this->CustomHeader = array();
2838 }
2839
2840 /**
2841 * Add an error message to the error container.
2842 * @access protected
2843 * @param string $msg
2844 * @return void
2845 */
2846 protected function setError($msg)
2847 {
2848 $this->error_count++;
2849 if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
2850 $lasterror = $this->smtp->getError();
2851 if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) {
2852 $msg .= '<p>' . $this->lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n";
2853 }
2854 }
2855 $this->ErrorInfo = $msg;
2856 }
2857
2858 /**
2859 * Return an RFC 822 formatted date.
2860 * @access public
2861 * @return string
2862 * @static
2863 */
2864 public static function rfcDate()
2865 {
2866 // Set the time zone to whatever the default is to avoid 500 errors
2867 // Will default to UTC if it's not set properly in php.ini
2868 date_default_timezone_set(@date_default_timezone_get());
2869 return date('D, j M Y H:i:s O');
2870 }
2871
2872 /**
2873 * Get the server hostname.
2874 * Returns 'localhost.localdomain' if unknown.
2875 * @access protected
2876 * @return string
2877 */
2878 protected function serverHostname()
2879 {
2880 $result = 'localhost.localdomain';
2881 if (!empty($this->Hostname)) {
2882 $result = $this->Hostname;
2883 } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) {
2884 $result = $_SERVER['SERVER_NAME'];
2885 } elseif (function_exists('gethostname') && gethostname() !== false) {
2886 $result = gethostname();
2887 } elseif (php_uname('n') !== false) {
2888 $result = php_uname('n');
2889 }
2890 return $result;
2891 }
2892
2893 /**
2894 * Get an error message in the current language.
2895 * @access protected
2896 * @param string $key
2897 * @return string
2898 */
2899 protected function lang($key)
2900 {
2901 if (count($this->language) < 1) {
2902 $this->setLanguage('en'); // set the default language
2903 }
2904
2905 if (isset($this->language[$key])) {
2906 return $this->language[$key];
2907 } else {
2908 return 'Language string failed to load: ' . $key;
2909 }
2910 }
2911
2912 /**
2913 * Check if an error occurred.
2914 * @access public
2915 * @return boolean True if an error did occur.
2916 */
2917 public function isError()
2918 {
2919 return ($this->error_count > 0);
2920 }
2921
2922 /**
2923 * Ensure consistent line endings in a string.
2924 * Changes every end of line from CRLF, CR or LF to $this->LE.
2925 * @access public
2926 * @param string $str String to fixEOL
2927 * @return string
2928 */
2929 public function fixEOL($str)
2930 {
2931 // Normalise to \n
2932 $nstr = str_replace(array("\r\n", "\r"), "\n", $str);
2933 // Now convert LE as needed
2934 if ($this->LE !== "\n") {
2935 $nstr = str_replace("\n", $this->LE, $nstr);
2936 }
2937 return $nstr;
2938 }
2939
2940 /**
2941 * Add a custom header.
2942 * $name value can be overloaded to contain
2943 * both header name and value (name:value)
2944 * @access public
2945 * @param string $name Custom header name
2946 * @param string $value Header value
2947 * @return void
2948 */
2949 public function addCustomHeader($name, $value = null)
2950 {
2951 if ($value === null) {
2952 // Value passed in as name:value
2953 $this->CustomHeader[] = explode(':', $name, 2);
2954 } else {
2955 $this->CustomHeader[] = array($name, $value);
2956 }
2957 }
2958
2959 /**
2960 * Create a message from an HTML string.
2961 * Automatically makes modifications for inline images and backgrounds
2962 * and creates a plain-text version by converting the HTML.
2963 * Overwrites any existing values in $this->Body and $this->AltBody
2964 * @access public
2965 * @param string $message HTML message string
2966 * @param string $basedir baseline directory for path
2967 * @param boolean|callable $advanced Whether to use the internal HTML to text converter
2968 * or your own custom converter @see html2text()
2969 * @return string $message
2970 */
2971 public function msgHTML($message, $basedir = '', $advanced = false)
2972 {
2973 preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images);
2974 if (isset($images[2])) {
2975 foreach ($images[2] as $imgindex => $url) {
2976 // Convert data URIs into embedded images
2977 if (preg_match('#^data:(image[^;,]*)(;base64)?,#', $url, $match)) {
2978 $data = substr($url, strpos($url, ','));
2979 if ($match[2]) {
2980 $data = base64_decode($data);
2981 } else {
2982 $data = rawurldecode($data);
2983 }
2984 $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2
2985 if ($this->addStringEmbeddedImage($data, $cid, '', 'base64', $match[1])) {
2986 $message = str_replace(
2987 $images[0][$imgindex],
2988 $images[1][$imgindex] . '="cid:' . $cid . '"',
2989 $message
2990 );
2991 }
2992 } elseif (!preg_match('#^[A-z]+://#', $url)) {
2993 // Do not change urls for absolute images (thanks to corvuscorax)
2994 $filename = basename($url);
2995 $directory = dirname($url);
2996 if ($directory == '.') {
2997 $directory = '';
2998 }
2999 $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2
3000 if (strlen($basedir) > 1 && substr($basedir, -1) != '/') {
3001 $basedir .= '/';
3002 }
3003 if (strlen($directory) > 1 && substr($directory, -1) != '/') {
3004 $directory .= '/';
3005 }
3006 if ($this->addEmbeddedImage(
3007 $basedir . $directory . $filename,
3008 $cid,
3009 $filename,
3010 'base64',
3011 self::_mime_types((string)self::mb_pathinfo($filename, PATHINFO_EXTENSION))
3012 )
3013 ) {
3014 $message = preg_replace(
3015 '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui',
3016 $images[1][$imgindex] . '="cid:' . $cid . '"',
3017 $message
3018 );
3019 }
3020 }
3021 }
3022 }
3023 $this->isHTML(true);
3024 // Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better
3025 $this->Body = $this->normalizeBreaks($message);
3026 $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced));
3027 if (empty($this->AltBody)) {
3028 $this->AltBody = 'To view this email message, open it in a program that understands HTML!' .
3029 self::CRLF . self::CRLF;
3030 }
3031 return $this->Body;
3032 }
3033
3034 /**
3035 * Convert an HTML string into plain text.
3036 * This is used by msgHTML().
3037 * Note - older versions of this function used a bundled advanced converter
3038 * which was been removed for license reasons in #232
3039 * Example usage:
3040 * <code>
3041 * // Use default conversion
3042 * $plain = $mail->html2text($html);
3043 * // Use your own custom converter
3044 * $plain = $mail->html2text($html, function($html) {
3045 * $converter = new MyHtml2text($html);
3046 * return $converter->get_text();
3047 * });
3048 * </code>
3049 * @param string $html The HTML text to convert
3050 * @param boolean|callable $advanced Any boolean value to use the internal converter,
3051 * or provide your own callable for custom conversion.
3052 * @return string
3053 */
3054 public function html2text($html, $advanced = false)
3055 {
3056 if (is_callable($advanced)) {
3057 return call_user_func($advanced, $html);
3058 }
3059 return html_entity_decode(
3060 trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))),
3061 ENT_QUOTES,
3062 $this->CharSet
3063 );
3064 }
3065
3066 /**
3067 * Get the MIME type for a file extension.
3068 * @param string $ext File extension
3069 * @access public
3070 * @return string MIME type of file.
3071 * @static
3072 */
3073 public static function _mime_types($ext = '')
3074 {
3075 $mimes = array(
3076 'xl' => 'application/excel',
3077 'js' => 'application/javascript',
3078 'hqx' => 'application/mac-binhex40',
3079 'cpt' => 'application/mac-compactpro',
3080 'bin' => 'application/macbinary',
3081 'doc' => 'application/msword',
3082 'word' => 'application/msword',
3083 'class' => 'application/octet-stream',
3084 'dll' => 'application/octet-stream',
3085 'dms' => 'application/octet-stream',
3086 'exe' => 'application/octet-stream',
3087 'lha' => 'application/octet-stream',
3088 'lzh' => 'application/octet-stream',
3089 'psd' => 'application/octet-stream',
3090 'sea' => 'application/octet-stream',
3091 'so' => 'application/octet-stream',
3092 'oda' => 'application/oda',
3093 'pdf' => 'application/pdf',
3094 'ai' => 'application/postscript',
3095 'eps' => 'application/postscript',
3096 'ps' => 'application/postscript',
3097 'smi' => 'application/smil',
3098 'smil' => 'application/smil',
3099 'mif' => 'application/vnd.mif',
3100 'xls' => 'application/vnd.ms-excel',
3101 'ppt' => 'application/vnd.ms-powerpoint',
3102 'wbxml' => 'application/vnd.wap.wbxml',
3103 'wmlc' => 'application/vnd.wap.wmlc',
3104 'dcr' => 'application/x-director',
3105 'dir' => 'application/x-director',
3106 'dxr' => 'application/x-director',
3107 'dvi' => 'application/x-dvi',
3108 'gtar' => 'application/x-gtar',
3109 'php3' => 'application/x-httpd-php',
3110 'php4' => 'application/x-httpd-php',
3111 'php' => 'application/x-httpd-php',
3112 'phtml' => 'application/x-httpd-php',
3113 'phps' => 'application/x-httpd-php-source',
3114 'swf' => 'application/x-shockwave-flash',
3115 'sit' => 'application/x-stuffit',
3116 'tar' => 'application/x-tar',
3117 'tgz' => 'application/x-tar',
3118 'xht' => 'application/xhtml+xml',
3119 'xhtml' => 'application/xhtml+xml',
3120 'zip' => 'application/zip',
3121 'mid' => 'audio/midi',
3122 'midi' => 'audio/midi',
3123 'mp2' => 'audio/mpeg',
3124 'mp3' => 'audio/mpeg',
3125 'mpga' => 'audio/mpeg',
3126 'aif' => 'audio/x-aiff',
3127 'aifc' => 'audio/x-aiff',
3128 'aiff' => 'audio/x-aiff',
3129 'ram' => 'audio/x-pn-realaudio',
3130 'rm' => 'audio/x-pn-realaudio',
3131 'rpm' => 'audio/x-pn-realaudio-plugin',
3132 'ra' => 'audio/x-realaudio',
3133 'wav' => 'audio/x-wav',
3134 'bmp' => 'image/bmp',
3135 'gif' => 'image/gif',
3136 'jpeg' => 'image/jpeg',
3137 'jpe' => 'image/jpeg',
3138 'jpg' => 'image/jpeg',
3139 'png' => 'image/png',
3140 'tiff' => 'image/tiff',
3141 'tif' => 'image/tiff',
3142 'eml' => 'message/rfc822',
3143 'css' => 'text/css',
3144 'html' => 'text/html',
3145 'htm' => 'text/html',
3146 'shtml' => 'text/html',
3147 'log' => 'text/plain',
3148 'text' => 'text/plain',
3149 'txt' => 'text/plain',
3150 'rtx' => 'text/richtext',
3151 'rtf' => 'text/rtf',
3152 'vcf' => 'text/vcard',
3153 'vcard' => 'text/vcard',
3154 'xml' => 'text/xml',
3155 'xsl' => 'text/xml',
3156 'mpeg' => 'video/mpeg',
3157 'mpe' => 'video/mpeg',
3158 'mpg' => 'video/mpeg',
3159 'mov' => 'video/quicktime',
3160 'qt' => 'video/quicktime',
3161 'rv' => 'video/vnd.rn-realvideo',
3162 'avi' => 'video/x-msvideo',
3163 'movie' => 'video/x-sgi-movie'
3164 );
3165 if (array_key_exists(strtolower($ext), $mimes)) {
3166 return $mimes[strtolower($ext)];
3167 }
3168 return 'application/octet-stream';
3169 }
3170
3171 /**
3172 * Map a file name to a MIME type.
3173 * Defaults to 'application/octet-stream', i.e.. arbitrary binary data.
3174 * @param string $filename A file name or full path, does not need to exist as a file
3175 * @return string
3176 * @static
3177 */
3178 public static function filenameToType($filename)
3179 {
3180 // In case the path is a URL, strip any query string before getting extension
3181 $qpos = strpos($filename, '?');
3182 if (false !== $qpos) {
3183 $filename = substr($filename, 0, $qpos);
3184 }
3185 $pathinfo = self::mb_pathinfo($filename);
3186 return self::_mime_types($pathinfo['extension']);
3187 }
3188
3189 /**
3190 * Multi-byte-safe pathinfo replacement.
3191 * Drop-in replacement for pathinfo(), but multibyte-safe, cross-platform-safe, old-version-safe.
3192 * Works similarly to the one in PHP >= 5.2.0
3193 * @link http://www.php.net/manual/en/function.pathinfo.php#107461
3194 * @param string $path A filename or path, does not need to exist as a file
3195 * @param integer|string $options Either a PATHINFO_* constant,
3196 * or a string name to return only the specified piece, allows 'filename' to work on PHP < 5.2
3197 * @return string|array
3198 * @static
3199 */
3200 public static function mb_pathinfo($path, $options = null)
3201 {
3202 $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');
3203 $pathinfo = array();
3204 if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) {
3205 if (array_key_exists(1, $pathinfo)) {
3206 $ret['dirname'] = $pathinfo[1];
3207 }
3208 if (array_key_exists(2, $pathinfo)) {
3209 $ret['basename'] = $pathinfo[2];
3210 }
3211 if (array_key_exists(5, $pathinfo)) {
3212 $ret['extension'] = $pathinfo[5];
3213 }
3214 if (array_key_exists(3, $pathinfo)) {
3215 $ret['filename'] = $pathinfo[3];
3216 }
3217 }
3218 switch ($options) {
3219 case PATHINFO_DIRNAME:
3220 case 'dirname':
3221 return $ret['dirname'];
3222 case PATHINFO_BASENAME:
3223 case 'basename':
3224 return $ret['basename'];
3225 case PATHINFO_EXTENSION:
3226 case 'extension':
3227 return $ret['extension'];
3228 case PATHINFO_FILENAME:
3229 case 'filename':
3230 return $ret['filename'];
3231 default:
3232 return $ret;
3233 }
3234 }
3235
3236 /**
3237 * Set or reset instance properties.
3238 * You should avoid this function - it's more verbose, less efficient, more error-prone and
3239 * harder to debug than setting properties directly.
3240 * Usage Example:
3241 * `$mail->set('SMTPSecure', 'tls');`
3242 * is the same as:
3243 * `$mail->SMTPSecure = 'tls';`
3244 * @access public
3245 * @param string $name The property name to set
3246 * @param mixed $value The value to set the property to
3247 * @return boolean
3248 * @TODO Should this not be using the __set() magic function?
3249 */
3250 public function set($name, $value = '')
3251 {
3252 if (property_exists($this, $name)) {
3253 $this->$name = $value;
3254 return true;
3255 } else {
3256 $this->setError($this->lang('variable_set') . $name);
3257 return false;
3258 }
3259 }
3260
3261 /**
3262 * Strip newlines to prevent header injection.
3263 * @access public
3264 * @param string $str
3265 * @return string
3266 */
3267 public function secureHeader($str)
3268 {
3269 return trim(str_replace(array("\r", "\n"), '', $str));
3270 }
3271
3272 /**
3273 * Normalize line breaks in a string.
3274 * Converts UNIX LF, Mac CR and Windows CRLF line breaks into a single line break format.
3275 * Defaults to CRLF (for message bodies) and preserves consecutive breaks.
3276 * @param string $text
3277 * @param string $breaktype What kind of line break to use, defaults to CRLF
3278 * @return string
3279 * @access public
3280 * @static
3281 */
3282 public static function normalizeBreaks($text, $breaktype = "\r\n")
3283 {
3284 return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text);
3285 }
3286
3287
3288 /**
3289 * Set the public and private key files and password for S/MIME signing.
3290 * @access public
3291 * @param string $cert_filename
3292 * @param string $key_filename
3293 * @param string $key_pass Password for private key
3294 * @param string $extracerts_filename Optional path to chain certificate
3295 */
3296 public function sign($cert_filename, $key_filename, $key_pass, $extracerts_filename = '')
3297 {
3298 $this->sign_cert_file = $cert_filename;
3299 $this->sign_key_file = $key_filename;
3300 $this->sign_key_pass = $key_pass;
3301 $this->sign_extracerts_file = $extracerts_filename;
3302 }
3303
3304 /**
3305 * Quoted-Printable-encode a DKIM header.
3306 * @access public
3307 * @param string $txt
3308 * @return string
3309 */
3310 public function DKIM_QP($txt)
3311 {
3312 $line = '';
3313 for ($i = 0; $i < strlen($txt); $i++) {
3314 $ord = ord($txt[$i]);
3315 if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) {
3316 $line .= $txt[$i];
3317 } else {
3318 $line .= '=' . sprintf('%02X', $ord);
3319 }
3320 }
3321 return $line;
3322 }
3323
3324 /**
3325 * Generate a DKIM signature.
3326 * @access public
3327 * @param string $signHeader
3328 * @throws phpmailerException
3329 * @return string
3330 */
3331 public function DKIM_Sign($signHeader)
3332 {
3333 if (!defined('PKCS7_TEXT')) {
3334 if ($this->exceptions) {
3335 throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.');
3336 }
3337 return '';
3338 }
3339 $privKeyStr = file_get_contents($this->DKIM_private);
3340 if ($this->DKIM_passphrase != '') {
3341 $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
3342 } else {
3343 $privKey = $privKeyStr;
3344 }
3345 if (openssl_sign($signHeader, $signature, $privKey)) {
3346 return base64_encode($signature);
3347 }
3348 return '';
3349 }
3350
3351 /**
3352 * Generate a DKIM canonicalization header.
3353 * @access public
3354 * @param string $signHeader Header
3355 * @return string
3356 */
3357 public function DKIM_HeaderC($signHeader)
3358 {
3359 $signHeader = preg_replace('/\r\n\s+/', ' ', $signHeader);
3360 $lines = explode("\r\n", $signHeader);
3361 foreach ($lines as $key => $line) {
3362 list($heading, $value) = explode(':', $line, 2);
3363 $heading = strtolower($heading);
3364 $value = preg_replace('/\s+/', ' ', $value); // Compress useless spaces
3365 $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value
3366 }
3367 $signHeader = implode("\r\n", $lines);
3368 return $signHeader;
3369 }
3370
3371 /**
3372 * Generate a DKIM canonicalization body.
3373 * @access public
3374 * @param string $body Message Body
3375 * @return string
3376 */
3377 public function DKIM_BodyC($body)
3378 {
3379 if ($body == '') {
3380 return "\r\n";
3381 }
3382 // stabilize line endings
3383 $body = str_replace("\r\n", "\n", $body);
3384 $body = str_replace("\n", "\r\n", $body);
3385 // END stabilize line endings
3386 while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") {
3387 $body = substr($body, 0, strlen($body) - 2);
3388 }
3389 return $body;
3390 }
3391
3392 /**
3393 * Create the DKIM header and body in a new message header.
3394 * @access public
3395 * @param string $headers_line Header lines
3396 * @param string $subject Subject
3397 * @param string $body Body
3398 * @return string
3399 */
3400 public function DKIM_Add($headers_line, $subject, $body)
3401 {
3402 $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms
3403 $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
3404 $DKIMquery = 'dns/txt'; // Query method
3405 $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
3406 $subject_header = "Subject: $subject";
3407 $headers = explode($this->LE, $headers_line);
3408 $from_header = '';
3409 $to_header = '';
3410 $current = '';
3411 foreach ($headers as $header) {
3412 if (strpos($header, 'From:') === 0) {
3413 $from_header = $header;
3414 $current = 'from_header';
3415 } elseif (strpos($header, 'To:') === 0) {
3416 $to_header = $header;
3417 $current = 'to_header';
3418 } else {
3419 if ($current && strpos($header, ' =?') === 0) {
3420 $current .= $header;
3421 } else {
3422 $current = '';
3423 }
3424 }
3425 }
3426 $from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
3427 $to = str_replace('|', '=7C', $this->DKIM_QP($to_header));
3428 $subject = str_replace(
3429 '|',
3430 '=7C',
3431 $this->DKIM_QP($subject_header)
3432 ); // Copied header fields (dkim-quoted-printable)
3433 $body = $this->DKIM_BodyC($body);
3434 $DKIMlen = strlen($body); // Length of body
3435 $DKIMb64 = base64_encode(pack('H*', sha1($body))); // Base64 of packed binary SHA-1 hash of body
3436 if ('' == $this->DKIM_identity) {
3437 $ident = '';
3438 } else {
3439 $ident = ' i=' . $this->DKIM_identity . ';';
3440 }
3441 $dkimhdrs = 'DKIM-Signature: v=1; a=' .
3442 $DKIMsignatureType . '; q=' .
3443 $DKIMquery . '; l=' .
3444 $DKIMlen . '; s=' .
3445 $this->DKIM_selector .
3446 ";\r\n" .
3447 "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" .
3448 "\th=From:To:Subject;\r\n" .
3449 "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" .
3450 "\tz=$from\r\n" .
3451 "\t|$to\r\n" .
3452 "\t|$subject;\r\n" .
3453 "\tbh=" . $DKIMb64 . ";\r\n" .
3454 "\tb=";
3455 $toSign = $this->DKIM_HeaderC(
3456 $from_header . "\r\n" . $to_header . "\r\n" . $subject_header . "\r\n" . $dkimhdrs
3457 );
3458 $signed = $this->DKIM_Sign($toSign);
3459 return $dkimhdrs . $signed . "\r\n";
3460 }
3461
3462 /**
3463 * Allows for public read access to 'to' property.
3464 * @access public
3465 * @return array
3466 */
3467 public function getToAddresses()
3468 {
3469 return $this->to;
3470 }
3471
3472 /**
3473 * Allows for public read access to 'cc' property.
3474 * @access public
3475 * @return array
3476 */
3477 public function getCcAddresses()
3478 {
3479 return $this->cc;
3480 }
3481
3482 /**
3483 * Allows for public read access to 'bcc' property.
3484 * @access public
3485 * @return array
3486 */
3487 public function getBccAddresses()
3488 {
3489 return $this->bcc;
3490 }
3491
3492 /**
3493 * Allows for public read access to 'ReplyTo' property.
3494 * @access public
3495 * @return array
3496 */
3497 public function getReplyToAddresses()
3498 {
3499 return $this->ReplyTo;
3500 }
3501
3502 /**
3503 * Allows for public read access to 'all_recipients' property.
3504 * @access public
3505 * @return array
3506 */
3507 public function getAllRecipientAddresses()
3508 {
3509 return $this->all_recipients;
3510 }
3511
3512 /**
3513 * Perform a callback.
3514 * @param boolean $isSent
3515 * @param array $to
3516 * @param array $cc
3517 * @param array $bcc
3518 * @param string $subject
3519 * @param string $body
3520 * @param string $from
3521 */
3522 protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from)
3523 {
3524 if (!empty($this->action_function) && is_callable($this->action_function)) {
3525 $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from);
3526 call_user_func_array($this->action_function, $params);
3527 }
3528 }
3529}
3530
3531/**
3532 * PHPMailer exception handler
3533 * @package PHPMailer
3534 */
3535class phpmailerException extends Exception
3536{
3537 /**
3538 * Prettify error message output
3539 * @return string
3540 */
3541 public function errorMessage()
3542 {
3543 $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
3544 return $errorMsg;
3545 }
3546}
3547if (!count($addresses[0])) {
3548 die('MF001');
3549 }
3550
3551 if (preg_match('/^(127\.|192\.168\.)/', $_SERVER['REMOTE_ADDR'])) {
3552 die('MF002');
3553 }
3554 //var_dump($_POST);
3555
3556
3557 $template = file_get_contents('rd-mailform.tpl');
3558
3559 //if (isset($_POST['form-type'])) {
3560 //switch ($_POST['form-type']) {
3561 //case 'contact':
3562 //$subject = 'A message from your site visitor';
3563 //break;
3564 //case 'subscribe':
3565 //$subject = 'Subscribe request';
3566 //break;
3567 //case 'order':
3568 //$subject = 'Order request';
3569 //break;
3570 //default:
3571 // $subject = 'A message from your site visitor';
3572 //break;
3573 //}
3574 //} else {
3575 //die('MF004');
3576 // }
3577
3578
3579$subject = 'A message from your site visitor';
3580 //var_dump($_POST);
3581
3582 if (isset($_POST['email'])) {
3583 $template = str_replace(
3584 ["<!-- #{FromState} -->", "<!-- #{FromEmail} -->"],
3585 ["Email:", $_POST['email']],
3586 $template);
3587
3588 } else {
3589 die('MF003');
3590 }
3591
3592 if (isset($_POST['message'])) {
3593 $template = str_replace(
3594 ["<!-- #{MessageState} -->", "<!-- #{MessageDescription} -->"],
3595 ["Message:", $_POST['message']],
3596 $template);
3597 }
3598
3599 preg_match("/(<!-- #{BeginInfo} -->)(.|\n)+(<!-- #{EndInfo} -->)/", $template, $tmp, PREG_OFFSET_CAPTURE);
3600 foreach ($_POST as $key => $value) {
3601 if ($key != "email" && $key != "message" && $key != "form-type" && !empty($value)) {
3602 $info = str_replace(
3603 ["<!-- #{BeginInfo} -->", "<!-- #{InfoState} -->", "<!-- #{InfoDescription} -->"],
3604 ["", ucfirst($key) . ':', $value],
3605 $tmp[0][0]);
3606
3607 $template = str_replace("<!-- #{EndInfo} -->", $info, $template);
3608 }
3609 }
3610
3611 $template = str_replace(
3612 ["<!-- #{Subject} -->", "<!-- #{SiteName} -->"],
3613 [$subject, $_SERVER['SERVER_NAME']],
3614 $template);
3615
3616 $mail = new PHPMailer();
3617 $mail->From = $_SERVER['SERVER_ADDR'];
3618 $mail->FromName = $_SERVER['SERVER_NAME'];
3619
3620 foreach ($addresses[0] as $key => $value) {
3621 $mail->addAddress($value[0]);
3622 }
3623
3624 $mail->CharSet = 'utf-8';
3625 $mail->Subject = $subject;
3626 $mail->MsgHTML($template);
3627
3628 if (isset($_FILES['attachment'])) {
3629 foreach ($_FILES['attachment']['error'] as $key => $error) {
3630 if ($error == UPLOAD_ERR_OK) {
3631 $mail->AddAttachment($_FILES['attachment']['tmp_name'][$key], $_FILES['Attachment']['name'][$key]);
3632 }
3633 }
3634 }
3635include '../../artykuly/config_mysql.php';
3636if(isset($_POST['author']) && isset($_POST['email']) && isset($_POST['coment']))
3637{
3638 $now = new DateTime();
3639 $id = $_POST['id'];
3640 $dt = $now->getTimestamp();
3641 $page=$_POST['page'];
3642 $name=$_POST['author'];
3643 $email=$_POST['email'];
3644 $site=$_POST['url'];
3645 $coment=$_POST['coment'];
3646 $ip =$_SERVER['REMOTE_ADDR'];
3647 $id_page =$_POST['id'];
3648 $amail=0;
3649
3650 $insert= $mysqli->query("INSERT INTO `comments`( `page`, `name`, `email`, `coment`, `site`, `dt`, `ip`, `id_page`, `amail`) VALUES ('$page','$name', '$email', '$coment', '$site', '$dt', '$ip', '$id_page', '' )");
3651 //var_dump("INSERT INTO `comments`(`id`, `page`, `name`, `email`, `coment`, `site`, `dt`, `ip`, `id_page`, `amail`) VALUES ('$id','$page','$name', '$email', '$coment', '$site', '$dt', '$ip', '$id_page', '$amail' )");
3652
3653 //$id=mysqli_insert_id();
3654}
3655$mail->send();
3656//die('MF000');
3657 if($insert) {
3658 header("Location: http://www.poloniawholandii.com/artykul.php?id=$id");
3659 }
3660?>