Make WordPress Core

Ticket #25560: ticket-25560-phpmailer-full-binary.patch

File ticket-25560-phpmailer-full-binary.patch, 764.1 KB (added by bpetty, 11 years ago)

This is a binary patch (contains images), and can only be applied with "git apply".

  • new file src/wp-includes/PHPMailer/.gitignore

    diff --git src/wp-includes/PHPMailer/.gitignore src/wp-includes/PHPMailer/.gitignore
    new file mode 100644
    index 0000000..88d2922
    - +  
     1docs/phpdoc/
     2test/message.txt
     3test/testbootstrap.php
     4.idea
  • new file src/wp-includes/PHPMailer/.travis.yml

    diff --git src/wp-includes/PHPMailer/.travis.yml src/wp-includes/PHPMailer/.travis.yml
    new file mode 100644
    index 0000000..28f0099
    - +  
     1language: php
     2php:
     3  - 5.5
     4  - 5.4
     5  - 5.3
     6before_install:
     7  - sudo apt-get update -qq
     8  - sudo apt-get install -y -qq postfix
     9before_script:
     10  - sudo service postfix stop
     11  - smtp-sink -d "%d.%H.%M.%S" localhost:2500 1000 &
     12  - cd test
     13  - cp testbootstrap-dist.php testbootstrap.php
     14  - chmod +x fakesendmail.sh
     15  - sudo mkdir -p /var/qmail/bin
     16  - sudo cp fakesendmail.sh /var/qmail/bin/sendmail
     17  - sudo cp fakesendmail.sh /usr/sbin/sendmail
     18  - echo 'sendmail_path = "/usr/sbin/sendmail -t -i "' | sudo tee "/home/travis/.phpenv/versions/`php -i|grep "PHP Version"|head -n 1|grep -o -P '\d+\.\d+\.\d+.*'`/etc/conf.d/sendmail.ini"
     19script:
     20  - phpunit phpmailerTest
  • new file src/wp-includes/PHPMailer/LICENSE

    diff --git src/wp-includes/PHPMailer/LICENSE src/wp-includes/PHPMailer/LICENSE
    new file mode 100644
    index 0000000..8e0763d
    - +  
     1                  GNU LESSER GENERAL PUBLIC LICENSE
     2                       Version 2.1, February 1999
     3
     4 Copyright (C) 1991, 1999 Free Software Foundation, Inc.
     5     59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     6 Everyone is permitted to copy and distribute verbatim copies
     7 of this license document, but changing it is not allowed.
     8
     9[This is the first released version of the Lesser GPL.  It also counts
     10 as the successor of the GNU Library Public License, version 2, hence
     11 the version number 2.1.]
     12
     13                            Preamble
     14
     15  The licenses for most software are designed to take away your
     16freedom to share and change it.  By contrast, the GNU General Public
     17Licenses are intended to guarantee your freedom to share and change
     18free software--to make sure the software is free for all its users.
     19
     20  This license, the Lesser General Public License, applies to some
     21specially designated software packages--typically libraries--of the
     22Free Software Foundation and other authors who decide to use it.  You
     23can use it too, but we suggest you first think carefully about whether
     24this license or the ordinary General Public License is the better
     25strategy to use in any particular case, based on the explanations below.
     26
     27  When we speak of free software, we are referring to freedom of use,
     28not price.  Our General Public Licenses are designed to make sure that
     29you have the freedom to distribute copies of free software (and charge
     30for this service if you wish); that you receive source code or can get
     31it if you want it; that you can change the software and use pieces of
     32it in new free programs; and that you are informed that you can do
     33these things.
     34
     35  To protect your rights, we need to make restrictions that forbid
     36distributors to deny you these rights or to ask you to surrender these
     37rights.  These restrictions translate to certain responsibilities for
     38you if you distribute copies of the library or if you modify it.
     39
     40  For example, if you distribute copies of the library, whether gratis
     41or for a fee, you must give the recipients all the rights that we gave
     42you.  You must make sure that they, too, receive or can get the source
     43code.  If you link other code with the library, you must provide
     44complete object files to the recipients, so that they can relink them
     45with the library after making changes to the library and recompiling
     46it.  And you must show them these terms so they know their rights.
     47
     48  We protect your rights with a two-step method: (1) we copyright the
     49library, and (2) we offer you this license, which gives you legal
     50permission to copy, distribute and/or modify the library.
     51
     52  To protect each distributor, we want to make it very clear that
     53there is no warranty for the free library.  Also, if the library is
     54modified by someone else and passed on, the recipients should know
     55that what they have is not the original version, so that the original
     56author's reputation will not be affected by problems that might be
     57introduced by others.
     58
     59  Finally, software patents pose a constant threat to the existence of
     60any free program.  We wish to make sure that a company cannot
     61effectively restrict the users of a free program by obtaining a
     62restrictive license from a patent holder.  Therefore, we insist that
     63any patent license obtained for a version of the library must be
     64consistent with the full freedom of use specified in this license.
     65
     66  Most GNU software, including some libraries, is covered by the
     67ordinary GNU General Public License.  This license, the GNU Lesser
     68General Public License, applies to certain designated libraries, and
     69is quite different from the ordinary General Public License.  We use
     70this license for certain libraries in order to permit linking those
     71libraries into non-free programs.
     72
     73  When a program is linked with a library, whether statically or using
     74a shared library, the combination of the two is legally speaking a
     75combined work, a derivative of the original library.  The ordinary
     76General Public License therefore permits such linking only if the
     77entire combination fits its criteria of freedom.  The Lesser General
     78Public License permits more lax criteria for linking other code with
     79the library.
     80
     81  We call this license the "Lesser" General Public License because it
     82does Less to protect the user's freedom than the ordinary General
     83Public License.  It also provides other free software developers Less
     84of an advantage over competing non-free programs.  These disadvantages
     85are the reason we use the ordinary General Public License for many
     86libraries.  However, the Lesser license provides advantages in certain
     87special circumstances.
     88
     89  For example, on rare occasions, there may be a special need to
     90encourage the widest possible use of a certain library, so that it becomes
     91a de-facto standard.  To achieve this, non-free programs must be
     92allowed to use the library.  A more frequent case is that a free
     93library does the same job as widely used non-free libraries.  In this
     94case, there is little to gain by limiting the free library to free
     95software only, so we use the Lesser General Public License.
     96
     97  In other cases, permission to use a particular library in non-free
     98programs enables a greater number of people to use a large body of
     99free software.  For example, permission to use the GNU C Library in
     100non-free programs enables many more people to use the whole GNU
     101operating system, as well as its variant, the GNU/Linux operating
     102system.
     103
     104  Although the Lesser General Public License is Less protective of the
     105users' freedom, it does ensure that the user of a program that is
     106linked with the Library has the freedom and the wherewithal to run
     107that program using a modified version of the Library.
     108
     109  The precise terms and conditions for copying, distribution and
     110modification follow.  Pay close attention to the difference between a
     111"work based on the library" and a "work that uses the library".  The
     112former contains code derived from the library, whereas the latter must
     113be combined with the library in order to run.
     114
     115                  GNU LESSER GENERAL PUBLIC LICENSE
     116   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
     117
     118  0. This License Agreement applies to any software library or other
     119program which contains a notice placed by the copyright holder or
     120other authorized party saying it may be distributed under the terms of
     121this Lesser General Public License (also called "this License").
     122Each licensee is addressed as "you".
     123
     124  A "library" means a collection of software functions and/or data
     125prepared so as to be conveniently linked with application programs
     126(which use some of those functions and data) to form executables.
     127
     128  The "Library", below, refers to any such software library or work
     129which has been distributed under these terms.  A "work based on the
     130Library" means either the Library or any derivative work under
     131copyright law: that is to say, a work containing the Library or a
     132portion of it, either verbatim or with modifications and/or translated
     133straightforwardly into another language.  (Hereinafter, translation is
     134included without limitation in the term "modification".)
     135
     136  "Source code" for a work means the preferred form of the work for
     137making modifications to it.  For a library, complete source code means
     138all the source code for all modules it contains, plus any associated
     139interface definition files, plus the scripts used to control compilation
     140and installation of the library.
     141
     142  Activities other than copying, distribution and modification are not
     143covered by this License; they are outside its scope.  The act of
     144running a program using the Library is not restricted, and output from
     145such a program is covered only if its contents constitute a work based
     146on the Library (independent of the use of the Library in a tool for
     147writing it).  Whether that is true depends on what the Library does
     148and what the program that uses the Library does.
     149 
     150  1. You may copy and distribute verbatim copies of the Library's
     151complete source code as you receive it, in any medium, provided that
     152you conspicuously and appropriately publish on each copy an
     153appropriate copyright notice and disclaimer of warranty; keep intact
     154all the notices that refer to this License and to the absence of any
     155warranty; and distribute a copy of this License along with the
     156Library.
     157
     158  You may charge a fee for the physical act of transferring a copy,
     159and you may at your option offer warranty protection in exchange for a
     160fee.
     161
     162  2. You may modify your copy or copies of the Library or any portion
     163of it, thus forming a work based on the Library, and copy and
     164distribute such modifications or work under the terms of Section 1
     165above, provided that you also meet all of these conditions:
     166
     167    a) The modified work must itself be a software library.
     168
     169    b) You must cause the files modified to carry prominent notices
     170    stating that you changed the files and the date of any change.
     171
     172    c) You must cause the whole of the work to be licensed at no
     173    charge to all third parties under the terms of this License.
     174
     175    d) If a facility in the modified Library refers to a function or a
     176    table of data to be supplied by an application program that uses
     177    the facility, other than as an argument passed when the facility
     178    is invoked, then you must make a good faith effort to ensure that,
     179    in the event an application does not supply such function or
     180    table, the facility still operates, and performs whatever part of
     181    its purpose remains meaningful.
     182
     183    (For example, a function in a library to compute square roots has
     184    a purpose that is entirely well-defined independent of the
     185    application.  Therefore, Subsection 2d requires that any
     186    application-supplied function or table used by this function must
     187    be optional: if the application does not supply it, the square
     188    root function must still compute square roots.)
     189
     190These requirements apply to the modified work as a whole.  If
     191identifiable sections of that work are not derived from the Library,
     192and can be reasonably considered independent and separate works in
     193themselves, then this License, and its terms, do not apply to those
     194sections when you distribute them as separate works.  But when you
     195distribute the same sections as part of a whole which is a work based
     196on the Library, the distribution of the whole must be on the terms of
     197this License, whose permissions for other licensees extend to the
     198entire whole, and thus to each and every part regardless of who wrote
     199it.
     200
     201Thus, it is not the intent of this section to claim rights or contest
     202your rights to work written entirely by you; rather, the intent is to
     203exercise the right to control the distribution of derivative or
     204collective works based on the Library.
     205
     206In addition, mere aggregation of another work not based on the Library
     207with the Library (or with a work based on the Library) on a volume of
     208a storage or distribution medium does not bring the other work under
     209the scope of this License.
     210
     211  3. You may opt to apply the terms of the ordinary GNU General Public
     212License instead of this License to a given copy of the Library.  To do
     213this, you must alter all the notices that refer to this License, so
     214that they refer to the ordinary GNU General Public License, version 2,
     215instead of to this License.  (If a newer version than version 2 of the
     216ordinary GNU General Public License has appeared, then you can specify
     217that version instead if you wish.)  Do not make any other change in
     218these notices.
     219
     220  Once this change is made in a given copy, it is irreversible for
     221that copy, so the ordinary GNU General Public License applies to all
     222subsequent copies and derivative works made from that copy.
     223
     224  This option is useful when you wish to copy part of the code of
     225the Library into a program that is not a library.
     226
     227  4. You may copy and distribute the Library (or a portion or
     228derivative of it, under Section 2) in object code or executable form
     229under the terms of Sections 1 and 2 above provided that you accompany
     230it with the complete corresponding machine-readable source code, which
     231must be distributed under the terms of Sections 1 and 2 above on a
     232medium customarily used for software interchange.
     233
     234  If distribution of object code is made by offering access to copy
     235from a designated place, then offering equivalent access to copy the
     236source code from the same place satisfies the requirement to
     237distribute the source code, even though third parties are not
     238compelled to copy the source along with the object code.
     239
     240  5. A program that contains no derivative of any portion of the
     241Library, but is designed to work with the Library by being compiled or
     242linked with it, is called a "work that uses the Library".  Such a
     243work, in isolation, is not a derivative work of the Library, and
     244therefore falls outside the scope of this License.
     245
     246  However, linking a "work that uses the Library" with the Library
     247creates an executable that is a derivative of the Library (because it
     248contains portions of the Library), rather than a "work that uses the
     249library".  The executable is therefore covered by this License.
     250Section 6 states terms for distribution of such executables.
     251
     252  When a "work that uses the Library" uses material from a header file
     253that is part of the Library, the object code for the work may be a
     254derivative work of the Library even though the source code is not.
     255Whether this is true is especially significant if the work can be
     256linked without the Library, or if the work is itself a library.  The
     257threshold for this to be true is not precisely defined by law.
     258
     259  If such an object file uses only numerical parameters, data
     260structure layouts and accessors, and small macros and small inline
     261functions (ten lines or less in length), then the use of the object
     262file is unrestricted, regardless of whether it is legally a derivative
     263work.  (Executables containing this object code plus portions of the
     264Library will still fall under Section 6.)
     265
     266  Otherwise, if the work is a derivative of the Library, you may
     267distribute the object code for the work under the terms of Section 6.
     268Any executables containing that work also fall under Section 6,
     269whether or not they are linked directly with the Library itself.
     270
     271  6. As an exception to the Sections above, you may also combine or
     272link a "work that uses the Library" with the Library to produce a
     273work containing portions of the Library, and distribute that work
     274under terms of your choice, provided that the terms permit
     275modification of the work for the customer's own use and reverse
     276engineering for debugging such modifications.
     277
     278  You must give prominent notice with each copy of the work that the
     279Library is used in it and that the Library and its use are covered by
     280this License.  You must supply a copy of this License.  If the work
     281during execution displays copyright notices, you must include the
     282copyright notice for the Library among them, as well as a reference
     283directing the user to the copy of this License.  Also, you must do one
     284of these things:
     285
     286    a) Accompany the work with the complete corresponding
     287    machine-readable source code for the Library including whatever
     288    changes were used in the work (which must be distributed under
     289    Sections 1 and 2 above); and, if the work is an executable linked
     290    with the Library, with the complete machine-readable "work that
     291    uses the Library", as object code and/or source code, so that the
     292    user can modify the Library and then relink to produce a modified
     293    executable containing the modified Library.  (It is understood
     294    that the user who changes the contents of definitions files in the
     295    Library will not necessarily be able to recompile the application
     296    to use the modified definitions.)
     297
     298    b) Use a suitable shared library mechanism for linking with the
     299    Library.  A suitable mechanism is one that (1) uses at run time a
     300    copy of the library already present on the user's computer system,
     301    rather than copying library functions into the executable, and (2)
     302    will operate properly with a modified version of the library, if
     303    the user installs one, as long as the modified version is
     304    interface-compatible with the version that the work was made with.
     305
     306    c) Accompany the work with a written offer, valid for at
     307    least three years, to give the same user the materials
     308    specified in Subsection 6a, above, for a charge no more
     309    than the cost of performing this distribution.
     310
     311    d) If distribution of the work is made by offering access to copy
     312    from a designated place, offer equivalent access to copy the above
     313    specified materials from the same place.
     314
     315    e) verify that the user has already received a copy of these
     316    materials or that you have already sent this user a copy.
     317
     318  For an executable, the required form of the "work that uses the
     319Library" must include any data and utility programs needed for
     320reproducing the executable from it.  However, as a special exception,
     321the materials to be distributed need not include anything that is
     322normally distributed (in either source or binary form) with the major
     323components (compiler, kernel, and so on) of the operating system on
     324which the executable runs, unless that component itself accompanies
     325the executable.
     326
     327  It may happen that this requirement contradicts the license
     328restrictions of other proprietary libraries that do not normally
     329accompany the operating system.  Such a contradiction means you cannot
     330use both them and the Library together in an executable that you
     331distribute.
     332
     333  7. You may place library facilities that are a work based on the
     334Library side-by-side in a single library together with other library
     335facilities not covered by this License, and distribute such a combined
     336library, provided that the separate distribution of the work based on
     337the Library and of the other library facilities is otherwise
     338permitted, and provided that you do these two things:
     339
     340    a) Accompany the combined library with a copy of the same work
     341    based on the Library, uncombined with any other library
     342    facilities.  This must be distributed under the terms of the
     343    Sections above.
     344
     345    b) Give prominent notice with the combined library of the fact
     346    that part of it is a work based on the Library, and explaining
     347    where to find the accompanying uncombined form of the same work.
     348
     349  8. You may not copy, modify, sublicense, link with, or distribute
     350the Library except as expressly provided under this License.  Any
     351attempt otherwise to copy, modify, sublicense, link with, or
     352distribute the Library is void, and will automatically terminate your
     353rights under this License.  However, parties who have received copies,
     354or rights, from you under this License will not have their licenses
     355terminated so long as such parties remain in full compliance.
     356
     357  9. You are not required to accept this License, since you have not
     358signed it.  However, nothing else grants you permission to modify or
     359distribute the Library or its derivative works.  These actions are
     360prohibited by law if you do not accept this License.  Therefore, by
     361modifying or distributing the Library (or any work based on the
     362Library), you indicate your acceptance of this License to do so, and
     363all its terms and conditions for copying, distributing or modifying
     364the Library or works based on it.
     365
     366  10. Each time you redistribute the Library (or any work based on the
     367Library), the recipient automatically receives a license from the
     368original licensor to copy, distribute, link with or modify the Library
     369subject to these terms and conditions.  You may not impose any further
     370restrictions on the recipients' exercise of the rights granted herein.
     371You are not responsible for enforcing compliance by third parties with
     372this License.
     373
     374  11. If, as a consequence of a court judgment or allegation of patent
     375infringement or for any other reason (not limited to patent issues),
     376conditions are imposed on you (whether by court order, agreement or
     377otherwise) that contradict the conditions of this License, they do not
     378excuse you from the conditions of this License.  If you cannot
     379distribute so as to satisfy simultaneously your obligations under this
     380License and any other pertinent obligations, then as a consequence you
     381may not distribute the Library at all.  For example, if a patent
     382license would not permit royalty-free redistribution of the Library by
     383all those who receive copies directly or indirectly through you, then
     384the only way you could satisfy both it and this License would be to
     385refrain entirely from distribution of the Library.
     386
     387If any portion of this section is held invalid or unenforceable under any
     388particular circumstance, the balance of the section is intended to apply,
     389and the section as a whole is intended to apply in other circumstances.
     390
     391It is not the purpose of this section to induce you to infringe any
     392patents or other property right claims or to contest validity of any
     393such claims; this section has the sole purpose of protecting the
     394integrity of the free software distribution system which is
     395implemented by public license practices.  Many people have made
     396generous contributions to the wide range of software distributed
     397through that system in reliance on consistent application of that
     398system; it is up to the author/donor to decide if he or she is willing
     399to distribute software through any other system and a licensee cannot
     400impose that choice.
     401
     402This section is intended to make thoroughly clear what is believed to
     403be a consequence of the rest of this License.
     404
     405  12. If the distribution and/or use of the Library is restricted in
     406certain countries either by patents or by copyrighted interfaces, the
     407original copyright holder who places the Library under this License may add
     408an explicit geographical distribution limitation excluding those countries,
     409so that distribution is permitted only in or among countries not thus
     410excluded.  In such case, this License incorporates the limitation as if
     411written in the body of this License.
     412
     413  13. The Free Software Foundation may publish revised and/or new
     414versions of the Lesser General Public License from time to time.
     415Such new versions will be similar in spirit to the present version,
     416but may differ in detail to address new problems or concerns.
     417
     418Each version is given a distinguishing version number.  If the Library
     419specifies a version number of this License which applies to it and
     420"any later version", you have the option of following the terms and
     421conditions either of that version or of any later version published by
     422the Free Software Foundation.  If the Library does not specify a
     423license version number, you may choose any version ever published by
     424the Free Software Foundation.
     425
     426  14. If you wish to incorporate parts of the Library into other free
     427programs whose distribution conditions are incompatible with these,
     428write to the author to ask for permission.  For software which is
     429copyrighted by the Free Software Foundation, write to the Free
     430Software Foundation; we sometimes make exceptions for this.  Our
     431decision will be guided by the two goals of preserving the free status
     432of all derivatives of our free software and of promoting the sharing
     433and reuse of software generally.
     434
     435                            NO WARRANTY
     436
     437  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
     438WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
     439EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
     440OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
     441KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
     442IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     443PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
     444LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
     445THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
     446
     447  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
     448WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
     449AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
     450FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
     451CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
     452LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
     453RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
     454FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
     455SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
     456DAMAGES.
     457
     458                     END OF TERMS AND CONDITIONS
     459
     460           How to Apply These Terms to Your New Libraries
     461
     462  If you develop a new library, and you want it to be of the greatest
     463possible use to the public, we recommend making it free software that
     464everyone can redistribute and change.  You can do so by permitting
     465redistribution under these terms (or, alternatively, under the terms of the
     466ordinary General Public License).
     467
     468  To apply these terms, attach the following notices to the library.  It is
     469safest to attach them to the start of each source file to most effectively
     470convey the exclusion of warranty; and each file should have at least the
     471"copyright" line and a pointer to where the full notice is found.
     472
     473    <one line to give the library's name and a brief idea of what it does.>
     474    Copyright (C) <year>  <name of author>
     475
     476    This library is free software; you can redistribute it and/or
     477    modify it under the terms of the GNU Lesser General Public
     478    License as published by the Free Software Foundation; either
     479    version 2.1 of the License, or (at your option) any later version.
     480
     481    This library is distributed in the hope that it will be useful,
     482    but WITHOUT ANY WARRANTY; without even the implied warranty of
     483    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     484    Lesser General Public License for more details.
     485
     486    You should have received a copy of the GNU Lesser General Public
     487    License along with this library; if not, write to the Free Software
     488    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
     489
     490Also add information on how to contact you by electronic and paper mail.
     491
     492You should also get your employer (if you work as a programmer) or your
     493school, if any, to sign a "copyright disclaimer" for the library, if
     494necessary.  Here is a sample; alter the names:
     495
     496  Yoyodyne, Inc., hereby disclaims all copyright interest in the
     497  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
     498
     499  <signature of Ty Coon>, 1 April 1990
     500  Ty Coon, President of Vice
     501
     502That's all there is to it!
     503
     504
  • new file src/wp-includes/PHPMailer/PHPMailerAutoload.php

    diff --git src/wp-includes/PHPMailer/PHPMailerAutoload.php src/wp-includes/PHPMailer/PHPMailerAutoload.php
    new file mode 100644
    index 0000000..46db5bd
    - +  
     1<?php
     2/**
     3 * PHPMailer SPL autoloader.
     4 * PHP Version 5.0.0
     5 * @package PHPMailer
     6 * @link https://github.com/PHPMailer/PHPMailer/
     7 * @author Marcus Bointon (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 2013 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 SPL autoloader.
     22 * @param string $classname The name of the class to load
     23 */
     24function PHPMailerAutoload($classname)
     25{
     26    //Can't use __DIR__ as it's only in PHP 5.3+
     27    $filename = dirname(__FILE__).DIRECTORY_SEPARATOR.'class.'.strtolower($classname).'.php';
     28    if (is_readable($filename)) {
     29        require $filename;
     30    }
     31}
     32
     33spl_autoload_register('PHPMailerAutoload');
  • new file src/wp-includes/PHPMailer/README.md

    diff --git src/wp-includes/PHPMailer/README.md src/wp-includes/PHPMailer/README.md
    new file mode 100644
    index 0000000..de76a76
    - +  
     1# PHPMailer - A full-featured email creation and transfer class for PHP
     2
     3Build status: [![Build Status](https://travis-ci.org/Synchro/PHPMailer.png)](https://travis-ci.org/Synchro/PHPMailer)
     4
     5## Class Features
     6
     7- Probably the world's most popular code for sending email from PHP!
     8- Used by many open-source projects: Drupal, SugarCRM, Yii, Joomla! and many more
     9- Integrated SMTP support - send without a local mail server
     10- send emails with multiple TOs, CCs, BCCs and REPLY-TOs
     11- Multipart/alternative emails for mail clients that do not read HTML email
     12- Support for 8bit, base64, binary, and quoted-printable encoding
     13- SMTP authentication with LOGIN, PLAIN, NTLM and CRAM-MD5 mechanisms
     14- Native language support
     15- Compatible with PHP 5.0 and later
     16- Much more!
     17
     18## Why you might need it
     19
     20Many PHP developers utilize email in their code. The only PHP function that supports this is the mail() function. However, it does not provide any assistance for making use of popular features such as HTML-based emails and attachments.
     21
     22Formatting email correctly is surprisingly difficult. There are myriad overlapping RFCs, requiring tight adherence to horribly complicated formatting and encoding rules - the vast majority of code that you'll find online that uses the mail() function directly is just plain wrong!
     23*Please* don't be tempted to do it yourself - if you don't use PHPMailer, there are many other excellent libraries that you should look at before rolling your own - try SwiftMailer, Zend_Mail, eZcomponents etc.
     24
     25The PHP mail() function usually sends via a local mail server, typically fronted by a `sendmail` binary on Linux, BSD and OS X platforms, however, Windows usually doesn't include a local mail server; PHPMailer's integrated SMTP implementation allows email sending on Windows platforms without a local mail server.
     26
     27## License
     28
     29This software is licenced under the [LGPL 2.1](http://www.gnu.org/licenses/lgpl-2.1.html). Please read LICENSE for information on the
     30software availability and distribution.
     31
     32## Installation
     33
     34PHPMailer is available via [Composer/Packagist](https://packagist.org/packages/phpmailer/phpmailer). Alternatively, just copy the contents of the PHPMailer folder into somewhere that's in your PHP `include_path` setting. If you don't speak git or just want a tarball, click the 'zip' button at the top of the page in GitHub.
     35
     36
     37## A Simple Example
     38
     39```php
     40<?php
     41require 'class.phpmailer.php';
     42
     43$mail = new PHPMailer;
     44
     45$mail->isSMTP();                                      // Set mailer to use SMTP
     46$mail->Host = 'smtp1.example.com;smtp2.example.com';  // Specify main and backup server
     47$mail->SMTPAuth = true;                               // Enable SMTP authentication
     48$mail->Username = 'jswan';                            // SMTP username
     49$mail->Password = 'secret';                           // SMTP password
     50$mail->SMTPSecure = 'tls';                            // Enable encryption, 'ssl' also accepted
     51
     52$mail->From = 'from@example.com';
     53$mail->FromName = 'Mailer';
     54$mail->addAddress('josh@example.net', 'Josh Adams');  // Add a recipient
     55$mail->addAddress('ellen@example.com');               // Name is optional
     56$mail->addReplyTo('info@example.com', 'Information');
     57$mail->addCC('cc@example.com');
     58$mail->addBCC('bcc@example.com');
     59
     60$mail->WordWrap = 50;                                 // Set word wrap to 50 characters
     61$mail->addAttachment('/var/tmp/file.tar.gz');         // Add attachments
     62$mail->addAttachment('/tmp/image.jpg', 'new.jpg');    // Optional name
     63$mail->isHTML(true);                                  // Set email format to HTML
     64
     65$mail->Subject = 'Here is the subject';
     66$mail->Body    = 'This is the HTML message body <b>in bold!</b>';
     67$mail->AltBody = 'This is the body in plain text for non-HTML mail clients';
     68
     69if(!$mail->send()) {
     70   echo 'Message could not be sent.';
     71   echo 'Mailer Error: ' . $mail->ErrorInfo;
     72   exit;
     73}
     74
     75echo 'Message has been sent';
     76```
     77
     78You'll find plenty more to play with in the `examples` folder.
     79
     80That's it. You should now be ready to use PHPMailer!
     81
     82## Localization
     83PHPMailer defaults to English, but in the `languages` folder you'll find numerous translations for PHPMailer error messages that you may encounter. Their filenames contain [ISO 639-1](http://en.wikipedia.org/wiki/ISO_639-1) language code for the translations, for example `fr` for French. To specify a language, you need to tell PHPMailer which one to use, like this:
     84
     85```php
     86// To load the French version
     87$mail->setLanguage('fr', '/optional/path/to/language/directory/');
     88```
     89
     90## Documentation
     91
     92You'll find some basic user-level docs in the docs folder, and you can generate complete API-level documentation using the `generatedocs.sh` shell script in the docs folder, though you'll need to install [PHPDocumentor](http://www.phpdoc.org) first.
     93
     94## Tests
     95
     96You'll find a PHPUnit test script in the `test` folder.
     97
     98Build status: [![Build Status](https://travis-ci.org/PHPMailer/PHPMailer.png)](https://travis-ci.org/PHPMailer/PHPMailer)
     99
     100If this isn't passing, is there something you can do to help?
     101
     102## Contributing
     103
     104Please submit bug reports, suggestions and pull requests to the [GitHub issue tracker](https://github.com/PHPMailer/PHPMailer/issues).
     105
     106We're particularly interested in fixing edge-cases, expanding test coverage and updating translations.
     107
     108With the move to the PHPMailer GitHub organisation, you'll need to update any remote URLs referencing the old GitHub location with a command like this from within your clone:
     109
     110`git remote set-url upstream https://github.com/PHPMailer/PHPMailer.git`
     111
     112Please *don't* use the SourceForge or Google Code projects any more.
     113
     114## Changelog
     115
     116See [changelog](changelog.md).
     117
     118## History
     119- PHPMailer was originally written in 2001 by Brent R. Matzelle as a [SourceForge project](http://sourceforge.net/projects/phpmailer/).
     120- Marcus Bointon (coolbru on SF) and Andy Prevost (codeworxtech) took over the project in 2004.
     121- Became an Apache incubator project on Google Code in 2010, managed by Jim Jagielski.
     122- Marcus created his fork on [GitHub](https://github.com/Synchro/PHPMailer).
     123- Jim and Marcus decide to join forces and use GitHub as the canonical and official repo for PHPMailer.
     124- PHPMailer moves to the [PHPMailer organisation](https://github.com/PHPMailer) on GitHub.
     125
     126### What's changed since moving from SourceForge?
     127- Official successor to the SourceForge and Google Code projects.
     128- Test suite.
     129- Continuous integration with Travis-CI.
     130- Composer support.
     131- Rolling releases.
     132- Additional languages and language strings.
     133- CRAM-MD5 authentication support.
     134- Preserves full repo history of authors, commits and branches from the original SourceForge project.
  • new file src/wp-includes/PHPMailer/changelog.md

    diff --git src/wp-includes/PHPMailer/changelog.md src/wp-includes/PHPMailer/changelog.md
    new file mode 100644
    index 0000000..4caa777
    - +  
     1# ChangeLog
     2
     3## Version 5.2.7 (September 12th 2013)
     4* Add Ukranian translation from @Krezalis
     5* Support for do_verp
     6* Fix bug in CRAM-MD5 AUTH
     7* Propagate Debugoutput option to SMTP class (@Reblutus)
     8* Determine MIME type of attachments automatically
     9* Add cross-platform, multibyte-safe pathinfo replacement (with tests) and use it
     10* Add a new 'html' Debugoutput type
     11* Clean up SMTP debug output, remove embedded HTML
     12* Some small changes in header formatting to improve IETF msglint test results
     13* Update test_script to use some recently changed features, rename to code_generator
     14* Generated code actually works!
     15* Update SyntaxHighlighter
     16* Major overhaul and cleanup of example code
     17* New PHPMailer graphic
     18* msgHTML now uses RFC2392-compliant content ids
     19* Add line break normalization function and use it in msgHTML
     20* Don't set unnecessary reply-to addresses
     21* Make fakesendmail.sh a bit cleaner and safer
     22* Set a content-transfer-encoding on multiparts (fixes msglint error)
     23* Fix cid generation in msgHTML (Thanks to @digitalthought)
     24* Fix handling of multiple SMTP servers (Thanks to @NanoCaiordo)
     25* SMTP->connect() now supports stream context options (Thanks to @stanislavdavid)
     26* Add support for iCal event alternatives (Thanks to @reblutus)
     27* Update to Polish language file (Thanks to Krzysztof Kowalewski)
     28* Update to Norwegian language file (Thanks to @datagutten)
     29* Update to Hungarian language file (Thanks to @dominicus-75)
     30* Add Persian/Farsi translation from @jaii
     31* Make SMTPDebug property type match type in SMTP class
     32* Add unit tests for DKIM
     33* Major refactor of SMTP class
     34* Reformat to PSR-2 coding standard
     35* Introduce autoloader
     36* Allow overriding of SMTP class
     37* Overhaul of PHPDocs
     38* Fix broken Q-encoding
     39* Czech language update (Thanks to @nemelu)
     40* Removal of excess blank lines in messages
     41* Added fake POP server and unit tests for POP-before-SMTP
     42
     43## Version 5.2.6 (April 11th 2013)
     44* Reflect move to PHPMailer GitHub organisation at https://github.com/PHPMailer/PHPMailer
     45* Fix unbumped version numbers
     46* Update packagist.org with new location
     47* Clean up Changelog
     48
     49## Version 5.2.5 (April 6th 2013)
     50* First official release after move from Google Code
     51* Fixes for qmail when sending via mail()
     52* Merge in changes from Google code 5.2.4 release
     53* Minor coding standards cleanup in SMTP class
     54* Improved unit tests, now tests S/MIME signing
     55* Travis-CI support on GitHub, runs tests with fake SMTP server
     56
     57## Version 5.2.4 (February 19, 2013)
     58* Fix tag and version bug.
     59* un-deprecate isSMTP(), isMail(), IsSendmail() and isQmail().
     60* Numerous translation updates
     61
     62## Version 5.2.3 (February 8, 2013)
     63* Fix issue with older PCREs and ValidateAddress() (Bugz: 124)
     64* Add CRAM-MD5 authentication, thanks to Elijah madden, https://github.com/okonomiyaki3000
     65* Replacement of obsolete Quoted-Printable encoder with a much better implementation
     66* Composer package definition
     67* New language added: Hebrew
     68
     69## Version 5.2.2 (December 3, 2012)
     70* Some fixes and syncs from https://github.com/Synchro/PHPMailer
     71* Add Slovak translation, thanks to Michal Tinka
     72
     73## Version 5.2.2-rc2 (November 6, 2012)
     74* Fix SMTP server rotation (Bugz: 118)
     75* Allow override of autogen'ed 'Date' header (for Drupal's
     76  og_mailinglist module)
     77* No whitespace after '-f' option (Bugz: 116)
     78* Work around potential warning (Bugz: 114)
     79
     80## Version 5.2.2-rc1 (September 28, 2012)
     81* Header encoding works with long lines (Bugz: 93)
     82* Turkish language update (Bugz: 94)
     83* undefined $pattern in EncodeQ bug squashed (Bugz: 98)
     84* use of mail() in safe_mode now works (Bugz: 96)
     85* ValidateAddress() now 'public static' so people can override the
     86  default and use their own validation scheme.
     87* ValidateAddress() no longer uses broken FILTER_VALIDATE_EMAIL
     88* Added in AUTH PLAIN SMTP authentication
     89
     90## Version 5.2.2-beta2 (August 17, 2012)
     91* Fixed Postfix VERP support (Bugz: 92)
     92* Allow action_function callbacks to pass/use
     93  the From address (passed as final param)
     94* Prevent inf look for get_lines() (Bugz: 77)
     95* New public var ($UseSendmailOptions). Only pass sendmail()
     96  options iff we really are using sendmail or something sendmail
     97  compatible. (Bugz: 75)
     98* default setting for LE returned to "\n" due to popular demand.
     99
     100## Version 5.2.2-beta1 (July 13, 2012)
     101* Expose PreSend() and PostSend() as public methods to allow
     102  for more control if serializing message sending.
     103* GetSentMIMEMessage() only constructs the message copy when
     104 needed. Save memory.
     105* Only pass params to mail() if the underlying MTA is
     106  "sendmail" (as defined as "having the string sendmail
     107  in its pathname") [#69]
     108* Attachments now work with Amazon SES and others [Bugz#70]
     109* Debug output now sent to stdout (via echo) or error_log [Bugz#5]
     110* New var: Debugoutput (for above) [Bugz#5]
     111* SMTP reads now Timeout aware (new var: Timeout=15) [Bugz#71]
     112* SMTP reads now can have a Timelimit associated with them
     113  (new var: Timelimit=30)[Bugz#71]
     114* Fix quoting issue associated with charsets
     115* default setting for LE is now RFC compliant: "\r\n"
     116* Return-Path can now be user defined (new var: ReturnPath)
     117  (the default is "" which implies no change from previous
     118  behavior, which was to use either From or Sender) [Bugz#46]
     119* X-Mailer header can now be disabled (by setting to a
     120  whitespace string, eg "  ") [Bugz#66]
     121* Bugz closed: #68, #60, #42, #43, #59, #55, #66, #48, #49,
     122               #52, #31, #41, #5. #70, #69
     123
     124## Version 5.2.1 (January 16, 2012)
     125* Closed several bugs#5
     126* Performance improvements
     127* MsgHTML() now returns the message as required.
     128* New method: GetSentMIMEMessage() (returns full copy of sent message)
     129
     130## Version 5.2 (July 19, 2011)
     131* protected MIME body and header
     132* better DKIM DNS Resource Record support
     133* better aly handling
     134* htmlfilter class added to extras
     135* moved to Apache Extras
     136
     137## Version 5.1 (October 20, 2009)
     138* fixed filename issue with AddStringAttachment (thanks to Tony)
     139* fixed "SingleTo" property, now works with Senmail, Qmail, and SMTP in
     140  addition to PHP mail()
     141* added DKIM digital signing functionality, new properties:
     142  - DKIM_domain (sets the domain name)
     143  - DKIM_private (holds DKIM private key)
     144  - DKIM_passphrase (holds your DKIM passphrase)
     145  - DKIM_selector (holds the DKIM "selector")
     146  - DKIM_identity (holds the identifying email address)
     147* added callback function support
     148  - callback function parameters include:
     149    result, to, cc, bcc, subject and body
     150  - see the test/test_callback.php file for usage.
     151* added "auto" identity functionality
     152  - can automatically add:
     153    - Return-path (if Sender not set)
     154    - Reply-To (if ReplyTo not set)
     155  - can be disabled:
     156    - $mail->SetFrom('yourname@yourdomain.com','First Last',false);
     157    - or by adding the $mail->Sender and/or $mail->ReplyTo properties
     158
     159Note: "auto" identity added to help with emails ending up in spam or junk boxes because of missing headers
     160
     161## Version 5.0.2 (May 24, 2009)
     162* Fix for missing attachments when inline graphics are present
     163* Fix for missing Cc in header when using SMTP (mail was sent,
     164  but not displayed in header -- Cc receiver only saw email To:
     165  line and no Cc line, but did get the email (To receiver
     166  saw same)
     167
     168## Version 5.0.1 (April 05, 2009)
     169* Temporary fix for missing attachments
     170
     171## Version 5.0.0 (April 02, 2009)
     172With the release of this version, we are initiating a new version numbering
     173system to differentiate from the PHP4 version of PHPMailer.
     174Most notable in this release is fully object oriented code.
     175
     176### class.smtp.php:
     177* Refactored class.smtp.php to support new exception handling
     178* code size reduced from 29.2 Kb to 25.6 Kb
     179* Removed unnecessary functions from class.smtp.php:
     180  - public function Expand($name) {
     181  - public function Help($keyword="") {
     182  - public function Noop() {
     183  - public function Send($from) {
     184  - public function SendOrMail($from) {
     185  - public function Verify($name) {
     186
     187###  class.phpmailer.php:
     188* Refactored class.phpmailer.php with new exception handling
     189* Changed processing functionality of Sendmail and Qmail so they cannot be
     190  inadvertently used
     191* removed getFile() function, just became a simple wrapper for
     192  file_get_contents()
     193* added check for PHP version (will gracefully exit if not at least PHP 5.0)
     194* enhanced code to check if an attachment source is the same as an embedded or
     195  inline graphic source to eliminate duplicate attachments
     196
     197### New /test_script
     198We have written a test script you can use to test the script as part of your
     199installation. Once you press submit, the test script will send a multi-mime
     200email with either the message you type in or an HTML email with an inline
     201graphic. Two attachments are included in the email (one of the attachments
     202is also the inline graphic so you can see that only one copy of the graphic
     203is sent in the email). The test script will also display the functional
     204script that you can copy/paste to your editor to duplicate the functionality.
     205
     206### New examples
     207All new examples in both basic and advanced modes. Advanced examples show
     208   Exception handling.
     209
     210### PHPDocumentator (phpdocs) documentation for PHPMailer version 5.0.0
     211All new documentation
     212
     213## Version 2.3 (November 06, 2008)
     214* added Arabic language (many thanks to Bahjat Al Mostafa)
     215* removed English language from language files and made it a default within
     216  class.phpmailer.php - if no language is found, it will default to use
     217  the english language translation
     218* fixed public/private declarations
     219* corrected line 1728, $basedir to $directory
     220* added $sign_cert_file to avoid improper duplicate use of $sign_key_file
     221* corrected $this->Hello on line 612 to $this->Helo
     222* changed default of $LE to "\r\n" to comply with RFC 2822. Can be set by the user
     223  if default is not acceptable
     224* removed trim() from return results in EncodeQP
     225* /test and three files it contained are removed from version 2.3
     226* fixed phpunit.php for compliance with PHP5
     227* changed $this->AltBody = $textMsg; to $this->AltBody = html_entity_decode($textMsg);
     228* We have removed the /phpdoc from the downloads. All documentation is now on
     229  the http://phpmailer.codeworxtech.com website.
     230
     231## Version 2.2.1 () July 19 2008
     232* fixed line 1092 in class.smtp.php (my apologies, error on my part)
     233
     234## Version 2.2 () July 15 2008
     235* Fixed redirect issue (display of UTF-8 in thank you redirect)
     236* fixed error in getResponse function declaration (class.pop3.php)
     237* PHPMailer now PHP6 compliant
     238* fixed line 1092 in class.smtp.php (endless loop from missing = sign)
     239
     240## Version 2.1 (Wed, June 04 2008)
     241NOTE: WE HAVE A NEW LANGUAGE VARIABLE FOR DIGITALLY SIGNED S/MIME EMAILS. IF YOU CAN HELP WITH LANGUAGES OTHER THAN ENGLISH AND SPANISH, IT WOULD BE APPRECIATED.
     242
     243* added S/MIME functionality (ability to digitally sign emails)
     244  BIG THANKS TO "sergiocambra" for posting this patch back in November 2007.
     245  The "Signed Emails" functionality adds the Sign method to pass the private key
     246  filename and the password to read it, and then email will be sent with
     247  content-type multipart/signed and with the digital signature attached.
     248* fully compatible with E_STRICT error level
     249  - Please note:
     250    In about half the test environments this development version was subjected
     251    to, an error was thrown for the date() functions used (line 1565 and 1569).
     252    This is NOT a PHPMailer error, it is the result of an incorrectly configured
     253    PHP5 installation. The fix is to modify your 'php.ini' file and include the
     254    date.timezone = America/New York
     255    directive, to your own server timezone
     256  - If you do get this error, and are unable to access your php.ini file:
     257    In your PHP script, add
     258    `date_default_timezone_set('America/Toronto');`
     259  - do not try to use
     260    `$myVar = date_default_timezone_get();`
     261    as a test, it will throw an error.
     262* added ability to define path (mainly for embedded images)
     263  function `MsgHTML($message,$basedir='')` ... where:
     264  `$basedir` is the fully qualified path
     265* fixed `MsgHTML()` function:
     266  - Embedded Images where images are specified by `<protocol>://` will not be altered or embedded
     267* fixed the return value of SMTP exit code ( pclose )
     268* addressed issue of multibyte characters in subject line and truncating
     269* added ability to have user specified Message ID
     270  (default is still that PHPMailer create a unique Message ID)
     271* corrected unidentified message type to 'application/octet-stream'
     272* fixed chunk_split() multibyte issue (thanks to Colin Brown, et al).
     273* added check for added attachments
     274* enhanced conversion of HTML to text in MsgHTML (thanks to "brunny")
     275
     276## Version 2.1.0beta2 (Sun, Dec 02 2007)
     277* implemented updated EncodeQP (thanks to coolbru, aka Marcus Bointon)
     278* finished all testing, all known bugs corrected, enhancements tested
     279
     280Note: will NOT work with PHP4.
     281
     282Please note, this is BETA software **DO NOT USE THIS IN PRODUCTION OR LIVE PROJECTS; INTENDED STRICTLY FOR TESTING**
     283
     284## Version 2.1.0beta1
     285Please note, this is BETA software
     286** DO NOT USE THIS IN PRODUCTION OR LIVE PROJECTS
     287 INTENDED STRICTLY FOR TESTING
     288
     289## Version 2.0.0 rc2 (Fri, Nov 16 2007), interim release
     290* implements new property to control VERP in class.smtp.php
     291  example (requires instantiating class.smtp.php):
     292  $mail->do_verp = true;
     293* POP-before-SMTP functionality included, thanks to Richard Davey
     294  (see class.pop3.php & pop3_before_smtp_test.php for examples)
     295* included example showing how to use PHPMailer with GMAIL
     296* fixed the missing Cc in SendMail() and Mail()
     297
     298******************
     299A note on sending bulk emails:
     300
     301If the email you are sending is not personalized, consider using the
     302"undisclosed-recipient:;" strategy. That is, put all of your recipients
     303in the Bcc field and set the To field to "undisclosed-recipients:;".
     304It's a lot faster (only one send) and saves quite a bit on resources.
     305Contrary to some opinions, this will not get you listed in spam engines -
     306it's a legitimate way for you to send emails.
     307
     308A partial example for use with PHPMailer:
     309
     310```
     311$mail->AddAddress("undisclosed-recipients:;");
     312$mail->AddBCC("email1@anydomain.com,email2@anyotherdomain.com,email3@anyalternatedomain.com");
     313```
     314
     315Many email service providers restrict the number of emails that can be sent
     316in any given time period. Often that is between 50 - 60 emails maximum
     317per hour or per send session.
     318
     319If that's the case, then break up your Bcc lists into chunks that are one
     320less than your limit, and put a pause in your script.
     321*******************
     322
     323## Version 2.0.0 rc1 (Thu, Nov 08 2007), interim release
     324* dramatically simplified using inline graphics ... it's fully automated and requires no user input
     325* added automatic document type detection for attachments and pictures
     326* added MsgHTML() function to replace Body tag for HTML emails
     327* fixed the SendMail security issues (input validation vulnerability)
     328* enhanced the AddAddresses functionality so that the "Name" portion is used in the email address
     329* removed the need to use the AltBody method (set from the HTML, or default text used)
     330* set the PHP Mail() function as the default (still support SendMail, SMTP Mail)
     331* removed the need to set the IsHTML property (set automatically)
     332* added Estonian language file by Indrek P&auml;ri
     333* added header injection patch
     334* added "set" method to permit users to create their own pseudo-properties like 'X-Headers', etc.
     335  example of use:
     336
     337```
     338$mail->set('X-Priority', '3');
     339$mail->set('X-MSMail-Priority', 'Normal');
     340```
     341
     342* fixed warning message in SMTP get_lines method
     343* added TLS/SSL SMTP support. Example of use:
     344
     345```
     346$mail = new PHPMailer();
     347$mail->Mailer = "smtp";
     348$mail->Host = "smtp.example.com";
     349$mail->SMTPSecure   = "tls"; // option
     350//$mail->SMTPSecure   = "ssl";  // option
     351...
     352$mail->Send();
     353```
     354
     355* PHPMailer has been tested with PHP4 (4.4.7) and PHP5 (5.2.7)
     356* Works with PHP installed as a module or as CGI-PHP
     357NOTE: will NOT work with PHP5 in E_STRICT error mode
     358
     359## Version 1.73 (Sun, Jun 10 2005)
     360* Fixed denial of service bug: http://www.cybsec.com/vuln/PHPMailer-DOS.pdf
     361* Now has a total of 20 translations
     362* Fixed alt attachments bug: http://tinyurl.com/98u9k
     363
     364## Version 1.72 (Wed, May 25 2004)
     365* Added Dutch, Swedish, Czech, Norwegian, and Turkish translations.
     366* Received: Removed this method because spam filter programs like
     367  SpamAssassin reject this header.
     368* Fixed error count bug.
     369* SetLanguage default is now "language/".
     370* Fixed magic_quotes_runtime bug.
     371
     372## Version 1.71 (Tue, Jul 28 2003)
     373* Made several speed enhancements
     374* Added German and Italian translation files
     375* Fixed HELO/AUTH bugs on keep-alive connects
     376* Now provides an error message if language file does not load
     377* Fixed attachment EOL bug
     378* Updated some unclear documentation
     379* Added additional tests and improved others
     380
     381## Version 1.70 (Mon, Jun 20 2003)
     382* Added SMTP keep-alive support
     383* Added IsError method for error detection
     384* Added error message translation support (SetLanguage)
     385* Refactored many methods to increase library performance
     386* Hello now sends the newer EHLO message before HELO as per RFC 2821
     387* Removed the boundary class and replaced it with GetBoundary
     388* Removed queue support methods
     389* New $Hostname variable
     390* New Message-ID header
     391* Received header reformat
     392* Helo variable default changed to $Hostname
     393* Removed extra spaces in Content-Type definition (#667182)
     394* Return-Path should be set to Sender when set
     395* Adds Q or B encoding to headers when necessary
     396* quoted-encoding should now encode NULs \000
     397* Fixed encoding of body/AltBody (#553370)
     398* Adds "To: undisclosed-recipients:;" when all recipients are hidden (BCC)
     399* Multiple bug fixes
     400
     401## Version 1.65 (Fri, Aug 09 2002)
     402* Fixed non-visible attachment bug (#585097) for Outlook
     403* SMTP connections are now closed after each transaction
     404* Fixed SMTP::Expand return value
     405* Converted SMTP class documentation to phpDocumentor format
     406
     407## Version 1.62 (Wed, Jun 26 2002)
     408* Fixed multi-attach bug
     409* Set proper word wrapping
     410* Reduced memory use with attachments
     411* Added more debugging
     412* Changed documentation to phpDocumentor format
     413
     414## Version 1.60 (Sat, Mar 30 2002)
     415* Sendmail pipe and address patch (Christian Holtje)
     416* Added embedded image and read confirmation support (A. Ognio)
     417* Added unit tests
     418* Added SMTP timeout support (*nix only)
     419* Added possibly temporary PluginDir variable for SMTP class
     420* Added LE message line ending variable
     421* Refactored boundary and attachment code
     422* Eliminated SMTP class warnings
     423* Added SendToQueue method for future queuing support
     424
     425## Version 1.54 (Wed, Dec 19 2001)
     426* Add some queuing support code
     427* Fixed a pesky multi/alt bug
     428* Messages are no longer forced to have "To" addresses
     429
     430## Version 1.50 (Thu, Nov 08 2001)
     431* Fix extra lines when not using SMTP mailer
     432* Set WordWrap variable to int with a zero default
     433
     434## Version 1.47 (Tue, Oct 16 2001)
     435* Fixed Received header code format
     436* Fixed AltBody order error
     437* Fixed alternate port warning
     438
     439## Version 1.45 (Tue, Sep 25 2001)
     440* Added enhanced SMTP debug support
     441* Added support for multiple ports on SMTP
     442* Added Received header for tracing
     443* Fixed AddStringAttachment encoding
     444* Fixed possible header name quote bug
     445* Fixed wordwrap() trim bug
     446* Couple other small bug fixes
     447
     448## Version 1.41 (Wed, Aug 22 2001)
     449* Fixed AltBody bug w/o attachments
     450* Fixed rfc_date() for certain mail servers
     451
     452## Version 1.40 (Sun, Aug 12 2001)
     453* Added multipart/alternative support (AltBody)
     454* Documentation update
     455* Fixed bug in Mercury MTA
     456
     457## Version 1.29 (Fri, Aug 03 2001)
     458* Added AddStringAttachment() method
     459* Added SMTP authentication support
     460
     461## Version 1.28 (Mon, Jul 30 2001)
     462* Fixed a typo in SMTP class
     463* Fixed header issue with Imail (win32) SMTP server
     464* Made fopen() calls for attachments use "rb" to fix win32 error
     465
     466## Version 1.25 (Mon, Jul 02 2001)
     467* Added RFC 822 date fix (Patrice)
     468* Added improved error handling by adding a $ErrorInfo variable
     469* Removed MailerDebug variable (obsolete with new error handler)
     470
     471## Version 1.20 (Mon, Jun 25 2001)
     472* Added quoted-printable encoding (Patrice)
     473* Set Version as public and removed PrintVersion()
     474* Changed phpdoc to only display public variables and methods
     475
     476## Version 1.19 (Thu, Jun 21 2001)
     477* Fixed MS Mail header bug
     478* Added fix for Bcc problem with mail(). *Does not work on Win32*
     479  (See PHP bug report: http://www.php.net/bugs.php?id=11616)
     480* mail() no longer passes a fifth parameter when not needed
     481
     482## Version 1.15 (Fri, Jun 15 2001)
     483Note: these changes contributed by Patrice Fournier
     484* Changed all remaining \n to \r\n
     485* Bcc: header no longer writen to message except
     486  when sent directly to sendmail
     487* Added a small message to non-MIME compliant mail reader
     488* Added Sender variable to change the Sender email
     489  used in -f for sendmail/mail and in 'MAIL FROM' for smtp mode
     490* Changed boundary setting to a place it will be set only once
     491* Removed transfer encoding for whole message when using multipart
     492* Message body now uses Encoding in multipart messages
     493* Can set encoding and type to attachments 7bit, 8bit
     494  and binary attachment are sent as is, base64 are encoded
     495* Can set Encoding to base64 to send 8 bits body
     496  through 7 bits servers
     497
     498## Version 1.10 (Tue, Jun 12 2001)
     499* Fixed win32 mail header bug (printed out headers in message body)
     500
     501## Version 1.09 (Fri, Jun 08 2001)
     502* Changed date header to work with Netscape mail programs
     503* Altered phpdoc documentation
     504
     505## Version 1.08 (Tue, Jun 05 2001)
     506* Added enhanced error-checking
     507* Added phpdoc documentation to source
     508
     509## Version 1.06 (Fri, Jun 01 2001)
     510* Added optional name for file attachments
     511
     512## Version 1.05 (Tue, May 29 2001)
     513* Code cleanup
     514* Eliminated sendmail header warning message
     515* Fixed possible SMTP error
     516
     517## Version 1.03 (Thu, May 24 2001)
     518* Fixed problem where qmail sends out duplicate messages
     519
     520## Version 1.02 (Wed, May 23 2001)
     521* Added multiple recipient and attachment Clear* methods
     522* Added Sendmail public variable
     523* Fixed problem with loading SMTP library multiple times
     524
     525## Version 0.98 (Tue, May 22 2001)
     526* Fixed problem with redundant mail hosts sending out multiple messages
     527* Added additional error handler code
     528* Added AddCustomHeader() function
     529* Added support for Microsoft mail client headers (affects priority)
     530* Fixed small bug with Mailer variable
     531* Added PrintVersion() function
     532
     533## Version 0.92 (Tue, May 15 2001)
     534* Changed file names to class.phpmailer.php and class.smtp.php to match
     535  current PHP class trend.
     536* Fixed problem where body not being printed when a message is attached
     537* Several small bug fixes
     538
     539## Version 0.90 (Tue, April 17 2001)
     540* Initial public release
  • new file src/wp-includes/PHPMailer/class.phpmailer.php

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

    diff --git src/wp-includes/PHPMailer/class.pop3.php src/wp-includes/PHPMailer/class.pop3.php
    new file mode 100644
    index 0000000..042b93a
    - +  
     1<?php
     2/**
     3 * PHPMailer POP-Before-SMTP Authentication Class.
     4 * PHP Version 5.0.0
     5 * Version 5.2.7
     6 * @package PHPMailer
     7 * @link https://github.com/PHPMailer/PHPMailer/
     8 * @author Marcus Bointon (coolbru) <phpmailer@synchromedia.co.uk>
     9 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
     10 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
     11 * @author Brent R. Matzelle (original founder)
     12 * @copyright 2013 Marcus Bointon
     13 * @copyright 2010 - 2012 Jim Jagielski
     14 * @copyright 2004 - 2009 Andy Prevost
     15 * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
     16 * @note This program is distributed in the hope that it will be useful - WITHOUT
     17 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
     18 * FITNESS FOR A PARTICULAR PURPOSE.
     19 */
     20
     21/**
     22 * PHPMailer POP-Before-SMTP Authentication Class.
     23 * Specifically for PHPMailer to use for RFC1939 POP-before-SMTP authentication.
     24 * Does not support APOP.
     25 * @package PHPMailer
     26 * @author Richard Davey (original author) <rich@corephp.co.uk>
     27 * @author Marcus Bointon (coolbru) <phpmailer@synchromedia.co.uk>
     28 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
     29 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
     30 */
     31
     32class POP3
     33{
     34    /**
     35     * The POP3 PHPMailer Version number.
     36     * @type string
     37     * @access public
     38     */
     39    public $Version = '5.2.7';
     40
     41    /**
     42     * Default POP3 port number.
     43     * @type int
     44     * @access public
     45     */
     46    public $POP3_PORT = 110;
     47
     48    /**
     49     * Default timeout in seconds.
     50     * @type int
     51     * @access public
     52     */
     53    public $POP3_TIMEOUT = 30;
     54
     55    /**
     56     * POP3 Carriage Return + Line Feed.
     57     * @type string
     58     * @access public
     59     * @deprecated Use the constant instead
     60     */
     61    public $CRLF = "\r\n";
     62
     63    /**
     64     * Debug display level.
     65     * Options: 0 = no, 1+ = yes
     66     * @type int
     67     * @access public
     68     */
     69    public $do_debug = 0;
     70
     71    /**
     72     * POP3 mail server hostname.
     73     * @type string
     74     * @access public
     75     */
     76    public $host;
     77
     78    /**
     79     * POP3 port number.
     80     * @type int
     81     * @access public
     82     */
     83    public $port;
     84
     85    /**
     86     * POP3 Timeout Value in seconds.
     87     * @type int
     88     * @access public
     89     */
     90    public $tval;
     91
     92    /**
     93     * POP3 username
     94     * @type string
     95     * @access public
     96     */
     97    public $username;
     98
     99    /**
     100     * POP3 password.
     101     * @type string
     102     * @access public
     103     */
     104    public $password;
     105
     106    /**
     107     * Resource handle for the POP3 connection socket.
     108     * @type resource
     109     * @access private
     110     */
     111    private $pop_conn;
     112
     113    /**
     114     * Are we connected?
     115     * @type bool
     116     * @access private
     117     */
     118    private $connected;
     119
     120    /**
     121     * Error container.
     122     * @type array
     123     * @access private
     124     */
     125    private $error;
     126
     127    /**
     128     * Line break constant
     129     */
     130    const CRLF = "\r\n";
     131
     132    /**
     133     * Constructor.
     134     * @access public
     135     */
     136    public function __construct()
     137    {
     138        $this->pop_conn = 0;
     139        $this->connected = false;
     140        $this->error = null;
     141    }
     142
     143    /**
     144     * Simple static wrapper for all-in-one POP before SMTP
     145     * @param $host
     146     * @param bool $port
     147     * @param bool $tval
     148     * @param string $username
     149     * @param string $password
     150     * @param int $debug_level
     151     * @return bool
     152     */
     153    public static function popBeforeSmtp(
     154        $host,
     155        $port = false,
     156        $tval = false,
     157        $username = '',
     158        $password = '',
     159        $debug_level = 0
     160    ) {
     161        $pop = new POP3;
     162        return $pop->authorise($host, $port, $tval, $username, $password, $debug_level);
     163    }
     164
     165    /**
     166     * Authenticate with a POP3 server.
     167     * A connect, login, disconnect sequence
     168     * appropriate for POP-before SMTP authorisation.
     169     * @access public
     170     * @param string $host
     171     * @param bool|int $port
     172     * @param bool|int $tval
     173     * @param string $username
     174     * @param string $password
     175     * @param int $debug_level
     176     * @return bool
     177     */
     178    public function authorise($host, $port = false, $tval = false, $username = '', $password = '', $debug_level = 0)
     179    {
     180        $this->host = $host;
     181        // If no port value provided, use default
     182        if ($port === false) {
     183            $this->port = $this->POP3_PORT;
     184        } else {
     185            $this->port = $port;
     186        }
     187        // If no timeout value provided, use default
     188        if ($tval === false) {
     189            $this->tval = $this->POP3_TIMEOUT;
     190        } else {
     191            $this->tval = $tval;
     192        }
     193        $this->do_debug = $debug_level;
     194        $this->username = $username;
     195        $this->password = $password;
     196        //  Refresh the error log
     197        $this->error = null;
     198        //  connect
     199        $result = $this->connect($this->host, $this->port, $this->tval);
     200        if ($result) {
     201            $login_result = $this->login($this->username, $this->password);
     202            if ($login_result) {
     203                $this->disconnect();
     204                return true;
     205            }
     206        }
     207        // We need to disconnect regardless of whether the login succeeded
     208        $this->disconnect();
     209        return false;
     210    }
     211
     212    /**
     213     * Connect to a POP3 server.
     214     * @access public
     215     * @param string $host
     216     * @param bool|int $port
     217     * @param integer $tval
     218     * @return boolean
     219     */
     220    public function connect($host, $port = false, $tval = 30)
     221    {
     222        //  Are we already connected?
     223        if ($this->connected) {
     224            return true;
     225        }
     226
     227        //On Windows this will raise a PHP Warning error if the hostname doesn't exist.
     228        //Rather than suppress it with @fsockopen, capture it cleanly instead
     229        set_error_handler(array($this, 'catchWarning'));
     230
     231        //  connect to the POP3 server
     232        $this->pop_conn = fsockopen(
     233            $host, //  POP3 Host
     234            $port, //  Port #
     235            $errno, //  Error Number
     236            $errstr, //  Error Message
     237            $tval
     238        ); //  Timeout (seconds)
     239        //  Restore the error handler
     240        restore_error_handler();
     241        //  Does the Error Log now contain anything?
     242        if ($this->error && $this->do_debug >= 1) {
     243            $this->displayErrors();
     244        }
     245        //  Did we connect?
     246        if ($this->pop_conn == false) {
     247            //  It would appear not...
     248            $this->error = array(
     249                'error' => "Failed to connect to server $host on port $port",
     250                'errno' => $errno,
     251                'errstr' => $errstr
     252            );
     253            if ($this->do_debug >= 1) {
     254                $this->displayErrors();
     255            }
     256            return false;
     257        }
     258
     259        //  Increase the stream time-out
     260        //  Check for PHP 4.3.0 or later
     261        if (version_compare(phpversion(), '5.0.0', 'ge')) {
     262            stream_set_timeout($this->pop_conn, $tval, 0);
     263        } else {
     264            //  Does not work on Windows
     265            if (substr(PHP_OS, 0, 3) !== 'WIN') {
     266                socket_set_timeout($this->pop_conn, $tval, 0);
     267            }
     268        }
     269
     270        //  Get the POP3 server response
     271        $pop3_response = $this->getResponse();
     272        //  Check for the +OK
     273        if ($this->checkResponse($pop3_response)) {
     274            //  The connection is established and the POP3 server is talking
     275            $this->connected = true;
     276            return true;
     277        }
     278        return false;
     279    }
     280
     281    /**
     282     * Log in to the POP3 server.
     283     * Does not support APOP (RFC 2828, 4949).
     284     * @access public
     285     * @param string $username
     286     * @param string $password
     287     * @return boolean
     288     */
     289    public function login($username = '', $password = '')
     290    {
     291        if ($this->connected == false) {
     292            $this->error = 'Not connected to POP3 server';
     293
     294            if ($this->do_debug >= 1) {
     295                $this->displayErrors();
     296            }
     297        }
     298        if (empty($username)) {
     299            $username = $this->username;
     300        }
     301        if (empty($password)) {
     302            $password = $this->password;
     303        }
     304
     305        // Send the Username
     306        $this->sendString("USER $username" . self::CRLF);
     307        $pop3_response = $this->getResponse();
     308        if ($this->checkResponse($pop3_response)) {
     309            // Send the Password
     310            $this->sendString("PASS $password" . self::CRLF);
     311            $pop3_response = $this->getResponse();
     312            if ($this->checkResponse($pop3_response)) {
     313                return true;
     314            }
     315        }
     316        return false;
     317    }
     318
     319    /**
     320     * Disconnect from the POP3 server.
     321     * @access public
     322     */
     323    public function disconnect()
     324    {
     325        $this->sendString('QUIT');
     326        //The QUIT command may cause the daemon to exit, which will kill our connection
     327        //So ignore errors here
     328        @fclose($this->pop_conn);
     329    }
     330
     331    /**
     332     * Get a response from the POP3 server.
     333     * $size is the maximum number of bytes to retrieve
     334     * @param integer $size
     335     * @return string
     336     * @access private
     337     */
     338    private function getResponse($size = 128)
     339    {
     340        $r = fgets($this->pop_conn, $size);
     341        if ($this->do_debug >= 1) {
     342            echo "Server -> Client: $r";
     343        }
     344        return $r;
     345    }
     346
     347    /**
     348     * Send raw data to the POP3 server.
     349     * @param string $string
     350     * @return integer
     351     * @access private
     352     */
     353    private function sendString($string)
     354    {
     355        if ($this->pop_conn) {
     356            if ($this->do_debug >= 2) { //Show client messages when debug >= 2
     357                echo "Client -> Server: $string";
     358            }
     359            return fwrite($this->pop_conn, $string, strlen($string));
     360        }
     361        return 0;
     362    }
     363
     364    /**
     365     * Checks the POP3 server response.
     366     * Looks for for +OK or -ERR.
     367     * @param string $string
     368     * @return boolean
     369     * @access private
     370     */
     371    private function checkResponse($string)
     372    {
     373        if (substr($string, 0, 3) !== '+OK') {
     374            $this->error = array(
     375                'error' => "Server reported an error: $string",
     376                'errno' => 0,
     377                'errstr' => ''
     378            );
     379            if ($this->do_debug >= 1) {
     380                $this->displayErrors();
     381            }
     382            return false;
     383        } else {
     384            return true;
     385        }
     386    }
     387
     388    /**
     389     * Display errors if debug is enabled.
     390     * @access private
     391     */
     392    private function displayErrors()
     393    {
     394        echo '<pre>';
     395        foreach ($this->error as $single_error) {
     396            print_r($single_error);
     397        }
     398        echo '</pre>';
     399    }
     400
     401    /**
     402     * POP3 connection error handler.
     403     * @param integer $errno
     404     * @param string $errstr
     405     * @param string $errfile
     406     * @param integer $errline
     407     * @access private
     408     */
     409    private function catchWarning($errno, $errstr, $errfile, $errline)
     410    {
     411        $this->error[] = array(
     412            'error' => "Connecting to the POP3 server raised a PHP warning: ",
     413            'errno' => $errno,
     414            'errstr' => $errstr,
     415            'errfile' => $errfile,
     416            'errline' => $errline
     417        );
     418    }
     419}
  • new file src/wp-includes/PHPMailer/class.smtp.php

    diff --git src/wp-includes/PHPMailer/class.smtp.php src/wp-includes/PHPMailer/class.smtp.php
    new file mode 100644
    index 0000000..e6b4522
    - +  
     1<?php
     2/**
     3 * PHPMailer RFC821 SMTP email transport class.
     4 * Version 5.2.7
     5 * PHP version 5.0.0
     6 * @category  PHP
     7 * @package   PHPMailer
     8 * @link      https://github.com/PHPMailer/PHPMailer/
     9 * @author Marcus Bointon (coolbru) <phpmailer@synchromedia.co.uk>
     10 * @author Jim Jagielski (jimjag) <jimjag@gmail.com>
     11 * @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
     12 * @copyright 2013 Marcus Bointon
     13 * @copyright 2004 - 2008 Andy Prevost
     14 * @copyright 2010 - 2012 Jim Jagielski
     15 * @license   http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
     16 */
     17
     18/**
     19 * PHPMailer RFC821 SMTP email transport class.
     20 *
     21 * Implements RFC 821 SMTP commands
     22 * and provides some utility methods for sending mail to an SMTP server.
     23 *
     24 * PHP Version 5.0.0
     25 *
     26 * @category PHP
     27 * @package  PHPMailer
     28 * @link     https://github.com/PHPMailer/PHPMailer/blob/master/class.smtp.php
     29 * @author   Chris Ryan <unknown@example.com>
     30 * @author   Marcus Bointon <phpmailer@synchromedia.co.uk>
     31 * @license  http://www.gnu.org/copyleft/lesser.html Distributed under the Lesser General Public License (LGPL)
     32 */
     33
     34class SMTP
     35{
     36    /**
     37     * The PHPMailer SMTP Version number.
     38     */
     39    const VERSION = '5.2.7';
     40
     41    /**
     42     * SMTP line break constant.
     43     */
     44    const CRLF = "\r\n";
     45
     46    /**
     47     * The SMTP port to use if one is not specified.
     48     */
     49    const DEFAULT_SMTP_PORT = 25;
     50
     51    /**
     52     * The PHPMailer SMTP Version number.
     53     * @type string
     54     * @deprecated This should be a constant
     55     * @see SMTP::VERSION
     56     */
     57    public $Version = '5.2.7';
     58
     59    /**
     60     * SMTP server port number.
     61     * @type int
     62     * @deprecated This is only ever ued as default value, so should be a constant
     63     * @see SMTP::DEFAULT_SMTP_PORT
     64     */
     65    public $SMTP_PORT = 25;
     66
     67    /**
     68     * SMTP reply line ending
     69     * @type string
     70     * @deprecated Use the class constant instead
     71     * @see SMTP::CRLF
     72     */
     73    public $CRLF = "\r\n";
     74
     75    /**
     76     * Debug output level.
     77     * Options: 0 for no output, 1 for commands, 2 for data and commands
     78     * @type int
     79     */
     80    public $do_debug = 0;
     81
     82    /**
     83     * The function/method to use for debugging output.
     84     * Options: 'echo', 'html' or 'error_log'
     85     * @type string
     86     */
     87    public $Debugoutput = 'echo';
     88
     89    /**
     90     * Whether to use VERP.
     91     * @type bool
     92     */
     93    public $do_verp = false;
     94
     95    /**
     96     * The SMTP timeout value for reads, in seconds.
     97     * @type int
     98     */
     99    public $Timeout = 15;
     100
     101    /**
     102     * The SMTP timelimit value for reads, in seconds.
     103     * @type int
     104     */
     105    public $Timelimit = 30;
     106
     107    /**
     108     * The socket for the server connection.
     109     * @type resource
     110     */
     111    protected $smtp_conn;
     112
     113    /**
     114     * Error message, if any, for the last call.
     115     * @type string
     116     */
     117    protected $error = '';
     118
     119    /**
     120     * The reply the server sent to us for HELO.
     121     * @type string
     122     */
     123    protected $helo_rply = '';
     124
     125    /**
     126     * The most recent reply received from the server.
     127     * @type string
     128     */
     129    protected $last_reply = '';
     130
     131    /**
     132     * Constructor.
     133     * @access public
     134     */
     135    public function __construct()
     136    {
     137        $this->smtp_conn = 0;
     138        $this->error = null;
     139        $this->helo_rply = null;
     140
     141        $this->do_debug = 0;
     142    }
     143
     144    /**
     145     * Output debugging info via a user-selected method.
     146     * @param string $str Debug string to output
     147     * @return void
     148     */
     149    protected function edebug($str)
     150    {
     151        switch ($this->Debugoutput) {
     152            case 'error_log':
     153                //Don't output, just log
     154                error_log($str);
     155                break;
     156            case 'html':
     157                //Cleans up output a bit for a better looking, HTML-safe output
     158                echo htmlentities(
     159                    preg_replace('/[\r\n]+/', '', $str),
     160                    ENT_QUOTES,
     161                    'UTF-8'
     162                )
     163                . "<br>\n";
     164                break;
     165            case 'echo':
     166            default:
     167                //Just echoes whatever was received
     168                echo $str;
     169        }
     170    }
     171
     172    /**
     173     * Connect to an SMTP server.
     174     * @param string $host    SMTP server IP or host name
     175     * @param int $port    The port number to connect to
     176     * @param int $timeout How long to wait for the connection to open
     177     * @param array $options An array of options for stream_context_create()
     178     * @access public
     179     * @return bool
     180     */
     181    public function connect($host, $port = null, $timeout = 30, $options = array())
     182    {
     183        // Clear errors to avoid confusion
     184        $this->error = null;
     185
     186        // Make sure we are __not__ connected
     187        if ($this->connected()) {
     188            // Already connected, generate error
     189            $this->error = array('error' => 'Already connected to a server');
     190            return false;
     191        }
     192
     193        if (empty($port)) {
     194            $port = self::DEFAULT_SMTP_PORT;
     195        }
     196
     197        // Connect to the SMTP server
     198        $errno = 0;
     199        $errstr = '';
     200        $socket_context = stream_context_create($options);
     201        //Suppress errors; connection failures are handled at a higher level
     202        $this->smtp_conn = @stream_socket_client(
     203            $host . ":" . $port,
     204            $errno,
     205            $errstr,
     206            $timeout,
     207            STREAM_CLIENT_CONNECT,
     208            $socket_context
     209        );
     210
     211        // Verify we connected properly
     212        if (empty($this->smtp_conn)) {
     213            $this->error = array(
     214                'error' => 'Failed to connect to server',
     215                'errno' => $errno,
     216                'errstr' => $errstr
     217            );
     218            if ($this->do_debug >= 1) {
     219                $this->edebug(
     220                    'SMTP -> ERROR: ' . $this->error['error']
     221                    . ": $errstr ($errno)"
     222                );
     223            }
     224            return false;
     225        }
     226
     227        // SMTP server can take longer to respond, give longer timeout for first read
     228        // Windows does not have support for this timeout function
     229        if (substr(PHP_OS, 0, 3) != 'WIN') {
     230            $max = ini_get('max_execution_time');
     231            if ($max != 0 && $timeout > $max) { // Don't bother if unlimited
     232                @set_time_limit($timeout);
     233            }
     234            stream_set_timeout($this->smtp_conn, $timeout, 0);
     235        }
     236
     237        // Get any announcement
     238        $announce = $this->get_lines();
     239
     240        if ($this->do_debug >= 2) {
     241            $this->edebug('SMTP -> FROM SERVER:' . $announce);
     242        }
     243
     244        return true;
     245    }
     246
     247    /**
     248     * Initiate a TLS (encrypted) session.
     249     * @access public
     250     * @return bool
     251     */
     252    public function startTLS()
     253    {
     254        if (!$this->sendCommand("STARTTLS", "STARTTLS", 220)) {
     255            return false;
     256        }
     257        // Begin encrypted connection
     258        if (!stream_socket_enable_crypto(
     259            $this->smtp_conn,
     260            true,
     261            STREAM_CRYPTO_METHOD_TLS_CLIENT
     262        )
     263        ) {
     264            return false;
     265        }
     266        return true;
     267    }
     268
     269    /**
     270     * Perform SMTP authentication.
     271     * Must be run after hello().
     272     * @see hello()
     273     * @param string $username    The user name
     274     * @param string $password    The password
     275     * @param string $authtype    The auth type (PLAIN, LOGIN, NTLM, CRAM-MD5)
     276     * @param string $realm       The auth realm for NTLM
     277     * @param string $workstation The auth workstation for NTLM
     278     * @access public
     279     * @return bool True if successfully authenticated.
     280     */
     281    public function authenticate(
     282        $username,
     283        $password,
     284        $authtype = 'LOGIN',
     285        $realm = '',
     286        $workstation = ''
     287    ) {
     288        if (empty($authtype)) {
     289            $authtype = 'LOGIN';
     290        }
     291
     292        switch ($authtype) {
     293            case 'PLAIN':
     294                // Start authentication
     295                if (!$this->sendCommand('AUTH', 'AUTH PLAIN', 334)) {
     296                    return false;
     297                }
     298                // Send encoded username and password
     299                if (!$this->sendCommand(
     300                    'User & Password',
     301                    base64_encode("\0" . $username . "\0" . $password),
     302                    235
     303                )
     304                ) {
     305                    return false;
     306                }
     307                break;
     308            case 'LOGIN':
     309                // Start authentication
     310                if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) {
     311                    return false;
     312                }
     313                if (!$this->sendCommand("Username", base64_encode($username), 334)) {
     314                    return false;
     315                }
     316                if (!$this->sendCommand("Password", base64_encode($password), 235)) {
     317                    return false;
     318                }
     319                break;
     320            case 'NTLM':
     321                /*
     322                 * ntlm_sasl_client.php
     323                 * Bundled with Permission
     324                 *
     325                 * How to telnet in windows:
     326                 * http://technet.microsoft.com/en-us/library/aa995718%28EXCHG.65%29.aspx
     327                 * PROTOCOL Docs http://curl.haxx.se/rfc/ntlm.html#ntlmSmtpAuthentication
     328                 */
     329                require_once 'extras/ntlm_sasl_client.php';
     330                $temp = new stdClass();
     331                $ntlm_client = new ntlm_sasl_client_class;
     332                //Check that functions are available
     333                if (!$ntlm_client->Initialize($temp)) {
     334                    $this->error = array('error' => $temp->error);
     335                    if ($this->do_debug >= 1) {
     336                        $this->edebug(
     337                            'You need to enable some modules in your php.ini file: '
     338                            . $this->error['error']
     339                        );
     340                    }
     341                    return false;
     342                }
     343                //msg1
     344                $msg1 = $ntlm_client->TypeMsg1($realm, $workstation); //msg1
     345
     346                if (!$this->sendCommand(
     347                    'AUTH NTLM',
     348                    'AUTH NTLM ' . base64_encode($msg1),
     349                    334
     350                )
     351                ) {
     352                    return false;
     353                }
     354
     355                //Though 0 based, there is a white space after the 3 digit number
     356                //msg2
     357                $challenge = substr($this->last_reply, 3);
     358                $challenge = base64_decode($challenge);
     359                $ntlm_res = $ntlm_client->NTLMResponse(
     360                    substr($challenge, 24, 8),
     361                    $password
     362                );
     363                //msg3
     364                $msg3 = $ntlm_client->TypeMsg3(
     365                    $ntlm_res,
     366                    $username,
     367                    $realm,
     368                    $workstation
     369                );
     370                // send encoded username
     371                return $this->sendCommand('Username', base64_encode($msg3), 235);
     372                break;
     373            case 'CRAM-MD5':
     374                // Start authentication
     375                if (!$this->sendCommand('AUTH CRAM-MD5', 'AUTH CRAM-MD5', 334)) {
     376                    return false;
     377                }
     378                // Get the challenge
     379                $challenge = base64_decode(substr($this->last_reply, 4));
     380
     381                // Build the response
     382                $response = $username . ' ' . $this->hmac($challenge, $password);
     383
     384                // send encoded credentials
     385                return $this->sendCommand('Username', base64_encode($response), 235);
     386                break;
     387        }
     388        return true;
     389    }
     390
     391    /**
     392     * Calculate an MD5 HMAC hash.
     393     * Works like hash_hmac('md5', $data, $key)
     394     * in case that function is not available
     395     * @param string $data The data to hash
     396     * @param string $key  The key to hash with
     397     * @access protected
     398     * @return string
     399     */
     400    protected function hmac($data, $key)
     401    {
     402        if (function_exists('hash_hmac')) {
     403            return hash_hmac('md5', $data, $key);
     404        }
     405
     406        // The following borrowed from
     407        // http://php.net/manual/en/function.mhash.php#27225
     408
     409        // RFC 2104 HMAC implementation for php.
     410        // Creates an md5 HMAC.
     411        // Eliminates the need to install mhash to compute a HMAC
     412        // Hacked by Lance Rushing
     413
     414        $b = 64; // byte length for md5
     415        if (strlen($key) > $b) {
     416            $key = pack('H*', md5($key));
     417        }
     418        $key = str_pad($key, $b, chr(0x00));
     419        $ipad = str_pad('', $b, chr(0x36));
     420        $opad = str_pad('', $b, chr(0x5c));
     421        $k_ipad = $key ^ $ipad;
     422        $k_opad = $key ^ $opad;
     423
     424        return md5($k_opad . pack('H*', md5($k_ipad . $data)));
     425    }
     426
     427    /**
     428     * Check connection state.
     429     * @access public
     430     * @return bool True if connected.
     431     */
     432    public function connected()
     433    {
     434        if (!empty($this->smtp_conn)) {
     435            $sock_status = stream_get_meta_data($this->smtp_conn);
     436            if ($sock_status['eof']) {
     437                // the socket is valid but we are not connected
     438                if ($this->do_debug >= 1) {
     439                    $this->edebug(
     440                        'SMTP -> NOTICE: EOF caught while checking if connected'
     441                    );
     442                }
     443                $this->close();
     444                return false;
     445            }
     446            return true; // everything looks good
     447        }
     448        return false;
     449    }
     450
     451    /**
     452     * Close the socket and clean up the state of the class.
     453     * Don't use this function without first trying to use QUIT.
     454     * @see quit()
     455     * @access public
     456     * @return void
     457     */
     458    public function close()
     459    {
     460        $this->error = null; // so there is no confusion
     461        $this->helo_rply = null;
     462        if (!empty($this->smtp_conn)) {
     463            // close the connection and cleanup
     464            fclose($this->smtp_conn);
     465            $this->smtp_conn = 0;
     466        }
     467    }
     468
     469    /**
     470     * Send an SMTP DATA command.
     471     * Issues a data command and sends the msg_data to the server,
     472     * finializing the mail transaction. $msg_data is the message
     473     * that is to be send with the headers. Each header needs to be
     474     * on a single line followed by a <CRLF> with the message headers
     475     * and the message body being separated by and additional <CRLF>.
     476     * Implements rfc 821: DATA <CRLF>
     477     * @param string $msg_data Message data to send
     478     * @access public
     479     * @return bool
     480     */
     481    public function data($msg_data)
     482    {
     483        if (!$this->sendCommand('DATA', 'DATA', 354)) {
     484            return false;
     485        }
     486
     487        /* The server is ready to accept data!
     488         * according to rfc821 we should not send more than 1000
     489         * including the CRLF
     490         * characters on a single line so we will break the data up
     491         * into lines by \r and/or \n then if needed we will break
     492         * each of those into smaller lines to fit within the limit.
     493         * in addition we will be looking for lines that start with
     494         * a period '.' and append and additional period '.' to that
     495         * line. NOTE: this does not count towards limit.
     496         */
     497
     498        // Normalize the line breaks before exploding
     499        $msg_data = str_replace("\r\n", "\n", $msg_data);
     500        $msg_data = str_replace("\r", "\n", $msg_data);
     501        $lines = explode("\n", $msg_data);
     502
     503        /* We need to find a good way to determine if headers are
     504         * in the msg_data or if it is a straight msg body
     505         * currently I am assuming rfc822 definitions of msg headers
     506         * and if the first field of the first line (':' separated)
     507         * does not contain a space then it _should_ be a header
     508         * and we can process all lines before a blank "" line as
     509         * headers.
     510         */
     511
     512        $field = substr($lines[0], 0, strpos($lines[0], ':'));
     513        $in_headers = false;
     514        if (!empty($field) && !strstr($field, ' ')) {
     515            $in_headers = true;
     516        }
     517
     518        //RFC 2822 section 2.1.1 limit
     519        $max_line_length = 998;
     520
     521        foreach ($lines as $line) {
     522            $lines_out = null;
     523            if ($line == '' && $in_headers) {
     524                $in_headers = false;
     525            }
     526            // ok we need to break this line up into several smaller lines
     527            while (strlen($line) > $max_line_length) {
     528                $pos = strrpos(substr($line, 0, $max_line_length), ' ');
     529
     530                // Patch to fix DOS attack
     531                if (!$pos) {
     532                    $pos = $max_line_length - 1;
     533                    $lines_out[] = substr($line, 0, $pos);
     534                    $line = substr($line, $pos);
     535                } else {
     536                    $lines_out[] = substr($line, 0, $pos);
     537                    $line = substr($line, $pos + 1);
     538                }
     539
     540                /* If processing headers add a LWSP-char to the front of new line
     541                 * rfc822 on long msg headers
     542                 */
     543                if ($in_headers) {
     544                    $line = "\t" . $line;
     545                }
     546            }
     547            $lines_out[] = $line;
     548
     549            // send the lines to the server
     550            while (list(, $line_out) = @each($lines_out)) {
     551                if (strlen($line_out) > 0) {
     552                    if (substr($line_out, 0, 1) == '.') {
     553                        $line_out = '.' . $line_out;
     554                    }
     555                }
     556                $this->client_send($line_out . self::CRLF);
     557            }
     558        }
     559
     560        // Message data has been sent, complete the command
     561        return $this->sendCommand('DATA END', '.', 250);
     562    }
     563
     564    /**
     565     * Send an SMTP HELO or EHLO command.
     566     * Used to identify the sending server to the receiving server.
     567     * This makes sure that client and server are in a known state.
     568     * Implements from RFC 821: HELO <SP> <domain> <CRLF>
     569     * and RFC 2821 EHLO.
     570     * @param string $host The host name or IP to connect to
     571     * @access public
     572     * @return bool
     573     */
     574    public function hello($host = '')
     575    {
     576        // Try extended hello first (RFC 2821)
     577        if (!$this->sendHello('EHLO', $host)) {
     578            if (!$this->sendHello('HELO', $host)) {
     579                return false;
     580            }
     581        }
     582
     583        return true;
     584    }
     585
     586    /**
     587     * Send an SMTP HELO or EHLO command.
     588     * Low-level implementation used by hello()
     589     * @see hello()
     590     * @param string $hello The HELO string
     591     * @param string $host  The hostname to say we are
     592     * @access protected
     593     * @return bool
     594     */
     595    protected function sendHello($hello, $host)
     596    {
     597        $noerror = $this->sendCommand($hello, $hello . ' ' . $host, 250);
     598        $this->helo_rply = $this->last_reply;
     599        return $noerror;
     600    }
     601
     602    /**
     603     * Send an SMTP MAIL command.
     604     * Starts a mail transaction from the email address specified in
     605     * $from. Returns true if successful or false otherwise. If True
     606     * the mail transaction is started and then one or more recipient
     607     * commands may be called followed by a data command.
     608     * Implements rfc 821: MAIL <SP> FROM:<reverse-path> <CRLF>
     609     * @param string $from Source address of this message
     610     * @access public
     611     * @return bool
     612     */
     613    public function mail($from)
     614    {
     615        $useVerp = ($this->do_verp ? ' XVERP' : '');
     616        return $this->sendCommand(
     617            'MAIL FROM',
     618            'MAIL FROM:<' . $from . '>' . $useVerp,
     619            250
     620        );
     621    }
     622
     623    /**
     624     * Send an SMTP QUIT command.
     625     * Closes the socket if there is no error or the $close_on_error argument is true.
     626     * Implements from rfc 821: QUIT <CRLF>
     627     * @param bool $close_on_error Should the connection close if an error occurs?
     628     * @access public
     629     * @return bool
     630     */
     631    public function quit($close_on_error = true)
     632    {
     633        $noerror = $this->sendCommand('QUIT', 'QUIT', 221);
     634        $e = $this->error; //Save any error
     635        if ($noerror or $close_on_error) {
     636            $this->close();
     637            $this->error = $e; //Restore any error from the quit command
     638        }
     639        return $noerror;
     640    }
     641
     642    /**
     643     * Send an SMTP RCPT command.
     644     * Sets the TO argument to $to.
     645     * Returns true if the recipient was accepted false if it was rejected.
     646     * Implements from rfc 821: RCPT <SP> TO:<forward-path> <CRLF>
     647     * @param string $to The address the message is being sent to
     648     * @access public
     649     * @return bool
     650     */
     651    public function recipient($to)
     652    {
     653        return $this->sendCommand(
     654            'RCPT TO ',
     655            'RCPT TO:<' . $to . '>',
     656            array(250, 251)
     657        );
     658    }
     659
     660    /**
     661     * Send an SMTP RSET command.
     662     * Abort any transaction that is currently in progress.
     663     * Implements rfc 821: RSET <CRLF>
     664     * @access public
     665     * @return bool True on success.
     666     */
     667    public function reset()
     668    {
     669        return $this->sendCommand('RSET', 'RSET', 250);
     670    }
     671
     672    /**
     673     * Send a command to an SMTP server and check its return code.
     674     * @param string $command       The command name - not sent to the server
     675     * @param string $commandstring The actual command to send
     676     * @param int|array $expect     One or more expected integer success codes
     677     * @access protected
     678     * @return bool True on success.
     679     */
     680    protected function sendCommand($command, $commandstring, $expect)
     681    {
     682        if (!$this->connected()) {
     683            $this->error = array(
     684                "error" => "Called $command without being connected"
     685            );
     686            return false;
     687        }
     688        $this->client_send($commandstring . self::CRLF);
     689
     690        $reply = $this->get_lines();
     691        $code = substr($reply, 0, 3);
     692
     693        if ($this->do_debug >= 2) {
     694            $this->edebug('SMTP -> FROM SERVER:' . $reply);
     695        }
     696
     697        if (!in_array($code, (array)$expect)) {
     698            $this->last_reply = null;
     699            $this->error = array(
     700                "error" => "$command command failed",
     701                "smtp_code" => $code,
     702                "detail" => substr($reply, 4)
     703            );
     704            if ($this->do_debug >= 1) {
     705                $this->edebug(
     706                    'SMTP -> ERROR: ' . $this->error['error'] . ': ' . $reply
     707                );
     708            }
     709            return false;
     710        }
     711
     712        $this->last_reply = $reply;
     713        $this->error = null;
     714        return true;
     715    }
     716
     717    /**
     718     * Send an SMTP SAML command.
     719     * Starts a mail transaction from the email address specified in $from.
     720     * Returns true if successful or false otherwise. If True
     721     * the mail transaction is started and then one or more recipient
     722     * commands may be called followed by a data command. This command
     723     * will send the message to the users terminal if they are logged
     724     * in and send them an email.
     725     * Implements rfc 821: SAML <SP> FROM:<reverse-path> <CRLF>
     726     * @param string $from The address the message is from
     727     * @access public
     728     * @return bool
     729     */
     730    public function sendAndMail($from)
     731    {
     732        return $this->sendCommand("SAML", "SAML FROM:$from", 250);
     733    }
     734
     735    /**
     736     * Send an SMTP VRFY command.
     737     * @param string $name The name to verify
     738     * @access public
     739     * @return bool
     740     */
     741    public function verify($name)
     742    {
     743        return $this->sendCommand("VRFY", "VRFY $name", array(250, 251));
     744    }
     745
     746    /**
     747     * Send an SMTP NOOP command.
     748     * Used to keep keep-alives alive, doesn't actually do anything
     749     * @access public
     750     * @return bool
     751     */
     752    public function noop()
     753    {
     754        return $this->sendCommand("NOOP", "NOOP", 250);
     755    }
     756
     757    /**
     758     * Send an SMTP TURN command.
     759     * This is an optional command for SMTP that this class does not support.
     760     * This method is here to make the RFC821 Definition
     761     * complete for this class and __may__ be implemented in future
     762     * Implements from rfc 821: TURN <CRLF>
     763     * @access public
     764     * @return bool
     765     */
     766    public function turn()
     767    {
     768        $this->error = array(
     769            'error' => 'The SMTP TURN command is not implemented'
     770        );
     771        if ($this->do_debug >= 1) {
     772            $this->edebug('SMTP -> NOTICE: ' . $this->error['error']);
     773        }
     774        return false;
     775    }
     776
     777    /**
     778     * Send raw data to the server.
     779     * @param string $data The data to send
     780     * @access public
     781     * @return int|bool The number of bytes sent to the server or FALSE on error
     782     */
     783    public function client_send($data)
     784    {
     785        if ($this->do_debug >= 1) {
     786            $this->edebug("CLIENT -> SMTP: $data");
     787        }
     788        return fwrite($this->smtp_conn, $data);
     789    }
     790
     791    /**
     792     * Get the latest error.
     793     * @access public
     794     * @return array
     795     */
     796    public function getError()
     797    {
     798        return $this->error;
     799    }
     800
     801    /**
     802     * Get the last reply from the server.
     803     * @access public
     804     * @return string
     805     */
     806    public function getLastReply()
     807    {
     808        return $this->last_reply;
     809    }
     810
     811    /**
     812     * Read the SMTP server's response.
     813     * Either before eof or socket timeout occurs on the operation.
     814     * With SMTP we can tell if we have more lines to read if the
     815     * 4th character is '-' symbol. If it is a space then we don't
     816     * need to read anything else.
     817     * @access protected
     818     * @return string
     819     */
     820    protected function get_lines()
     821    {
     822        $data = '';
     823        $endtime = 0;
     824        // If the connection is bad, give up now
     825        if (!is_resource($this->smtp_conn)) {
     826            return $data;
     827        }
     828        stream_set_timeout($this->smtp_conn, $this->Timeout);
     829        if ($this->Timelimit > 0) {
     830            $endtime = time() + $this->Timelimit;
     831        }
     832        while (is_resource($this->smtp_conn) && !feof($this->smtp_conn)) {
     833            $str = @fgets($this->smtp_conn, 515);
     834            if ($this->do_debug >= 4) {
     835                $this->edebug("SMTP -> get_lines(): \$data was \"$data\"");
     836                $this->edebug("SMTP -> get_lines(): \$str is \"$str\"");
     837            }
     838            $data .= $str;
     839            if ($this->do_debug >= 4) {
     840                $this->edebug("SMTP -> get_lines(): \$data is \"$data\"");
     841            }
     842            // if 4th character is a space, we are done reading, break the loop
     843            if (substr($str, 3, 1) == ' ') {
     844                break;
     845            }
     846            // Timed-out? Log and break
     847            $info = stream_get_meta_data($this->smtp_conn);
     848            if ($info['timed_out']) {
     849                if ($this->do_debug >= 4) {
     850                    $this->edebug(
     851                        'SMTP -> get_lines(): timed-out (' . $this->Timeout . ' sec)'
     852                    );
     853                }
     854                break;
     855            }
     856            // Now check if reads took too long
     857            if ($endtime) {
     858                if (time() > $endtime) {
     859                    if ($this->do_debug >= 4) {
     860                        $this->edebug(
     861                            'SMTP -> get_lines(): timelimit reached ('
     862                            . $this->Timelimit . ' sec)'
     863                        );
     864                    }
     865                    break;
     866                }
     867            }
     868        }
     869        return $data;
     870    }
     871
     872    /**
     873     * Enable or disable VERP address generation.
     874     * @param bool $enabled
     875     */
     876    public function setVerp($enabled = false)
     877    {
     878        $this->do_verp = $enabled;
     879    }
     880
     881    /**
     882     * Get VERP address generation mode.
     883     * @return bool
     884     */
     885    public function getVerp()
     886    {
     887        return $this->do_verp;
     888    }
     889
     890    /**
     891     * Set debug output method.
     892     * @param string $method The function/method to use for debugging output.
     893     */
     894    public function setDebugOutput($method = 'echo')
     895    {
     896        $this->Debugoutput = $method;
     897    }
     898
     899    /**
     900     * Get debug output method.
     901     * @return string
     902     */
     903    public function getDebugOutput()
     904    {
     905        return $this->Debugoutput;
     906    }
     907
     908    /**
     909     * Set debug output level.
     910     * @param int $level
     911     */
     912    public function setDebugLevel($level = 0)
     913    {
     914        $this->do_debug = $level;
     915    }
     916
     917    /**
     918     * Get debug output level.
     919     * @return int
     920     */
     921    public function getDebugLevel()
     922    {
     923        return $this->do_debug;
     924    }
     925
     926    /**
     927     * Set SMTP timeout.
     928     * @param int $timeout
     929     */
     930    public function setTimeout($timeout = 0)
     931    {
     932        $this->Timeout = $timeout;
     933    }
     934
     935    /**
     936     * Get SMTP timeout.
     937     * @return int
     938     */
     939    public function getTimeout()
     940    {
     941        return $this->Timeout;
     942    }
     943}
  • new file src/wp-includes/PHPMailer/composer.json

    diff --git src/wp-includes/PHPMailer/composer.json src/wp-includes/PHPMailer/composer.json
    new file mode 100644
    index 0000000..086f381
    - +  
     1{
     2    "name": "phpmailer/phpmailer",
     3    "type": "library",
     4    "description": "PHPMailer is a full-featured email creation and transfer class for PHP",
     5    "authors": [
     6        {
     7