From: <be...@us...> - 2015-10-20 05:21:56
|
Revision: 13164 http://sourceforge.net/p/xoops/svn/13164 Author: beckmi Date: 2015-10-20 05:21:53 +0000 (Tue, 20 Oct 2015) Log Message: ----------- phpMailer 5.2.13 Modified Paths: -------------- XoopsCore/branches/2.5.x/2.5.8/docs/changelog.250.txt XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/README.md XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/changelog.md XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/class.phpmailer.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/class.pop3.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/class.smtp.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/index.html XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/index.html XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-ar.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-be.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-br.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-ca.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-ch.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-cz.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-de.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-dk.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-el.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-eo.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-es.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-et.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-fa.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-fi.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-fo.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-fr.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-gl.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-hr.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-hu.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-it.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-ja.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-ka.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-lt.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-lv.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-nl.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-no.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-pl.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-pt.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-ro.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-ru.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-se.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-sk.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-sr.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-tr.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-uk.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-vi.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-zh.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-zh_cn.php Added Paths: ----------- XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/class.phpmaileroauth.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/class.phpmaileroauthgoogle.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/get_oauth_token.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-am.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-az.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-bg.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-id.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-ko.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-ms.php XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/language/phpmailer.lang-sl.php Modified: XoopsCore/branches/2.5.x/2.5.8/docs/changelog.250.txt =================================================================== --- XoopsCore/branches/2.5.x/2.5.8/docs/changelog.250.txt 2015-10-20 00:07:35 UTC (rev 13163) +++ XoopsCore/branches/2.5.x/2.5.8/docs/changelog.250.txt 2015-10-20 05:21:53 UTC (rev 13164) @@ -26,7 +26,7 @@ - fix moved "count($tagsArray)" and "count($attrArray)" outside of FOR loop in xoopsfilterinput.php (mamba) - add option to set height of Themes block (mamba) - fix: Invalid argument supplied for foreach() (cesagonchu/mamba) -- fix profile/search (cesag/slider84) +- fix profile/search (cesagonchu/slider84) Security fixes @@ -35,7 +35,7 @@ Updated: - TinyMCE to 3.5.11 (mamba) - - PHPMailer to 5.2.9 (rgriffith) + - PHPMailer to 5.2.13 (mamba) - jQuery to 1.11.3 (mamba) - jQuery UI 1.11.4 (mamba) - jGrowl to 1.4.3 (mamba) Modified: XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/README.md =================================================================== --- XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/README.md 2015-10-20 00:07:35 UTC (rev 13163) +++ XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/README.md 2015-10-20 05:21:53 UTC (rev 13164) @@ -6,16 +6,18 @@ [](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/) [](https://scrutinizer-ci.com/g/PHPMailer/PHPMailer/) +[](https://packagist.org/packages/phpmailer/phpmailer) [](https://packagist.org/packages/phpmailer/phpmailer) [](https://packagist.org/packages/phpmailer/phpmailer) [](https://packagist.org/packages/phpmailer/phpmailer) + ## Class Features - Probably the world's most popular code for sending email from PHP! -- Used by many open-source projects: Drupal, SugarCRM, Yii, Joomla! and many more +- Used by many open-source projects: WordPress, Drupal, 1CRM, SugarCRM, Yii, Joomla! and many more - Integrated SMTP support - send without a local mail server - Send emails with multiple TOs, CCs, BCCs and REPLY-TOs - Multipart/alternative emails for mail clients that do not read HTML email - Support for UTF-8 content and 8bit, base64, binary, and quoted-printable encodings -- SMTP authentication with LOGIN, PLAIN, NTLM and CRAM-MD5 mechanisms over SSL and TLS transports -- Native language support +- SMTP authentication with LOGIN, PLAIN, NTLM, CRAM-MD5 and Google's XOAUTH2 mechanisms over SSL and TLS transports +- Error messages in 47 languages! - DKIM and S/MIME signing support - Compatible with PHP 5.0 and later - Much more! @@ -31,19 +33,36 @@ ## License -This software is licenced under the [LGPL 2.1](http://www.gnu.org/licenses/lgpl-2.1.html). Please read LICENSE for information on the +This software is distributed under the [LGPL 2.1](http://www.gnu.org/licenses/lgpl-2.1.html) license. Please read LICENSE for information on the software availability and distribution. ## Installation & loading -PHPMailer 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. +PHPMailer is available via [Composer/Packagist](https://packagist.org/packages/phpmailer/phpmailer) (using semantic versioning), so just add this line to your `composer.json` file: -PHPMailer provides an SPL-compatible autoloader, and that is the preferred way of loading the library - just `require '/path/to/PHPMailerAutoload.php';` and everything should work. The autoloader does not throw errors if it can't find classes so it prepends itself to the SPL list, allowing your own (or your framework's) autoloader to catch errors. SPL autoloading was introduced in PHP 5.1.0, so if you are using a version older than that you will need to require/include each class manually. +```json +"phpmailer/phpmailer": "~5.2" +``` + +or + +```sh +composer require phpmailer/phpmailer +``` + +If you want to use the Gmail XOAUTH2 authentication class, you will also need to add a dependency on the `league/oauth2-client` package. + +Alternatively, 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. + +If you're not using composer's autoloader, PHPMailer provides an SPL-compatible autoloader, and that is the preferred way of loading the library - just `require '/path/to/PHPMailerAutoload.php';` and everything should work. The autoloader does not throw errors if it can't find classes so it prepends itself to the SPL list, allowing your own (or your framework's) autoloader to catch errors. SPL autoloading was introduced in PHP 5.1.0, so if you are using a version older than that you will need to require/include each class manually. + PHPMailer does *not* declare a namespace because namespaces were only introduced in PHP 5.3. +If you want to use Google's XOAUTH2 authentication mechanism, you need to be running at least PHP 5.4, and load the dependencies listed in `composer.json`. + ### Minimal installation -While installing the entire package manually or with composer is simple, convenient and reliable, you may want to include only vital files in your project. At the very least you will need [class.phpmailer.php](class.phpmailer.php). If you're using SMTP, you'll need [class.smtp.php](class.smtp.php), and if you're using POP-before SMTP, you'll need [class.pop3.php](class.pop3.php). For all of these, we recommend you use [the autoloader](PHPMailerAutoload.php) too as otherwise you will either have to `require` all classes manually or use some other autoloader. You can skip the [language](language/) folder if you're not showing errors to users and can make do with English-only errors. You may need the additional classes in the [extras](extras/) folder if you are using those features, including NTLM authentication, advanced HTML-to-text conversion and ics generation. +While installing the entire package manually or with composer is simple, convenient and reliable, you may want to include only vital files in your project. At the very least you will need [class.phpmailer.php](class.phpmailer.php). If you're using SMTP, you'll need [class.smtp.php](class.smtp.php), and if you're using POP-before SMTP, you'll need [class.pop3.php](class.pop3.php). For all of these, we recommend you use [the autoloader](PHPMailerAutoload.php) too as otherwise you will either have to `require` all classes manually or use some other autoloader. You can skip the [language](language/) folder if you're not showing errors to users and can make do with English-only errors. You may need the additional classes in the [extras](extras/) folder if you are using those features, including NTLM authentication and ics generation. If you're using Google XOAUTH2 you will need `class.phpmaileroauth.php` and `class.oauth.php` classes too, as well as the composer dependencies. ## A Simple Example @@ -71,7 +90,6 @@ $mail->addCC('cc...@ex...'); $mail->addBCC('bc...@ex...'); -$mail->WordWrap = 50; // Set word wrap to 50 characters $mail->addAttachment('/var/tmp/file.tar.gz'); // Add attachments $mail->addAttachment('/tmp/image.jpg', 'new.jpg'); // Optional name $mail->isHTML(true); // Set email format to HTML @@ -93,7 +111,7 @@ That's it. You should now be ready to use PHPMailer! ## Localization -PHPMailer defaults to English, but in the [language](language/) folder you'll find numerous (39 at the time of writing) 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: +PHPMailer defaults to English, but in the [language](language/) folder you'll find numerous (46 at the time of writing!) 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: ```php // To load the French version @@ -104,10 +122,16 @@ ## Documentation -Generated documentation is [available online](http://phpmailer.github.io/PHPMailer/). +Examples of how to use PHPMailer for common scenarios can be found in the [examples](examples/) folder. If you're looking for a good starting point, we recommend you start with [the gmail example](examples/gmail.phps). +There are tips and a troubleshooting guide in the [GitHub wiki](https://github.com/PHPMailer/PHPMailer/wiki). If you're having trouble, this should be the first place you look as it's the most frequently updated. + +Complete generated API documentation is [available online](http://phpmailer.github.io/PHPMailer/). + You'll find some basic user-level docs in the [docs](docs/) folder, and you can generate complete API-level documentation using the [generatedocs.sh](docs/generatedocs.sh) shell script in the docs folder, though you'll need to install [PHPDocumentor](http://www.phpdoc.org) first. You may find [the unit tests](test/phpmailerTest.php) a good source of how to do various operations such as encryption. +If the documentation doesn't cover what you need, search the [many questions on StackOverflow](http://stackoverflow.com/questions/tagged/phpmailer), and before you ask a question about "SMTP Error: Could not connect to SMTP host.", [read the troubleshooting guide](https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting). + ## Tests There is a PHPUnit test script in the [test](test/) folder. @@ -124,10 +148,20 @@ With 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: -`git remote set-url upstream https://github.com/PHPMailer/PHPMailer.git` +```sh +git remote set-url upstream https://github.com/PHPMailer/PHPMailer.git +``` Please *don't* use the SourceForge or Google Code projects any more. +## Sponsorship + +Development time and resources for PHPMailer are provided by [Smartmessages.net](https://info.smartmessages.net/), a powerful email marketing system. + +<a href="https://info.smartmessages.net/"><img src="https://www.smartmessages.net/img/smartmessages-logo.svg" width="250" height="28" alt="Smartmessages email marketing"></a> + +Other contributions are gladly received, whether in beer 🍺, T-shirts 👕, Amazon wishlist raids, or cold, hard cash 💰. + ## Changelog See [changelog](changelog.md). Modified: XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/changelog.md =================================================================== --- XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/changelog.md 2015-10-20 00:07:35 UTC (rev 13163) +++ XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/changelog.md 2015-10-20 05:21:53 UTC (rev 13164) @@ -1,5 +1,58 @@ # ChangeLog +## Version 5.2.13 (Sep 14th 2015) +* Rename internal oauth class to avoid name clashes +* Improve Estonian translations + +## Version 5.2.12 (Sep 1st 2015) +* Fix incorrect composer package dependencies +* Skip existing embedded image `cid`s in `msgHTML` + +## Version 5.2.11 (Aug 31st 2015) +* Don't switch to quoted-printable for long lines if already using base64 +* Fixed Travis-CI config when run on PHP 7 +* Added Google XOAUTH2 authentication mechanism, thanks to @sherryl4george +* Add address parser for RFC822-format addresses +* Update MS Office MIME types +* Don't convert line breaks when using quoted-printable encoding +* Handle MS Exchange returning an invalid empty AUTH-type list in EHLO +* Don't set name or filename properties on MIME parts that don't have one + +## Version 5.2.10 (May 4th 2015) +* Add custom header getter +* Use `application/javascript` for .js attachments +* Improve RFC2821 compliance for timelimits, especially for end-of-data +* Add Azerbaijani translations (Thanks to @mirjalal) +* Minor code cleanup for robustness +* Add Indonesian translations (Thanks to @ceceprawiro) +* Avoid `error_log` Debugoutput naming clash +* Add ability to parse server capabilities in response to EHLO (useful for SendGrid etc) +* Amended default values for WordWrap to match RFC +* Remove html2text converter class (has incompatible license) +* Provide new mechanism for injecting html to text converters +* Improve pointers to docs and support in README +* Add example file upload script +* Refactor and major cleanup of EasyPeasyICS, now a lot more usable +* Make set() method simpler and more reliable +* Add Malay translation (Thanks to @nawawi) +* Add Bulgarian translation (Thanks to @mialy) +* Add Armenian translation (Thanks to Hrayr Grigoryan) +* Add Slovenian translation (Thanks to Klemen Tušar) +* More efficient word wrapping +* Add support for S/MIME signing with additional CA certificate (thanks to @IgitBuh) +* Fix incorrect MIME structure when using S/MIME signing and isMail() (#372) +* Improved checks and error messages for missing extensions +* Store and report SMTP errors more consistently +* Add MIME multipart preamble for better Outlook compatibility +* Enable TLS encryption automatically if the server offers it +* Provide detailed errors when individual recipients fail +* Report more errors when connecting +* Add extras classes to composer classmap +* Expose stream_context_create options via new SMTPOptions property +* Automatic encoding switch to quoted-printable if message lines are too long +* Add Korean translation (Thanks to @ChalkPE) +* Provide a pointer to troubleshooting docs on SMTP connection failure + ## Version 5.2.9 (Sept 25th 2014) * **Important: The autoloader is no longer autoloaded by the PHPMailer class** * Update html2text from https://github.com/mtibben/html2text @@ -64,7 +117,7 @@ * Better default behaviour for validateAddress ## Version 5.2.7 (September 12th 2013) -* Add Ukranian translation from @Krezalis +* Add Ukrainian translation from @Krezalis * Support for do_verp * Fix bug in CRAM-MD5 AUTH * Propagate Debugoutput option to SMTP class (@Reblutus) @@ -502,7 +555,7 @@ ## Version 1.15 (Fri, Jun 15 2001) Note: these changes contributed by Patrice Fournier * Changed all remaining \n to \r\n -* Bcc: header no longer writen to message except +* Bcc: header no longer written to message except when sent directly to sendmail * Added a small message to non-MIME compliant mail reader * Added Sender variable to change the Sender email Modified: XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/class.phpmailer.php =================================================================== --- XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/class.phpmailer.php 2015-10-20 00:07:35 UTC (rev 13163) +++ XoopsCore/branches/2.5.x/2.5.8/htdocs/class/mail/phpmailer/class.phpmailer.php 2015-10-20 05:21:53 UTC (rev 13164) @@ -31,14 +31,15 @@ * The PHPMailer Version number. * @type string */ - public $Version = '5.2.9'; + public $Version = '5.2.13'; /** * Email priority. - * Options: 1 = High, 3 = Normal, 5 = low. + * Options: null (default), 1 = High, 3 = Normal, 5 = low. + * When null, the header is not set at all. * @type integer */ - public $Priority = 3; + public $Priority = null; /** * The character set of the message. @@ -149,6 +150,7 @@ /** * Word-wrap the message body to this number of chars. + * Set to 0 to not wrap. A useful value here is 78, for RFC2822 section 2.1.1 compliance. * @type integer */ public $WordWrap = 0; @@ -239,13 +241,21 @@ public $Helo = ''; /** - * The secure connection prefix. - * Options: "", "ssl" or "tls" + * What kind of encryption to use on the SMTP connection. + * Options: '', 'ssl' or 'tls' * @type string */ public $SMTPSecure = ''; /** + * Whether to enable TLS encryption automatically if a server supports it, + * even if `SMTPSecure` is not set to 'tls'. + * Be aware that in PHP >= 5.6 this requires that the server's certificates are valid. + * @type boolean + */ + public $SMTPAutoTLS = true; + + /** * Whether to use SMTP authentication. * Uses the Username and Password properties. * @type boolean @@ -255,6 +265,12 @@ public $SMTPAuth = false; /** + * Options array passed to stream_context_create when connecting via SMTP. + * @type array + */ + public $SMTPOptions = array(); + + /** * SMTP username. * @type string */ @@ -289,9 +305,10 @@ /** * The SMTP server timeout in seconds. + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 * @type integer */ - public $Timeout = 10; + public $Timeout = 300; /** * SMTP class debug output mode. @@ -422,13 +439,24 @@ public $action_function = ''; /** - * What to use in the X-Mailer header. - * Options: null for default, whitespace for none, or a string to use + * What to put in the X-Mailer header. + * Options: An empty string for PHPMailer default, whitespace for none, or a string to use * @type string */ public $XMailer = ''; - + /** + * Only For XOAUTH - Google + * Options: An empty string for PHPMailer default, Enter the email used to get access token + * @type string + */ +// public $UserEmail = ''; +// public $RefreshToken = ''; +// public $ClientId = ''; +// public $ClientSecret = ''; + + + /** * An instance of the SMTP sender class. * @type SMTP * @access protected @@ -465,7 +493,7 @@ /** * An array of all kinds of addresses. - * Includes all of $to, $cc, $bcc, $replyto + * Includes all of $to, $cc, $bcc * @type array * @access protected */ @@ -535,6 +563,13 @@ protected $sign_key_file = ''; /** + * The optional S/MIME extra certificates ("CA Chain") file path. + * @type string + * @access protected + */ + protected $sign_extracerts_file = ''; + + /** * The S/MIME password for the key. * Used only if the key is encrypted. * @type string @@ -550,6 +585,13 @@ protected $exceptions = false; /** + * Unique ID used for message ID and boundaries. + * @type string + * @access protected + */ + protected $uniqueid = ''; + + /** * Error severity: message only, continue processing. */ const STOP_MESSAGE = 0; @@ -570,12 +612,18 @@ const CRLF = "\r\n"; /** + * The maximum line length allowed by RFC 2822 section 2.1.1 + * @type integer + */ + const MAX_LINE_LENGTH = 998; + + /** * Constructor. * @param boolean $exceptions Should we throw external exceptions? */ public function __construct($exceptions = false) { - $this->exceptions = ($exceptions == true); + $this->exceptions = (boolean)$exceptions; } /** @@ -583,7 +631,8 @@ */ public function __destruct() { - if ($this->Mailer == 'smtp') { //close any open SMTP connection nicely + //Close any open SMTP connection nicely + if ($this->Mailer == 'smtp') { $this->smtpClose(); } } @@ -629,7 +678,8 @@ if ($this->SMTPDebug <= 0) { return; } - if (is_callable($this->Debugoutput)) { + //Avoid clash with built-in function names + if (!in_array($this->Debugoutput, array('error_log', 'html', 'echo')) and is_callable($this->Debugoutput)) { call_user_func($this->Debugoutput, $str, $this->SMTPDebug); return; } @@ -815,6 +865,61 @@ } /** + * Parse and validate a string containing one or more RFC822-style comma-separated email addresses + * of the form "display name <address>" into an array of name/address pairs. + * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available. + * Note that quotes in the name part are removed. + * @param string $addrstr The address list string + * @param bool $useimap Whether to use the IMAP extension to parse the list + * @return array + * @link http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation + */ + public function parseAddresses($addrstr, $useimap = true) + { + $addresses = array(); + if ($useimap and function_exists('imap_rfc822_parse_adrlist')) { + //Use this built-in parser if it's available + $list = imap_rfc822_parse_adrlist($addrstr, ''); + foreach ($list as $address) { + if ($address->host != '.SYNTAX-ERROR.') { + if ($this->validateAddress($address->mailbox . '@' . $address->host)) { + $addresses[] = array( + 'name' => (property_exists($address, 'personal') ? $address->personal : ''), + 'address' => $address->mailbox . '@' . $address->host + ); + } + } + } + } else { + //Use this simpler parser + $list = explode(',', $addrstr); + foreach ($list as $address) { + $address = trim($address); + //Is there a separate name part? + if (strpos($address, '<') === false) { + //No separate name, just use the whole thing + if ($this->validateAddress($address)) { + $addresses[] = array( + 'name' => '', + 'address' => $address + ); + } + } else { + list($name, $email) = explode('<', $address); + $email = trim(str_replace('>', '', $email)); + if ($this->validateAddress($email)) { + $addresses[] = array( + 'name' => trim(str_replace(array('"', "'"), '', $name)), + 'address' => $email + ); + } + } + } + } + return $addresses; + } + + /** * Set the From and FromName properties. * @param string $address * @param string $name @@ -992,15 +1097,20 @@ $this->ContentType = 'multipart/alternative'; } - $this->error_count = 0; // reset errors + $this->error_count = 0; // Reset errors $this->setMessageType(); // Refuse to send an empty message unless we are specifically allowing it if (!$this->AllowEmpty and empty($this->Body)) { throw new phpmailerException($this->lang('empty_message'), self::STOP_CRITICAL); } + // Create body before headers in case body makes changes to headers (e.g. altering transfer encoding) + $this->MIMEHeader = ''; + $this->MIMEBody = $this->createBody(); + // createBody may have added some headers, so retain them + $tempheaders = $this->MIMEHeader; $this->MIMEHeader = $this->createHeader(); - $this->MIMEBody = $this->createBody(); + $this->MIMEHeader .= $tempheaders; // To capture the complete message when using mail(), create // an extra header list which createHeader() doesn't fold in @@ -1020,7 +1130,6 @@ if (!empty($this->DKIM_domain) && !empty($this->DKIM_private) && !empty($this->DKIM_selector) - && !empty($this->DKIM_domain) && file_exists($this->DKIM_private)) { $header_dkim = $this->DKIM_Add( $this->MIMEHeader . $this->mailHeader, @@ -1031,7 +1140,6 @@ str_replace("\r\n", "\n", $header_dkim) . self::CRLF; } return true; - } catch (phpmailerException $exc) { $this->setError($exc->getMessage()); if ($this->exceptions) { @@ -1101,7 +1209,7 @@ $sendmail = sprintf('%s -oi -t', escapeshellcmd($this->Sendmail)); } } - if ($this->SingleTo === true) { + if ($this->SingleTo) { foreach ($this->SingleToArray as $toAddr) { if (!@$mail = popen($sendmail, 'w')) { throw new phpmailerException($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); @@ -1165,7 +1273,7 @@ ini_set('sendmail_from', $this->Sender); } $result = false; - if ($this->SingleTo === true && count($toArr) > 1) { + if ($this->SingleTo && count($toArr) > 1) { foreach ($toArr as $toAddr) { $result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params); $this->doCallback($result, array($toAddr), $this->cc, $this->bcc, $this->Subject, $body, $this->From); @@ -1211,58 +1319,51 @@ protected function smtpSend($header, $body) { $bad_rcpt = array(); - - if (!$this->smtpConnect()) { + if (!$this->smtpConnect($this->SMTPOptions)) { throw new phpmailerException($this->lang('smtp_connect_failed'), self::STOP_CRITICAL); } - $smtp_from = ($this->Sender == '') ? $this->From : $this->Sender; + if ('' == $this->Sender) { + $smtp_from = $this->From; + } else { + $smtp_from = $this->Sender; + } if (!$this->smtp->mail($smtp_from)) { $this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError())); throw new phpmailerException($this->ErrorInfo, self::STOP_CRITICAL); } // Attempt to send to all recipients - foreach ($this->to as $to) { - if (!$this->smtp->recipient($to[0])) { - $bad_rcpt[] = $to[0]; - $isSent = false; - } else { - $isSent = true; + foreach (array($this->to, $this->cc, $this->bcc) as $togroup) { + foreach ($togroup as $to) { + if (!$this->smtp->recipient($to[0])) { + $error = $this->smtp->getError(); + $bad_rcpt[] = array('to' => $to[0], 'error' => $error['detail']); + $isSent = false; + } else { + $isSent = true; + } + $this->doCallback($isSent, array($to[0]), array(), array(), $this->Subject, $body, $this->From); } - $this->doCallback($isSent, array($to[0]), array(), array(), $this->Subject, $body, $this->From); } - foreach ($this->cc as $cc) { - if (!$this->smtp->recipient($cc[0])) { - $bad_rcpt[] = $cc[0]; - $isSent = false; - } else { - $isSent = true; - } - $this->doCallback($isSent, array(), array($cc[0]), array(), $this->Subject, $body, $this->From); - } - foreach ($this->bcc as $bcc) { - if (!$this->smtp->recipient($bcc[0])) { - $bad_rcpt[] = $bcc[0]; - $isSent = false; - } else { - $isSent = true; - } - $this->doCallback($isSent, array(), array(), array($bcc[0]), $this->Subject, $body, $this->From); - } // Only send the DATA command if we have viable recipients if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) { throw new phpmailerException($this->lang('data_not_accepted'), self::STOP_CRITICAL); } - if ($this->SMTPKeepAlive == true) { + if ($this->SMTPKeepAlive) { $this->smtp->reset(); } else { $this->smtp->quit(); $this->smtp->close(); } - if (count($bad_rcpt) > 0) { // Create error message for any bad addresses + //Create error message for any bad addresses + if (count($bad_rcpt) > 0) { + $errstr = ''; + foreach ($bad_rcpt as $bad) { + $errstr .= $bad['to'] . ': ' . $bad['error']; + } throw new phpmailerException( - $this->lang('recipients_failed') . implode(', ', $bad_rcpt), + $this->lang('recipients_failed') . $errstr, self::STOP_CONTINUE ); } @@ -1283,7 +1384,7 @@ if (is_null($this->smtp)) { $this->smtp = $this->getSMTPInstance(); } - + // Already connected? if ($this->smtp->connected()) { return true; @@ -1308,14 +1409,25 @@ // The host string prefix can temporarily override the current setting for SMTPSecure // If it's not specified, the default value is used $prefix = ''; + $secure = $this->SMTPSecure; $tls = ($this->SMTPSecure == 'tls'); - if ($hostinfo[2] == 'ssl' or ($hostinfo[2] == '' and $this->SMTPSecure == 'ssl')) { + if ('ssl' == $hostinfo[2] or ('' == $hostinfo[2] and 'ssl' == $this->SMTPSecure)) { $prefix = 'ssl://'; - $tls = false; // Can't have SSL and TLS at once + $tls = false; // Can't have SSL and TLS at the same time + $secure = 'ssl'; } elseif ($hostinfo[2] == 'tls') { $tls = true; // tls doesn't use a prefix + $secure = 'tls'; } + //Do we need the OpenSSL extension? + $sslext = defined('OPENSSL_ALGO_SHA1'); + if ('tls' === $secure or 'ssl' === $secure) { + //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled + if (!$sslext) { + throw new phpmailerException($this->lang('extension_missing').'openssl', self::STOP_CRITICAL); + } + } $host = $hostinfo[3]; $port = $this->Port; $tport = (integer)$hostinfo[4]; @@ -1330,7 +1442,14 @@ $hello = $this->serverHostname(); } $this->smtp->hello($hello); - + //Automatically enable TLS encryption if: + // * it's not disabled + // * we have openssl extension + // * we are not already using SSL + // * the server offers STARTTLS + if ($this->SMTPAutoTLS and $sslext and $secure != 'ssl' and $this->smtp->getServerExt('STARTTLS')) { + $tls = true; + } if ($tls) { if (!$this->smtp->startTLS()) { throw new phpmailerException($this->lang('connect_host')); @@ -1340,10 +1459,10 @@ } if ($this->SMTPAuth) { if (!$this->smtp->authenticate( - $this->Username, - $this->Password, - $this->AuthType, - $this->Realm, + $this->Username, + $this->Password, + $this->AuthType, + $this->Realm, $this->Workstation ) ) { @@ -1353,6 +1472,7 @@ return true; } catch (phpmailerException $exc) { $lastexception = $exc; + $this->edebug($exc->getMessage()); // We must have connected, but then failed TLS or Auth, so close connection nicely $this->smtp->quit(); } @@ -1411,7 +1531,8 @@ 'signing' => 'Signing Error: ', 'smtp_connect_failed' => 'SMTP connect() failed.', 'smtp_error' => 'SMTP server error: ', - 'variable_set' => 'Cannot set or reset variable: ' + 'variable_set' => 'Cannot set or reset variable: ', + 'extension_missing' => 'Extension missing: ' ); if (empty($lang_path)) { // Calculate an absolute path so it can work if CWD is not here @@ -1419,18 +1540,19 @@ } $foundlang = true; $lang_file = $lang_path . 'phpmailer.lang-' . $langcode . '.php'; - if ($langcode != 'en') { // There is no English translation file + // There is no English translation file + if ($langcode != 'en') { // Make sure language file path is readable if (!is_readable($lang_file)) { $foundlang = false; } else { // Overwrite language-specific strings. - // This way we'll never have missing translations. + // This way we'll never have missing translation keys. $foundlang = include $lang_file; } } $this->language = $PHPMAILER_LANG; - return ($foundlang == true); // Returns false if language not found + return (boolean)$foundlang; // Returns false if language not found } /** @@ -1492,7 +1614,11 @@ */ public function wrapText($message, $length, $qp_mode = false) { - $soft_break = ($qp_mode) ? sprintf(' =%s', $this->LE) : $this->LE; + if ($qp_mode) { + $soft_break = sprintf(' =%s', $this->LE); + } else { + $soft_break = $this->LE; + } // If utf-8 encoding is used, we will need to make sure we don't // split multibyte characters when we wrap $is_utf8 = (strtolower($this->CharSet) == 'utf-8'); @@ -1500,20 +1626,23 @@ $crlflen = strlen(self::CRLF); $message = $this->fixEOL($message); + //Remove a trailing line break if (substr($message, -$lelen) == $this->LE) { $message = substr($message, 0, -$lelen); } - $line = explode($this->LE, $message); // Magic. We know fixEOL uses $LE + //Split message into lines + $lines = explode($this->LE, $message); + //Message will be rebuilt in here $message = ''; - for ($i = 0; $i < count($line); $i++) { - $line_part = explode(' ', $line[$i]); + foreach ($lines as $line) { + $words = explode(' ', $line); $buf = ''; - for ($e = 0; $e < count($line_part); $e++) { - $word = $line_part[$e]; + $firstword = true; + foreach ($words as $word) { if ($qp_mode and (strlen($word) > $length)) { $space_left = $length - strlen($buf) - $crlflen; - if ($e != 0) { + if (!$firstword) { if ($space_left > 20) { $len = $space_left; if ($is_utf8) { @@ -1555,13 +1684,17 @@ } } else { $buf_o = $buf; - $buf .= ($e == 0) ? $word : (' ' . $word); + if (!$firstword) { + $buf .= ' '; + } + $buf .= $word; if (strlen($buf) > $length and $buf_o != '') { $message .= $buf_o . $soft_break; $buf = $word; } } + $firstword = false; } $message .= $buf . self::CRLF; } @@ -1571,11 +1704,11 @@ /** * Find the last character boundary prior to $maxLength in a utf-8 - * quoted (printable) encoded string. + * quoted-printable encoded string. * Original written by Colin Brown. * @access public * @param string $encodedText utf-8 QP text - * @param integer $maxLength find last character boundary prior to this length + * @param integer $maxLength Find the last character boundary prior to this length * @return integer */ public function utf8CharBoundary($encodedText, $maxLength) @@ -1585,22 +1718,26 @@ while (!$foundSplitPos) { $lastChunk = substr($encodedText, $maxLength - $lookBack, $lookBack); $encodedCharPos = strpos($lastChunk, '='); - if ($encodedCharPos !== false) { + if (false !== $encodedCharPos) { // Found start of encoded character byte within $lookBack block. // Check the encoded byte value (the 2 chars after the '=') $hex = substr($encodedText, $maxLength - $lookBack + $encodedCharPos + 1, 2); $dec = hexdec($hex); - if ($dec < 128) { // Single byte character. + if ($dec < 128) { + // Single byte character. // If the encoded char was found at pos 0, it will fit // otherwise reduce maxLength to start of the encoded char - $maxLength = ($encodedCharPos == 0) ? $maxLength : - $maxLength - ($lookBack - $encodedCharPos); + if ($encodedCharPos > 0) { + $maxLength = $maxLength - ($lookBack - $encodedCharPos); + } $foundSplitPos = true; - } elseif ($dec >= 192) { // First byte of a multi byte character + } elseif ($dec >= 192) { + // First byte of a multi byte character // Reduce maxLength to split at start of character $maxLength = $maxLength - ($lookBack - $encodedCharPos); $foundSplitPos = true; - } elseif ($dec < 192) { // Middle byte of a multi byte character, look further back + } elseif ($dec < 192) { + // Middle byte of a multi byte character, look further back $lookBack += 3; } } else { @@ -1612,7 +1749,10 @@ } /** - * Set the body wrapping. + * Apply word wrapping to the message body. + * Wraps the message body to the number of chars set in the WordWrap property. + * You should only do this to plain-text bodies as wrapping HTML tags may break them. + * This is called automatically by createBody(), so you don't need to call it yourself. * @access public * @return void */ @@ -1644,12 +1784,6 @@ { $result = ''; - // Set the boundaries - $uniq_id = md5(uniqid(time())); - $this->boundary[1] = 'b1_' . $uniq_id; - $this->boundary[2] = 'b2_' . $uniq_id; - $this->boundary[3] = 'b3_' . $uniq_id; - if ($this->MessageDate == '') { $this->MessageDate = self::rfcDate(); } @@ -1657,7 +1791,7 @@ // To be created automatically by mail() - if ($this->SingleTo === true) { + if ($this->SingleTo) { if ($this->Mailer != 'mail') { foreach ($this->to as $toaddr) { $this->SingleToArray[] = $this->addrFormat($toaddr); @@ -1701,10 +1835,12 @@ if ($this->MessageID != '') { $this->lastMessageID = $this->MessageID; } else { - $this->lastMessageID = sprintf('<%s@%s>', $uniq_id, $this->ServerHostname()); + $this->lastMessageID = sprintf('<%s@%s>', $this->uniqueid, $this->ServerHostname()); } - $result .= $this->HeaderLine('Message-ID', $this->lastMessageID); - $result .= $this->headerLine('X-Priority', $this->Priority); + $result .= $this->headerLine('Message-ID', $this->lastMessageID); + if (!is_null($this->Priority)) { + $result .= $this->headerLine('X-Priority', $this->Priority); + } if ($this->XMailer == '') { $result .= $this->headerLine( 'X-Mailer', @@ -1722,10 +1858,10 @@ } // Add custom headers - for ($index = 0; $index < count($this->CustomHeader); $index++) { + foreach ($this->CustomHeader as $header) { $result .= $this->headerLine( - trim($this->CustomHeader[$index][0]), - $this->encodeHeader(trim($this->CustomHeader[$index][1])) + trim($header[0]), + $this->encodeHeader(trim($header[1])) ); } if (!$this->sign_key_file) { @@ -1801,7 +1937,6 @@ return $this->MIMEHeader . $this->mailHeader . self::CRLF . $this->MIMEBody; } - /** * Assemble the message body. * Returns an empty string on failure. @@ -1812,6 +1947,11 @@ public function createBody() { $body = ''; + //Create unique IDs and preset boundaries + $this->uniqueid = md5(uniqid(time())); + $this->boundary[1] = 'b1_' . $this->uniqueid; + $this->boundary[2] = 'b2_' . $this->uniqueid; + $this->boundary[3] = 'b3_' . $this->uniqueid; if ($this->sign_key_file) { $body .= $this->getMailMIME() . $this->LE; @@ -1821,30 +1961,48 @@ $bodyEncoding = $this->Encoding; $bodyCharSet = $this->CharSet; + //Can we do a 7-bit downgrade? if ($bodyEncoding == '8bit' and !$this->has8bitChars($this->Body)) { $bodyEncoding = '7bit'; $bodyCharSet = 'us-ascii'; } + //If lines are too long, and we're not already using an encoding that will shorten them, + //change to quoted-printable transfer encoding + if ('base64' != $this->Encoding and self::hasLineLongerThanMax($this->Body)) { + $this->Encoding = 'quoted-printable'; + $bodyEncoding = 'quoted-printable'; + } + $altBodyEncoding = $this->Encoding; $altBodyCharSet = $this->CharSet; + //Can we do a 7-bit downgrade? if ($altBodyEncoding == '8bit' and !$this->has8bitChars($this->AltBody)) { $altBodyEncoding = '7bit'; $altBodyCharSet = 'us-ascii'; } + //If lines are too long, change to quoted-printable transfer encoding + if (self::hasLineLongerThanMax($this->AltBody)) { + $altBodyEncoding = 'quoted-printable'; + } + //Use this as a preamble in all multipart message types + $mimepre = "This is a multi-part message in MIME format." . $this->LE . $this->LE; switch ($this->message_type) { case 'inline': + $body .= $mimepre; $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding); $body .= $this->encodeString($this->Body, $bodyEncoding); $body .= $this->LE . $this->LE; $body .= $this->attachAll('inline', $this->boundary[1]); break; case 'attach': + $body .= $mimepre; $body .= $this->getBoundary($this->boundary[1], $bodyCharSet, '', $bodyEncoding); $body .= $this->encodeString($this->Body, $bodyEncoding); $body .= $this->LE . $this->LE; $body .= $this->attachAll('attachment', $this->boundary[1]); break; case 'inline_attach': + $body .= $mimepre; $body .= $this->textLine('--' . $this->boundary[1]); $body .= $this->headerLine('Content-Type', 'multipart/related;'); $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); @@ -1857,6 +2015,7 @@ $body .= $this->attachAll('attachment', $this->boundary[1]); break; case 'alt': + $body .= $mimepre; $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding); $body .= $this->encodeString($this->AltBody, $altBodyEncoding); $body .= $this->LE . $this->LE; @@ -1871,6 +2030,7 @@ $body .= $this->endBoundary($this->boundary[1]); break; case 'alt_inline': + $body .= $mimepre; $body .= $this->getBoundary($this->boundary[1], $altBodyCharSet, 'text/plain', $altBodyEncoding); $body .= $this->encodeString($this->AltBody, $altBodyEncoding); $body .= $this->LE . $this->LE; @@ -1886,6 +2046,7 @@ $body .= $this->endBoundary($this->boundary[1]); break; case 'alt_attach': + $body .= $mimepre; $body .= $this->textLine('--' . $this->boundary[1]); $body .= $this->headerLine('Content-Type', 'multipart/alternative;'); $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); @@ -1901,6 +2062,7 @@ $body .= $this->attachAll('attachment', $this->boundary[1]); break; case 'alt_inline_attach': + $body .= $mimepre; $body .= $this->textLine('--' . $this->boundary[1]); $body .= $this->headerLine('Content-Type', 'multipart/alternative;'); $body .= $this->textLine("\tboundary=\"" . $this->boundary[2] . '"'); @@ -1932,23 +2094,42 @@ } elseif ($this->sign_key_file) { try { if (!defined('PKCS7_TEXT')) { - throw new phpmailerException($this->lang('signing') . ' OpenSSL extension missing.'); + throw new phpmailerException($this->lang('extension_missing') . 'openssl'); } // @TODO would be nice to use php://temp streams here, but need to wrap for PHP < 5.1 $file = tempnam(sys_get_temp_dir(), 'mail'); - file_put_contents($file, $body); // @TODO check this worked + if (false === file_put_contents($file, $body)) { + throw new phpmailerException($this->lang('signing') . ' Could not write temp file'); + } $signed = tempnam(sys_get_temp_dir(), 'signed'); - if (@openssl_pkcs7_sign( - $file, - $signed, - 'file://' . realpath($this->sign_cert_file), - array('file://' . realpath($this->sign_key_file), $this->sign_key_pass), - null - ) - ) { + //Workaround for PHP bug https://bugs.php.net/bug.php?id=69197 + if (empty($this->sign_extracerts_file)) { + $sign = @openssl_pkcs7_sign( + $file, + $signed, + 'file://' . realpath($this->sign_cert_file), + array('file://' . realpath($this->sign_key_file), $this->sign_key_pass), + null + ); + } else { + $sign = @openssl_pkcs7_sign( + $file, + $signed, + 'file://' . realpath($this->sign_cert_file), + array('file://' . realpath($this->sign_key_file), $this->sign_key_pass), + null, + PKCS7_DETACHED, + $this->sign_extracerts_file + ); + } + if ($sign) { @unlink($file); $body = file_get_contents($signed); @unlink($signed); + //The message returned by openssl contains both headers and body, so need to split them up + $parts = explode("\n\n", $body, 2); + $this->MIMEHeader .= $parts[0] . $this->LE . $this->LE; + $body = $parts[1]; } else { @unlink($file); @unlink($signed); @@ -2160,12 +2341,21 @@ $cidUniq[$cid] = true; $mime[] = sprintf('--%s%s', $boundary, $this->LE); - $mime[] = sprintf( - 'Content-Type: %s; name="%s"%s', - $type, - $this->encodeHeader($this->secureHeader($name)), - $this->LE - ); + //Only include a filename property if we have one + if (!empty($name)) { + $mime[] = sprintf( + 'Content-Type: %s; name="%s"%s', + $type, + $this->encodeHeader($this->secureHeader($name)), + $this->LE + ); + } else { + $mime[] = sprintf( + 'Content-Type: %s%s', + $type, + $this->LE + ); + } // RFC1341 part 5 says 7bit is assumed if not specified if ($encoding != '7bit') { $mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, $this->LE); @@ -2189,12 +2379,20 @@ $this->LE . $this->LE ); } else { - $mime[] = sprintf( - 'Content-Disposition: %s; filename=%s%s', - $disposition, - $encoded_name, - $this->LE . $this->LE - ); + if (!empty($encoded_name)) { + $mime[] = sprintf( + 'Content-Disposition: %s; filename=%s%s', + $disposition, + $encoded_name, + $this->LE . $this->LE + ); + } else { + $mime[] = sprintf( + 'Content-Disposition: %s%s', + $disposition, + $this->LE . $this->LE + ); + } } } else { $mime[] = $this->LE; @@ -2246,7 +2444,7 @@ //Doesn't exist in PHP 5.4, but we don't need to check because //get_magic_quotes_runtime always returns false in 5.4+ //so it will never get here - ini_set('magic_quotes_runtime', 0); + ini_set('magic_quotes_runtime', false); } } $file_buffer = file_get_contents($path); @@ -2255,7 +2453,7 @@ if (version_compare(PHP_VERSION, '5.3.0', '<')) { set_magic_quotes_runtime($magic_quotes); } else { - ini_set('magic_quotes_runtime', ($magic_quotes?'1':'0')); + ini_set('magic_quotes_runtime', $magic_quotes); } } return $file_buffer; @@ -2335,7 +2533,8 @@ break; } - if ($matchcount == 0) { // There are no chars that need encoding + //There are no chars that need encoding + if ($matchcount == 0) { return ($str); } @@ -2445,8 +2644,9 @@ */ public function encodeQP($string, $line_max = 76) { - if (function_exists('quoted_printable_encode')) { // Use native function if it's available (>= PHP5.3) - return $this->fixEOL(quoted_printable_encode($string)); + // Use native function if it's available (>= PHP5.3) + if (function_exists('quoted_printable_encode')) { + return quoted_printable_encode($string); } // Fall back to a pure PHP implementation $string = str_replace( @@ -2454,8 +2654,7 @@ array(' ', "\r\n=2E", "\r\n", '='), rawurlencode($string) ); - $string = preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string); - return $this->fixEOL($string); + return preg_replace('/[^\r\n]{' . ($line_max - 3) . '}[^=\r\n]{2}/', "$0=\r\n", $string); } /** @@ -2512,7 +2711,7 @@ // If the string contains an '=', make sure it's the first thing we replace // so as to avoid double-encoding $eqkey = array_search('=', $matches[0]); - if ($eqkey !== false) { + if (false !== $eqkey) { unset($matches[0][$eqkey]); array_unshift($matches[0], '='); } @@ -2563,7 +2762,7 @@ /** * Add an embedded (inline) attachment from a file. * This can include images, sounds, and just about any other document type. - * These differ from 'regular' attachmants in that they are intended to be + * These differ from 'regular' attachments in that they are intended to be * displayed inline with the message, not just attached for download. * This is used in HTML messages that embed the images * the HTML refers to using the $cid value. @@ -2630,7 +2829,7 @@ $disposition = 'inline' ) { // If a MIME type is not specified, try to work it out from the name - if ($type == '') { + if ($type == '' and !empty($name)) { $type = self::filenameToType($name); } @@ -2772,8 +2971,17 @@ $this->error_count++; if ($this->Mailer == 'smtp' and !is_null($this->smtp)) { $lasterror = $this->smtp->getError(); - if (!empty($lasterror) and array_key_exists('smtp_msg', $lasterror)) { - $msg .= '<p>' . $this->lang('smtp_error') . $lasterror['smtp_msg'] . "</p>\n"; + if (!empty($lasterror['error'])) { + $msg .= $this->lang('smtp_error') . $lasterror['error'];... [truncated message content] |