PageRenderTime 75ms CodeModel.GetById 6ms app.highlight 52ms RepoModel.GetById 1ms app.codeStats 2ms

/wp-includes/class-phpmailer.php

http://github.com/markjaquith/WordPress
PHP | 4062 lines | 2386 code | 252 blank | 1424 comment | 387 complexity | ba294aa3723e495c39f8f2f440d7019d MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1<?php
   2/**
   3 * PHPMailer - PHP email creation and transport class.
   4 * PHP Version 5
   5 * @package PHPMailer
   6 * @link https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
   7 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
   8 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
   9 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
  10 * @author Brent R. Matzelle (original founder)
  11 * @copyright 2012 - 2014 Marcus Bointon
  12 * @copyright 2010 - 2012 Jim Jagielski
  13 * @copyright 2004 - 2009 Andy Prevost
  14 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
  15 * @note This program is distributed in the hope that it will be useful - WITHOUT
  16 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  17 * FITNESS FOR A PARTICULAR PURPOSE.
  18 */
  19
  20/**
  21 * PHPMailer - PHP email creation and transport class.
  22 * @package PHPMailer
  23 * @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
  24 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
  25 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
  26 * @author Brent R. Matzelle (original founder)
  27 */
  28class PHPMailer
  29{
  30    /**
  31     * The PHPMailer Version number.
  32     * @var string
  33     */
  34    public $Version = '5.2.27';
  35
  36    /**
  37     * Email priority.
  38     * Options: null (default), 1 = High, 3 = Normal, 5 = low.
  39     * When null, the header is not set at all.
  40     * @var integer
  41     */
  42    public $Priority = null;
  43
  44    /**
  45     * The character set of the message.
  46     * @var string
  47     */
  48    public $CharSet = 'iso-8859-1';
  49
  50    /**
  51     * The MIME Content-type of the message.
  52     * @var string
  53     */
  54    public $ContentType = 'text/plain';
  55
  56    /**
  57     * The message encoding.
  58     * Options: "8bit", "7bit", "binary", "base64", and "quoted-printable".
  59     * @var string
  60     */
  61    public $Encoding = '8bit';
  62
  63    /**
  64     * Holds the most recent mailer error message.
  65     * @var string
  66     */
  67    public $ErrorInfo = '';
  68
  69    /**
  70     * The From email address for the message.
  71     * @var string
  72     */
  73    public $From = 'root@localhost';
  74
  75    /**
  76     * The From name of the message.
  77     * @var string
  78     */
  79    public $FromName = 'Root User';
  80
  81    /**
  82     * The Sender email (Return-Path) of the message.
  83     * If not empty, will be sent via -f to sendmail or as 'MAIL FROM' in smtp mode.
  84     * @var string
  85     */
  86    public $Sender = '';
  87
  88    /**
  89     * The Return-Path of the message.
  90     * If empty, it will be set to either From or Sender.
  91     * @var string
  92     * @deprecated Email senders should never set a return-path header;
  93     * it's the receiver's job (RFC5321 section 4.4), so this no longer does anything.
  94     * @link https://tools.ietf.org/html/rfc5321#section-4.4 RFC5321 reference
  95     */
  96    public $ReturnPath = '';
  97
  98    /**
  99     * The Subject of the message.
 100     * @var string
 101     */
 102    public $Subject = '';
 103
 104    /**
 105     * An HTML or plain text message body.
 106     * If HTML then call isHTML(true).
 107     * @var string
 108     */
 109    public $Body = '';
 110
 111    /**
 112     * The plain-text message body.
 113     * This body can be read by mail clients that do not have HTML email
 114     * capability such as mutt & Eudora.
 115     * Clients that can read HTML will view the normal Body.
 116     * @var string
 117     */
 118    public $AltBody = '';
 119
 120    /**
 121     * An iCal message part body.
 122     * Only supported in simple alt or alt_inline message types
 123     * To generate iCal events, use the bundled extras/EasyPeasyICS.php class or iCalcreator
 124     * @link http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/
 125     * @link http://kigkonsult.se/iCalcreator/
 126     * @var string
 127     */
 128    public $Ical = '';
 129
 130    /**
 131     * The complete compiled MIME message body.
 132     * @access protected
 133     * @var string
 134     */
 135    protected $MIMEBody = '';
 136
 137    /**
 138     * The complete compiled MIME message headers.
 139     * @var string
 140     * @access protected
 141     */
 142    protected $MIMEHeader = '';
 143
 144    /**
 145     * Extra headers that createHeader() doesn't fold in.
 146     * @var string
 147     * @access protected
 148     */
 149    protected $mailHeader = '';
 150
 151    /**
 152     * Word-wrap the message body to this number of chars.
 153     * Set to 0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance.
 154     * @var integer
 155     */
 156    public $WordWrap = 0;
 157
 158    /**
 159     * Which method to use to send mail.
 160     * Options: "mail", "sendmail", or "smtp".
 161     * @var string
 162     */
 163    public $Mailer = 'mail';
 164
 165    /**
 166     * The path to the sendmail program.
 167     * @var string
 168     */
 169    public $Sendmail = '/usr/sbin/sendmail';
 170
 171    /**
 172     * Whether mail() uses a fully sendmail-compatible MTA.
 173     * One which supports sendmail's "-oi -f" options.
 174     * @var boolean
 175     */
 176    public $UseSendmailOptions = true;
 177
 178    /**
 179     * Path to PHPMailer plugins.
 180     * Useful if the SMTP class is not in the PHP include path.
 181     * @var string
 182     * @deprecated Should not be needed now there is an autoloader.
 183     */
 184    public $PluginDir = '';
 185
 186    /**
 187     * The email address that a reading confirmation should be sent to, also known as read receipt.
 188     * @var string
 189     */
 190    public $ConfirmReadingTo = '';
 191
 192    /**
 193     * The hostname to use in the Message-ID header and as default HELO string.
 194     * If empty, PHPMailer attempts to find one with, in order,
 195     * $_SERVER['SERVER_NAME'], gethostname(), php_uname('n'), or the value
 196     * 'localhost.localdomain'.
 197     * @var string
 198     */
 199    public $Hostname = '';
 200
 201    /**
 202     * An ID to be used in the Message-ID header.
 203     * If empty, a unique id will be generated.
 204     * You can set your own, but it must be in the format "<id@domain>",
 205     * as defined in RFC5322 section 3.6.4 or it will be ignored.
 206     * @see https://tools.ietf.org/html/rfc5322#section-3.6.4
 207     * @var string
 208     */
 209    public $MessageID = '';
 210
 211    /**
 212     * The message Date to be used in the Date header.
 213     * If empty, the current date will be added.
 214     * @var string
 215     */
 216    public $MessageDate = '';
 217
 218    /**
 219     * SMTP hosts.
 220     * Either a single hostname or multiple semicolon-delimited hostnames.
 221     * You can also specify a different port
 222     * for each host by using this format: [hostname:port]
 223     * (e.g. "smtp1.example.com:25;smtp2.example.com").
 224     * You can also specify encryption type, for example:
 225     * (e.g. "tls://smtp1.example.com:587;ssl://smtp2.example.com:465").
 226     * Hosts will be tried in order.
 227     * @var string
 228     */
 229    public $Host = 'localhost';
 230
 231    /**
 232     * The default SMTP server port.
 233     * @var integer
 234     * @TODO Why is this needed when the SMTP class takes care of it?
 235     */
 236    public $Port = 25;
 237
 238    /**
 239     * The SMTP HELO of the message.
 240     * Default is $Hostname. If $Hostname is empty, PHPMailer attempts to find
 241     * one with the same method described above for $Hostname.
 242     * @var string
 243     * @see PHPMailer::$Hostname
 244     */
 245    public $Helo = '';
 246
 247    /**
 248     * What kind of encryption to use on the SMTP connection.
 249     * Options: '', 'ssl' or 'tls'
 250     * @var string
 251     */
 252    public $SMTPSecure = '';
 253
 254    /**
 255     * Whether to enable TLS encryption automatically if a server supports it,
 256     * even if `SMTPSecure` is not set to 'tls'.
 257     * Be aware that in PHP >= 5.6 this requires that the server's certificates are valid.
 258     * @var boolean
 259     */
 260    public $SMTPAutoTLS = true;
 261
 262    /**
 263     * Whether to use SMTP authentication.
 264     * Uses the Username and Password properties.
 265     * @var boolean
 266     * @see PHPMailer::$Username
 267     * @see PHPMailer::$Password
 268     */
 269    public $SMTPAuth = false;
 270
 271    /**
 272     * Options array passed to stream_context_create when connecting via SMTP.
 273     * @var array
 274     */
 275    public $SMTPOptions = array();
 276
 277    /**
 278     * SMTP username.
 279     * @var string
 280     */
 281    public $Username = '';
 282
 283    /**
 284     * SMTP password.
 285     * @var string
 286     */
 287    public $Password = '';
 288
 289    /**
 290     * SMTP auth type.
 291     * Options are CRAM-MD5, LOGIN, PLAIN, attempted in that order if not specified
 292     * @var string
 293     */
 294    public $AuthType = '';
 295
 296    /**
 297     * SMTP realm.
 298     * Used for NTLM auth
 299     * @var string
 300     */
 301    public $Realm = '';
 302
 303    /**
 304     * SMTP workstation.
 305     * Used for NTLM auth
 306     * @var string
 307     */
 308    public $Workstation = '';
 309
 310    /**
 311     * The SMTP server timeout in seconds.
 312     * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2
 313     * @var integer
 314     */
 315    public $Timeout = 300;
 316
 317    /**
 318     * SMTP class debug output mode.
 319     * Debug output level.
 320     * Options:
 321     * * `0` No output
 322     * * `1` Commands
 323     * * `2` Data and commands
 324     * * `3` As 2 plus connection status
 325     * * `4` Low-level data output
 326     * @var integer
 327     * @see SMTP::$do_debug
 328     */
 329    public $SMTPDebug = 0;
 330
 331    /**
 332     * How to handle debug output.
 333     * Options:
 334     * * `echo` Output plain-text as-is, appropriate for CLI
 335     * * `html` Output escaped, line breaks converted to `<br>`, appropriate for browser output
 336     * * `error_log` Output to error log as configured in php.ini
 337     *
 338     * Alternatively, you can provide a callable expecting two params: a message string and the debug level:
 339     * <code>
 340     * $mail->Debugoutput = function($str, $level) {echo "debug level $level; message: $str";};
 341     * </code>
 342     * @var string|callable
 343     * @see SMTP::$Debugoutput
 344     */
 345    public $Debugoutput = 'echo';
 346
 347    /**
 348     * Whether to keep SMTP connection open after each message.
 349     * If this is set to true then to close the connection
 350     * requires an explicit call to smtpClose().
 351     * @var boolean
 352     */
 353    public $SMTPKeepAlive = false;
 354
 355    /**
 356     * Whether to split multiple to addresses into multiple messages
 357     * or send them all in one message.
 358     * Only supported in `mail` and `sendmail` transports, not in SMTP.
 359     * @var boolean
 360     */
 361    public $SingleTo = false;
 362
 363    /**
 364     * Storage for addresses when SingleTo is enabled.
 365     * @var array
 366     * @TODO This should really not be public
 367     */
 368    public $SingleToArray = array();
 369
 370    /**
 371     * Whether to generate VERP addresses on send.
 372     * Only applicable when sending via SMTP.
 373     * @link https://en.wikipedia.org/wiki/Variable_envelope_return_path
 374     * @link http://www.postfix.org/VERP_README.html Postfix VERP info
 375     * @var boolean
 376     */
 377    public $do_verp = false;
 378
 379    /**
 380     * Whether to allow sending messages with an empty body.
 381     * @var boolean
 382     */
 383    public $AllowEmpty = false;
 384
 385    /**
 386     * The default line ending.
 387     * @note The default remains "\n". We force CRLF where we know
 388     *        it must be used via self::CRLF.
 389     * @var string
 390     */
 391    public $LE = "\n";
 392
 393    /**
 394     * DKIM selector.
 395     * @var string
 396     */
 397    public $DKIM_selector = '';
 398
 399    /**
 400     * DKIM Identity.
 401     * Usually the email address used as the source of the email.
 402     * @var string
 403     */
 404    public $DKIM_identity = '';
 405
 406    /**
 407     * DKIM passphrase.
 408     * Used if your key is encrypted.
 409     * @var string
 410     */
 411    public $DKIM_passphrase = '';
 412
 413    /**
 414     * DKIM signing domain name.
 415     * @example 'example.com'
 416     * @var string
 417     */
 418    public $DKIM_domain = '';
 419
 420    /**
 421     * DKIM private key file path.
 422     * @var string
 423     */
 424    public $DKIM_private = '';
 425
 426    /**
 427     * DKIM private key string.
 428     * If set, takes precedence over `$DKIM_private`.
 429     * @var string
 430     */
 431    public $DKIM_private_string = '';
 432
 433    /**
 434     * Callback Action function name.
 435     *
 436     * The function that handles the result of the send email action.
 437     * It is called out by send() for each email sent.
 438     *
 439     * Value can be any php callable: http://www.php.net/is_callable
 440     *
 441     * Parameters:
 442     *   boolean $result        result of the send action
 443     *   array   $to            email addresses of the recipients
 444     *   array   $cc            cc email addresses
 445     *   array   $bcc           bcc email addresses
 446     *   string  $subject       the subject
 447     *   string  $body          the email body
 448     *   string  $from          email address of sender
 449     * @var string
 450     */
 451    public $action_function = '';
 452
 453    /**
 454     * What to put in the X-Mailer header.
 455     * Options: An empty string for PHPMailer default, whitespace for none, or a string to use
 456     * @var string
 457     */
 458    public $XMailer = '';
 459
 460    /**
 461     * Which validator to use by default when validating email addresses.
 462     * May be a callable to inject your own validator, but there are several built-in validators.
 463     * @see PHPMailer::validateAddress()
 464     * @var string|callable
 465     * @static
 466     */
 467    public static $validator = 'auto';
 468
 469    /**
 470     * An instance of the SMTP sender class.
 471     * @var SMTP
 472     * @access protected
 473     */
 474    protected $smtp = null;
 475
 476    /**
 477     * The array of 'to' names and addresses.
 478     * @var array
 479     * @access protected
 480     */
 481    protected $to = array();
 482
 483    /**
 484     * The array of 'cc' names and addresses.
 485     * @var array
 486     * @access protected
 487     */
 488    protected $cc = array();
 489
 490    /**
 491     * The array of 'bcc' names and addresses.
 492     * @var array
 493     * @access protected
 494     */
 495    protected $bcc = array();
 496
 497    /**
 498     * The array of reply-to names and addresses.
 499     * @var array
 500     * @access protected
 501     */
 502    protected $ReplyTo = array();
 503
 504    /**
 505     * An array of all kinds of addresses.
 506     * Includes all of $to, $cc, $bcc
 507     * @var array
 508     * @access protected
 509     * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc
 510     */
 511    protected $all_recipients = array();
 512
 513    /**
 514     * An array of names and addresses queued for validation.
 515     * In send(), valid and non duplicate entries are moved to $all_recipients
 516     * and one of $to, $cc, or $bcc.
 517     * This array is used only for addresses with IDN.
 518     * @var array
 519     * @access protected
 520     * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc
 521     * @see PHPMailer::$all_recipients
 522     */
 523    protected $RecipientsQueue = array();
 524
 525    /**
 526     * An array of reply-to names and addresses queued for validation.
 527     * In send(), valid and non duplicate entries are moved to $ReplyTo.
 528     * This array is used only for addresses with IDN.
 529     * @var array
 530     * @access protected
 531     * @see PHPMailer::$ReplyTo
 532     */
 533    protected $ReplyToQueue = array();
 534
 535    /**
 536     * The array of attachments.
 537     * @var array
 538     * @access protected
 539     */
 540    protected $attachment = array();
 541
 542    /**
 543     * The array of custom headers.
 544     * @var array
 545     * @access protected
 546     */
 547    protected $CustomHeader = array();
 548
 549    /**
 550     * The most recent Message-ID (including angular brackets).
 551     * @var string
 552     * @access protected
 553     */
 554    protected $lastMessageID = '';
 555
 556    /**
 557     * The message's MIME type.
 558     * @var string
 559     * @access protected
 560     */
 561    protected $message_type = '';
 562
 563    /**
 564     * The array of MIME boundary strings.
 565     * @var array
 566     * @access protected
 567     */
 568    protected $boundary = array();
 569
 570    /**
 571     * The array of available languages.
 572     * @var array
 573     * @access protected
 574     */
 575    protected $language = array();
 576
 577    /**
 578     * The number of errors encountered.
 579     * @var integer
 580     * @access protected
 581     */
 582    protected $error_count = 0;
 583
 584    /**
 585     * The S/MIME certificate file path.
 586     * @var string
 587     * @access protected
 588     */
 589    protected $sign_cert_file = '';
 590
 591    /**
 592     * The S/MIME key file path.
 593     * @var string
 594     * @access protected
 595     */
 596    protected $sign_key_file = '';
 597
 598    /**
 599     * The optional S/MIME extra certificates ("CA Chain") file path.
 600     * @var string
 601     * @access protected
 602     */
 603    protected $sign_extracerts_file = '';
 604
 605    /**
 606     * The S/MIME password for the key.
 607     * Used only if the key is encrypted.
 608     * @var string
 609     * @access protected
 610     */
 611    protected $sign_key_pass = '';
 612
 613    /**
 614     * Whether to throw exceptions for errors.
 615     * @var boolean
 616     * @access protected
 617     */
 618    protected $exceptions = false;
 619
 620    /**
 621     * Unique ID used for message ID and boundaries.
 622     * @var string
 623     * @access protected
 624     */
 625    protected $uniqueid = '';
 626
 627    /**
 628     * Error severity: message only, continue processing.
 629     */
 630    const STOP_MESSAGE = 0;
 631
 632    /**
 633     * Error severity: message, likely ok to continue processing.
 634     */
 635    const STOP_CONTINUE = 1;
 636
 637    /**
 638     * Error severity: message, plus full stop, critical error reached.
 639     */
 640    const STOP_CRITICAL = 2;
 641
 642    /**
 643     * SMTP RFC standard line ending.
 644     */
 645    const CRLF = "\r\n";
 646
 647    /**
 648     * The maximum line length allowed by RFC 2822 section 2.1.1
 649     * @var integer
 650     */
 651    const MAX_LINE_LENGTH = 998;
 652
 653    /**
 654     * Constructor.
 655     * @param boolean $exceptions Should we throw external exceptions?
 656     */
 657    public function __construct($exceptions = null)
 658    {
 659        if ($exceptions !== null) {
 660            $this->exceptions = (boolean)$exceptions;
 661        }
 662        //Pick an appropriate debug output format automatically
 663        $this->Debugoutput = (strpos(PHP_SAPI, 'cli') !== false ? 'echo' : 'html');
 664    }
 665
 666    /**
 667     * Destructor.
 668     */
 669    public function __destruct()
 670    {
 671        //Close any open SMTP connection nicely
 672        $this->smtpClose();
 673    }
 674
 675    /**
 676     * Call mail() in a safe_mode-aware fashion.
 677     * Also, unless sendmail_path points to sendmail (or something that
 678     * claims to be sendmail), don't pass params (not a perfect fix,
 679     * but it will do)
 680     * @param string $to To
 681     * @param string $subject Subject
 682     * @param string $body Message Body
 683     * @param string $header Additional Header(s)
 684     * @param string $params Params
 685     * @access private
 686     * @return boolean
 687     */
 688    private function mailPassthru($to, $subject, $body, $header, $params)
 689    {
 690        //Check overloading of mail function to avoid double-encoding
 691        if (ini_get('mbstring.func_overload') & 1) {
 692            $subject = $this->secureHeader($subject);
 693        } else {
 694            $subject = $this->encodeHeader($this->secureHeader($subject));
 695        }
 696
 697        //Can't use additional_parameters in safe_mode, calling mail() with null params breaks
 698        //@link http://php.net/manual/en/function.mail.php
 699        if (ini_get('safe_mode') or !$this->UseSendmailOptions or is_null($params)) {
 700            $result = @mail($to, $subject, $body, $header);
 701        } else {
 702            $result = @mail($to, $subject, $body, $header, $params);
 703        }
 704        return $result;
 705    }
 706    /**
 707     * Output debugging info via user-defined method.
 708     * Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug).
 709     * @see PHPMailer::$Debugoutput
 710     * @see PHPMailer::$SMTPDebug
 711     * @param string $str
 712     */
 713    protected function edebug($str)
 714    {
 715        if ($this->SMTPDebug <= 0) {
 716            return;
 717        }
 718        //Avoid clash with built-in function names
 719        if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) {
 720            call_user_func($this->Debugoutput, $str, $this->SMTPDebug);
 721            return;
 722        }
 723        switch ($this->Debugoutput) {
 724            case 'error_log':
 725                //Don't output, just log
 726                error_log($str);
 727                break;
 728            case 'html':
 729                //Cleans up output a bit for a better looking, HTML-safe output
 730                echo htmlentities(
 731                    preg_replace('/[\r\n]+/', '', $str),
 732                    ENT_QUOTES,
 733                    'UTF-8'
 734                )
 735                . "<br>\n";
 736                break;
 737            case 'echo':
 738            default:
 739                //Normalize line breaks
 740                $str = preg_replace('/\r\n?/ms', "\n", $str);
 741                echo gmdate('Y-m-d H:i:s') . "\t" . str_replace(
 742                    "\n",
 743                    "\n                   \t                  ",
 744                    trim($str)
 745                ) . "\n";
 746        }
 747    }
 748
 749    /**
 750     * Sets message type to HTML or plain.
 751     * @param boolean $isHtml True for HTML mode.
 752     * @return void
 753     */
 754    public function isHTML($isHtml = true)
 755    {
 756        if ($isHtml) {
 757            $this->ContentType = 'text/html';
 758        } else {
 759            $this->ContentType = 'text/plain';
 760        }
 761    }
 762
 763    /**
 764     * Send messages using SMTP.
 765     * @return void
 766     */
 767    public function isSMTP()
 768    {
 769        $this->Mailer = 'smtp';
 770    }
 771
 772    /**
 773     * Send messages using PHP's mail() function.
 774     * @return void
 775     */
 776    public function isMail()
 777    {
 778        $this->Mailer = 'mail';
 779    }
 780
 781    /**
 782     * Send messages using $Sendmail.
 783     * @return void
 784     */
 785    public function isSendmail()
 786    {
 787        $ini_sendmail_path = ini_get('sendmail_path');
 788
 789        if (!stristr($ini_sendmail_path, 'sendmail')) {
 790            $this->Sendmail = '/usr/sbin/sendmail';
 791        } else {
 792            $this->Sendmail = $ini_sendmail_path;
 793        }
 794        $this->Mailer = 'sendmail';
 795    }
 796
 797    /**
 798     * Send messages using qmail.
 799     * @return void
 800     */
 801    public function isQmail()
 802    {
 803        $ini_sendmail_path = ini_get('sendmail_path');
 804
 805        if (!stristr($ini_sendmail_path, 'qmail')) {
 806            $this->Sendmail = '/var/qmail/bin/qmail-inject';
 807        } else {
 808            $this->Sendmail = $ini_sendmail_path;
 809        }
 810        $this->Mailer = 'qmail';
 811    }
 812
 813    /**
 814     * Add a "To" address.
 815     * @param string $address The email address to send to
 816     * @param string $name
 817     * @return boolean true on success, false if address already used or invalid in some way
 818     */
 819    public function addAddress($address, $name = '')
 820    {
 821        return $this->addOrEnqueueAnAddress('to', $address, $name);
 822    }
 823
 824    /**
 825     * Add a "CC" address.
 826     * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer.
 827     * @param string $address The email address to send to
 828     * @param string $name
 829     * @return boolean true on success, false if address already used or invalid in some way
 830     */
 831    public function addCC($address, $name = '')
 832    {
 833        return $this->addOrEnqueueAnAddress('cc', $address, $name);
 834    }
 835
 836    /**
 837     * Add a "BCC" address.
 838     * @note: This function works with the SMTP mailer on win32, not with the "mail" mailer.
 839     * @param string $address The email address to send to
 840     * @param string $name
 841     * @return boolean true on success, false if address already used or invalid in some way
 842     */
 843    public function addBCC($address, $name = '')
 844    {
 845        return $this->addOrEnqueueAnAddress('bcc', $address, $name);
 846    }
 847
 848    /**
 849     * Add a "Reply-To" address.
 850     * @param string $address The email address to reply to
 851     * @param string $name
 852     * @return boolean true on success, false if address already used or invalid in some way
 853     */
 854    public function addReplyTo($address, $name = '')
 855    {
 856        return $this->addOrEnqueueAnAddress('Reply-To', $address, $name);
 857    }
 858
 859    /**
 860     * Add an address to one of the recipient arrays or to the ReplyTo array. Because PHPMailer
 861     * can't validate addresses with an IDN without knowing the PHPMailer::$CharSet (that can still
 862     * be modified after calling this function), addition of such addresses is delayed until send().
 863     * Addresses that have been added already return false, but do not throw exceptions.
 864     * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo'
 865     * @param string $address The email address to send, resp. to reply to
 866     * @param string $name
 867     * @throws phpmailerException
 868     * @return boolean true on success, false if address already used or invalid in some way
 869     * @access protected
 870     */
 871    protected function addOrEnqueueAnAddress($kind, $address, $name)
 872    {
 873        $address = trim($address);
 874        $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
 875        if (($pos = strrpos($address, '@')) === false) {
 876            // At-sign is misssing.
 877            $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address";
 878            $this->setError($error_message);
 879            $this->edebug($error_message);
 880            if ($this->exceptions) {
 881                throw new phpmailerException($error_message);
 882            }
 883            return false;
 884        }
 885        $params = array($kind, $address, $name);
 886        // Enqueue addresses with IDN until we know the PHPMailer::$CharSet.
 887        if ($this->has8bitChars(substr($address, ++$pos)) and $this->idnSupported()) {
 888            if ($kind != 'Reply-To') {
 889                if (!array_key_exists($address, $this->RecipientsQueue)) {
 890                    $this->RecipientsQueue[$address] = $params;
 891                    return true;
 892                }
 893            } else {
 894                if (!array_key_exists($address, $this->ReplyToQueue)) {
 895                    $this->ReplyToQueue[$address] = $params;
 896                    return true;
 897                }
 898            }
 899            return false;
 900        }
 901        // Immediately add standard addresses without IDN.
 902        return call_user_func_array(array($this, 'addAnAddress'), $params);
 903    }
 904
 905    /**
 906     * Add an address to one of the recipient arrays or to the ReplyTo array.
 907     * Addresses that have been added already return false, but do not throw exceptions.
 908     * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo'
 909     * @param string $address The email address to send, resp. to reply to
 910     * @param string $name
 911     * @throws phpmailerException
 912     * @return boolean true on success, false if address already used or invalid in some way
 913     * @access protected
 914     */
 915    protected function addAnAddress($kind, $address, $name = '')
 916    {
 917        if (!in_array($kind, array('to', 'cc', 'bcc', 'Reply-To'))) {
 918            $error_message = $this->lang('Invalid recipient kind: ') . $kind;
 919            $this->setError($error_message);
 920            $this->edebug($error_message);
 921            if ($this->exceptions) {
 922                throw new phpmailerException($error_message);
 923            }
 924            return false;
 925        }
 926        if (!$this->validateAddress($address)) {
 927            $error_message = $this->lang('invalid_address') . " (addAnAddress $kind): $address";
 928            $this->setError($error_message);
 929            $this->edebug($error_message);
 930            if ($this->exceptions) {
 931                throw new phpmailerException($error_message);
 932            }
 933            return false;
 934        }
 935        if ($kind != 'Reply-To') {
 936            if (!array_key_exists(strtolower($address), $this->all_recipients)) {
 937                array_push($this->$kind, array($address, $name));
 938                $this->all_recipients[strtolower($address)] = true;
 939                return true;
 940            }
 941        } else {
 942            if (!array_key_exists(strtolower($address), $this->ReplyTo)) {
 943                $this->ReplyTo[strtolower($address)] = array($address, $name);
 944                return true;
 945            }
 946        }
 947        return false;
 948    }
 949
 950    /**
 951     * Parse and validate a string containing one or more RFC822-style comma-separated email addresses
 952     * of the form "display name <address>" into an array of name/address pairs.
 953     * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available.
 954     * Note that quotes in the name part are removed.
 955     * @param string $addrstr The address list string
 956     * @param bool $useimap Whether to use the IMAP extension to parse the list
 957     * @return array
 958     * @link http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation
 959     */
 960    public function parseAddresses($addrstr, $useimap = true)
 961    {
 962        $addresses = array();
 963        if ($useimap and function_exists('imap_rfc822_parse_adrlist')) {
 964            //Use this built-in parser if it's available
 965            $list = imap_rfc822_parse_adrlist($addrstr, '');
 966            foreach ($list as $address) {
 967                if ($address->host != '.SYNTAX-ERROR.') {
 968                    if ($this->validateAddress($address->mailbox . '@' . $address->host)) {
 969                        $addresses[] = array(
 970                            'name' => (property_exists($address, 'personal') ? $address->personal : ''),
 971                            'address' => $address->mailbox . '@' . $address->host
 972                        );
 973                    }
 974                }
 975            }
 976        } else {
 977            //Use this simpler parser
 978            $list = explode(',', $addrstr);
 979            foreach ($list as $address) {
 980                $address = trim($address);
 981                //Is there a separate name part?
 982                if (strpos($address, '<') === false) {
 983                    //No separate name, just use the whole thing
 984                    if ($this->validateAddress($address)) {
 985                        $addresses[] = array(
 986                            'name' => '',
 987                            'address' => $address
 988                        );
 989                    }
 990                } else {
 991                    list($name, $email) = explode('<', $address);
 992                    $email = trim(str_replace('>', '', $email));
 993                    if ($this->validateAddress($email)) {
 994                        $addresses[] = array(
 995                            'name' => trim(str_replace(array('"', "'"), '', $name)),
 996                            'address' => $email
 997                        );
 998                    }
 999                }
1000            }
1001        }
1002        return $addresses;
1003    }
1004
1005    /**
1006     * Set the From and FromName properties.
1007     * @param string $address
1008     * @param string $name
1009     * @param boolean $auto Whether to also set the Sender address, defaults to true
1010     * @throws phpmailerException
1011     * @return boolean
1012     */
1013    public function setFrom($address, $name = '', $auto = true)
1014    {
1015        $address = trim($address);
1016        $name = trim(preg_replace('/[\r\n]+/', '', $name)); //Strip breaks and trim
1017        // Don't validate now addresses with IDN. Will be done in send().
1018        if (($pos = strrpos($address, '@')) === false or
1019            (!$this->has8bitChars(substr($address, ++$pos)) or !$this->idnSupported()) and
1020            !$this->validateAddress($address)) {
1021            $error_message = $this->lang('invalid_address') . " (setFrom) $address";
1022            $this->setError($error_message);
1023            $this->edebug($error_message);
1024            if ($this->exceptions) {
1025                throw new phpmailerException($error_message);
1026            }
1027            return false;
1028        }
1029        $this->From = $address;
1030        $this->FromName = $name;
1031        if ($auto) {
1032            if (empty($this->Sender)) {
1033                $this->Sender = $address;
1034            }
1035        }
1036        return true;
1037    }
1038
1039    /**
1040     * Return the Message-ID header of the last email.
1041     * Technically this is the value from the last time the headers were created,
1042     * but it's also the message ID of the last sent message except in
1043     * pathological cases.
1044     * @return string
1045     */
1046    public function getLastMessageID()
1047    {
1048        return $this->lastMessageID;
1049    }
1050
1051    /**
1052     * Check that a string looks like an email address.
1053     * @param string $address The email address to check
1054     * @param string|callable $patternselect A selector for the validation pattern to use :
1055     * * `auto` Pick best pattern automatically;
1056     * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
1057     * * `pcre` Use old PCRE implementation;
1058     * * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
1059     * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
1060     * * `noregex` Don't use a regex: super fast, really dumb.
1061     * Alternatively you may pass in a callable to inject your own validator, for example:
1062     * PHPMailer::validateAddress('user@example.com', function($address) {
1063     *     return (strpos($address, '@') !== false);
1064     * });
1065     * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator.
1066     * @return boolean
1067     * @static
1068     * @access public
1069     */
1070    public static function validateAddress($address, $patternselect = null)
1071    {
1072        if (is_null($patternselect)) {
1073            $patternselect = self::$validator;
1074        }
1075        if (is_callable($patternselect)) {
1076            return call_user_func($patternselect, $address);
1077        }
1078        //Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
1079        if (strpos($address, "\n") !== false or strpos($address, "\r") !== false) {
1080            return false;
1081        }
1082        if (!$patternselect or $patternselect == 'auto') {
1083            //Check this constant first so it works when extension_loaded() is disabled by safe mode
1084            //Constant was added in PHP 5.2.4
1085            if (defined('PCRE_VERSION')) {
1086                //This pattern can get stuck in a recursive loop in PCRE <= 8.0.2
1087                if (version_compare(PCRE_VERSION, '8.0.3') >= 0) {
1088                    $patternselect = 'pcre8';
1089                } else {
1090                    $patternselect = 'pcre';
1091                }
1092            } elseif (function_exists('extension_loaded') and extension_loaded('pcre')) {
1093                //Fall back to older PCRE
1094                $patternselect = 'pcre';
1095            } else {
1096                //Filter_var appeared in PHP 5.2.0 and does not require the PCRE extension
1097                if (version_compare(PHP_VERSION, '5.2.0') >= 0) {
1098                    $patternselect = 'php';
1099                } else {
1100                    $patternselect = 'noregex';
1101                }
1102            }
1103        }
1104        switch ($patternselect) {
1105            case 'pcre8':
1106                /**
1107                 * Uses the same RFC5322 regex on which FILTER_VALIDATE_EMAIL is based, but allows dotless domains.
1108                 * @link http://squiloople.com/2009/12/20/email-address-validation/
1109                 * @copyright 2009-2010 Michael Rushton
1110                 * Feel free to use and redistribute this code. But please keep this copyright notice.
1111                 */
1112                return (boolean)preg_match(
1113                    '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' .
1114                    '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' .
1115                    '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' .
1116                    '([!#-\'*+\/-9=?^-~-]+|"(?>(?2)(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\x7F]))*' .
1117                    '(?2)")(?>(?1)\.(?1)(?4))*(?1)@(?!(?1)[a-z0-9-]{64,})(?1)(?>([a-z0-9](?>[a-z0-9-]*[a-z0-9])?)' .
1118                    '(?>(?1)\.(?!(?1)[a-z0-9-]{64,})(?1)(?5)){0,126}|\[(?:(?>IPv6:(?>([a-f0-9]{1,4})(?>:(?6)){7}' .
1119                    '|(?!(?:.*[a-f0-9][:\]]){8,})((?6)(?>:(?6)){0,6})?::(?7)?))|(?>(?>IPv6:(?>(?6)(?>:(?6)){5}:' .
1120                    '|(?!(?:.*[a-f0-9]:){6,})(?8)?::(?>((?6)(?>:(?6)){0,4}):)?))?(25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
1121                    '|[1-9]?[0-9])(?>\.(?9)){3}))\])(?1)$/isD',
1122                    $address
1123                );
1124            case 'pcre':
1125                //An older regex that doesn't need a recent PCRE
1126                return (boolean)preg_match(
1127                    '/^(?!(?>"?(?>\\\[ -~]|[^"])"?){255,})(?!(?>"?(?>\\\[ -~]|[^"])"?){65,}@)(?>' .
1128                    '[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*")' .
1129                    '(?>\.(?>[!#-\'*+\/-9=?^-~-]+|"(?>(?>[\x01-\x08\x0B\x0C\x0E-!#-\[\]-\x7F]|\\\[\x00-\xFF]))*"))*' .
1130                    '@(?>(?![a-z0-9-]{64,})(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)(?>\.(?![a-z0-9-]{64,})' .
1131                    '(?>[a-z0-9](?>[a-z0-9-]*[a-z0-9])?)){0,126}|\[(?:(?>IPv6:(?>(?>[a-f0-9]{1,4})(?>:' .
1132                    '[a-f0-9]{1,4}){7}|(?!(?:.*[a-f0-9][:\]]){8,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?' .
1133                    '::(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,6})?))|(?>(?>IPv6:(?>[a-f0-9]{1,4}(?>:' .
1134                    '[a-f0-9]{1,4}){5}:|(?!(?:.*[a-f0-9]:){6,})(?>[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4})?' .
1135                    '::(?>(?:[a-f0-9]{1,4}(?>:[a-f0-9]{1,4}){0,4}):)?))?(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}' .
1136                    '|[1-9]?[0-9])(?>\.(?>25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}))\])$/isD',
1137                    $address
1138                );
1139            case 'html5':
1140                /**
1141                 * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements.
1142                 * @link http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email)
1143                 */
1144                return (boolean)preg_match(
1145                    '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' .
1146                    '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD',
1147                    $address
1148                );
1149            case 'noregex':
1150                //No PCRE! Do something _very_ approximate!
1151                //Check the address is 3 chars or longer and contains an @ that's not the first or last char
1152                return (strlen($address) >= 3
1153                    and strpos($address, '@') >= 1
1154                    and strpos($address, '@') != strlen($address) - 1);
1155            case 'php':
1156            default:
1157                return (boolean)filter_var($address, FILTER_VALIDATE_EMAIL);
1158        }
1159    }
1160
1161    /**
1162     * Tells whether IDNs (Internationalized Domain Names) are supported or not. This requires the
1163     * "intl" and "mbstring" PHP extensions.
1164     * @return bool "true" if required functions for IDN support are present
1165     */
1166    public function idnSupported()
1167    {
1168        // @TODO: Write our own "idn_to_ascii" function for PHP <= 5.2.
1169        return function_exists('idn_to_ascii') and function_exists('mb_convert_encoding');
1170    }
1171
1172    /**
1173     * Converts IDN in given email address to its ASCII form, also known as punycode, if possible.
1174     * Important: Address must be passed in same encoding as currently set in PHPMailer::$CharSet.
1175     * This function silently returns unmodified address if:
1176     * - No conversion is necessary (i.e. domain name is not an IDN, or is already in ASCII form)
1177     * - Conversion to punycode is impossible (e.g. required PHP functions are not available)
1178     *   or fails for any reason (e.g. domain has characters not allowed in an IDN)
1179     * @see PHPMailer::$CharSet
1180     * @param string $address The email address to convert
1181     * @return string The encoded address in ASCII form
1182     */
1183    public function punyencodeAddress($address)
1184    {
1185        // Verify we have required functions, CharSet, and at-sign.
1186        if ($this->idnSupported() and
1187            !empty($this->CharSet) and
1188            ($pos = strrpos($address, '@')) !== false) {
1189            $domain = substr($address, ++$pos);
1190            // Verify CharSet string is a valid one, and domain properly encoded in this CharSet.
1191            if ($this->has8bitChars($domain) and @mb_check_encoding($domain, $this->CharSet)) {
1192                $domain = mb_convert_encoding($domain, 'UTF-8', $this->CharSet);
1193                if (($punycode = defined('INTL_IDNA_VARIANT_UTS46') ?
1194                    idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46) :
1195                    idn_to_ascii($domain)) !== false) {
1196                    return substr($address, 0, $pos) . $punycode;
1197                }
1198            }
1199        }
1200        return $address;
1201    }
1202
1203    /**
1204     * Create a message and send it.
1205     * Uses the sending method specified by $Mailer.
1206     * @throws phpmailerException
1207     * @return boolean false on error - See the ErrorInfo property for details of the error.
1208     */
1209    public function send()
1210    {
1211        try {
1212            if (!$this->preSend()) {
1213                return false;
1214            }
1215            return $this->postSend();
1216        } catch (phpmailerException $exc) {
1217            $this->mailHeader = '';
1218            $this->setError($exc->getMessage());
1219            if ($this->exceptions) {
1220                throw $exc;
1221            }
1222            return false;
1223        }
1224    }
1225
1226    /**
1227     * Prepare a message for sending.
1228     * @throws phpmailerException
1229     * @return boolean
1230     */
1231    public function preSend()
1232    {
1233        try {
1234            $this->error_count = 0; // Reset errors
1235            $this->mailHeader = '';
1236
1237            // Dequeue recipient and Reply-To addresses with IDN
1238            foreach (array_merge($this->RecipientsQueue, $this->ReplyToQueue) as $params) {
1239                $params[1] = $this->punyencodeAddress($params[1]);
1240                call_user_func_array(array($this, 'addAnAddress'), $params);
1241            }
1242            if ((count($this->to) + count($this->cc) + count($this->bcc)) < 1) {
1243                throw new phpmailerException($this->lang('provide_address'), self::STOP_CRITICAL);
1244            }
1245
1246            // Validate From, Sender, and ConfirmReadingTo addresses
1247            foreach (array('From', 'Sender', 'ConfirmReadingTo') as $address_kind) {
1248                $this->$address_kind = trim($this->$address_kind);
1249                if (empty($this->$address_kind)) {
1250                    continue;
1251                }
1252                $this->$address_kind = $this->punyencodeAddress($this->$address_kind);
1253                if (!$this->validateAddress($this->$address_kind)) {
1254                    $error_message = $this->lang('invalid_address') . ' (punyEncode) ' . $this->$address_kind;
1255                    $this->setError($error_message);
1256                    $this->edebug($error_message);
1257                    if ($this->exceptions) {
1258                        throw new phpmailerException($error_message);
1259                    }
1260                    return false;
1261                }
1262            }
1263
1264            // Set whether the message is multipart/alternative
1265            if ($this->alternativeExists()) {
1266                $this->ContentType = 'multipart/alternative';
1267            }
1268
1269            $this->setMessageType();
1270            // Refuse to send an empty message unless we are specifically allowing it
1271            if (!$this->AllowEmpty and empty($this->Body)) {
1272                throw new phpmailerException($this->lang('empty_message'), self::STOP_CRITICAL);
1273            }
1274
1275            // Create body before headers in case body makes changes to headers (e.g. altering transfer encoding)
1276            $this->MIMEHeader = '';
1277            $this->MIMEBody = $this->createBody();
1278            // createBody may have added some headers, so retain them
1279            $tempheaders = $this->MIMEHeader;
1280            $this->MIMEHeader = $this->createHeader();
1281            $this->MIMEHeader .= $tempheaders;
1282
1283            // To capture the complete message when using mail(), create
1284            // an extra header list which createHeader() doesn't fold in
1285            if ($this->Mailer == 'mail') {
1286                if (count($this->to) > 0) {
1287                    $this->mailHeader .= $this->addrAppend('To', $this->to);
1288                } else {
1289                    $this->mailHeader .= $this->headerLine('To', 'undisclosed-recipients:;');
1290                }
1291                $this->mailHeader .= $this->headerLine(
1292                    'Subject',
1293                    $this->encodeHeader($this->secureHeader(trim($this->Subject)))
1294                );
1295            }
1296
1297            // Sign with DKIM if enabled
1298            if (!empty($this->DKIM_domain)
1299                and !empty($this->DKIM_selector)
1300                and (!empty($this->DKIM_private_string)
1301                    or (!empty($this->DKIM_private)
1302                        and self::isPermittedPath($this->DKIM_private)
1303                        and file_exists($this->DKIM_private)
1304                    )
1305                )
1306            ) {
1307                $header_dkim = $this->DKIM_Add(
1308                    $this->MIMEHeader . $this->mailHeader,
1309                    $this->encodeHeader($this->secureHeader($this->Subject)),
1310                    $this->MIMEBody
1311                );
1312                $this->MIMEHeader = rtrim($this->MIMEHeader, "\r\n ") . self::CRLF .
1313                    str_replace("\r\n", "\n", $header_dkim) . self::CRLF;
1314            }
1315            return true;
1316        } catch (phpmailerException $exc) {
1317            $this->setError($exc->getMessage());
1318            if ($this->exceptions) {
1319                throw $exc;
1320            }
1321            return false;
1322        }
1323    }
1324
1325    /**
1326     * Actually send a message.
1327     * Send the email via the selected mechanism
1328     * @throws phpmailerException
1329     * @return boolean
1330     */
1331    public function postSend()
1332    {
1333        try {
1334            // Choose the mailer and send through it
1335            switch ($this->Mailer) {
1336                case 'sendmail':
1337                case 'qmail':
1338                    return $this->sendmailSend($this->MIMEHeader, $this->MIMEBody);
1339                case 'smtp':
1340                    return $this->smtpSend($this->MIMEHeader, $this->MIMEBody);
1341                case 'mail':
1342                    return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
1343                default:
1344                    $sendMethod = $this->Mailer.'Send';
1345                    if (method_exists($this, $sendMethod)) {
1346                        return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody);
1347                    }
1348
1349                    return $this->mailSend($this->MIMEHeader, $this->MIMEBody);
1350            }
1351        } catch (phpmailerException $exc) {
1352            $this->setError($exc->getMessage());
1353            $this->edebug($exc->getMessage());
1354            if ($this->exceptions) {
1355                throw $exc;
1356            }
1357        }
1358        return false;
1359    }
1360
1361    /**
1362     * Send mail using the $Sendmail program.
1363     * @param string $header The message headers
1364     * @param string $body The message body
1365     * @see PHPMailer::$Sendmail
1366     * @throws phpmailerException
1367     * @access protected
1368     * @return boolean
1369     */
1370    protected function sendmailSend($header, $body)
1371    {
1372        // CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
1373        if (!empty($this->Sender) and self::isShellSafe($this->Sender)) {
1374            if ($this->Mailer == 'qmail') {
1375                $sendmailFmt = '%s -f%s';
1376            } else {
1377                $sendmailFmt = '%s -oi -f%s -t';
1378            }
1379        } else {
1380            if ($this->Mailer == 'qmail') {
1381                $sendmailFmt = '%s';
1382            } else {
1383                $sendmailFmt = '%s -oi -t';
1384            }
1385        }
1386
1387        // TODO: If possible, this should be changed to escapeshellarg.  Needs thorough testing.
1388        $sendmail = sprintf($sendmailFmt, escapeshellcmd($this->Sendmail), $this->Sender);
1389
1390        if ($this->SingleTo) {
1391            foreach ($this->SingleToArray as $toAddr) {
1392                if (!@$mail = popen($sendmail, 'w')) {
1393                    throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1394                }
1395                fputs($mail, 'To: ' . $toAddr . "\n");
1396                fputs($mail, $header);
1397                fputs($mail, $body);
1398                $result = pclose($mail);
1399                $this->doCallback(
1400                    ($result == 0),
1401                    array($toAddr),
1402                    $this->cc,
1403                    $this->bcc,
1404                    $this->Subject,
1405                    $body,
1406                    $this->From
1407                );
1408                if ($result != 0) {
1409                    throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1410                }
1411            }
1412        } else {
1413            if (!@$mail = popen($sendmail, 'w')) {
1414                throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1415            }
1416            fputs($mail, $header);
1417            fputs($mail, $body);
1418            $result = pclose($mail);
1419            $this->doCallback(
1420                ($result == 0),
1421                $this->to,
1422                $this->cc,
1423                $this->bcc,
1424                $this->Subject,
1425                $body,
1426                $this->From
1427            );
1428            if ($result != 0) {
1429                throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
1430            }
1431        }
1432        return true;
1433    }
1434
1435    /**
1436     * Fix CVE-2016-10033 and CVE-2016-10045 by disallowing potentially unsafe shell characters.
1437     *
1438     * Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows.
1439     * @param string $string The string to be validated
1440     * @see https://github.com/PHPMailer/PHPMailer/issues/924 CVE-2016-10045 bug report
1441     * @access protected
1442     * @return boolean
1443     */
1444    protected static function isShellSafe($string)
1445    {
1446        // Future-proof
1447        if (escapeshellcmd($string) !== $string
1448            or !in_array(escapeshellarg($string), array("'$string'", "\"$string\""))
1449        ) {
1450            return false;
1451        }
1452
1453        $length = strlen($string);
1454
1455        for ($i = 0; $i < $length; $i++) {
1456            $c = $string[$i];
1457
1458            // All other characters have a special meaning in at least one common shell, including = and +.
1459            // Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here.
1460            // Note that this does permit non-Latin alphanumeric characters based on the …

Large files files are truncated, but you can click here to view the full file