From 31493b6732733c961e62cee1b1991b5d389d209f Mon Sep 17 00:00:00 2001 From: Marcus Bointon Date: Thu, 7 Sep 2017 18:21:09 +0200 Subject: [PATCH] Big cleanup for Symfony coding style and php-cs-fixer, see #1148 --- composer.json | 3 +- composer.lock | 513 +++++++++++++++++++++- examples/DKIM_gen_keys.phps | 4 +- examples/callback.phps | 13 +- examples/extending.phps | 8 +- examples/gmail.phps | 3 +- examples/gmail_xoauth.phps | 26 +- examples/mailing_list.phps | 4 +- examples/simple_contact_form.phps | 10 +- examples/smtp_low_memory.phps | 2 + examples/ssl_options.phps | 8 +- get_oauth_token.php | 2 +- src/Exception.php | 11 +- src/OAuth.php | 16 +- src/PHPMailer.php | 700 +++++++++++++++++------------- src/POP3.php | 71 +-- src/SMTP.php | 214 +++++---- test/bootstrap.php | 2 +- test/phpmailerLangTest.php | 18 +- test/phpmailerTest.php | 197 +++++---- test/testbootstrap-dist.php | 1 + 21 files changed, 1248 insertions(+), 578 deletions(-) diff --git a/composer.json b/composer.json index 593c27833..383c84406 100644 --- a/composer.json +++ b/composer.json @@ -29,7 +29,8 @@ "zendframework/zend-serializer": "2.7.*", "doctrine/annotations": "1.2.*", "zendframework/zend-eventmanager": "3.0.*", - "zendframework/zend-i18n": "2.7.3" + "zendframework/zend-i18n": "2.7.3", + "friendsofphp/php-cs-fixer": "^2.2" }, "suggest": { "psr/log": "For optional PSR-3 debug logging", diff --git a/composer.lock b/composer.lock index 21f017dd7..e972e93d3 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "content-hash": "c83b5cea4ea6633422ee7d0ce4f621b2", + "content-hash": "8067184a7c98f5da35efc75d4cf96446", "packages": [], "packages-dev": [ { @@ -374,17 +374,145 @@ ], "time": "2017-03-29T16:04:15+00:00" }, + { + "name": "friendsofphp/php-cs-fixer", + "version": "v2.2.6", + "source": { + "type": "git", + "url": "https://github.com/FriendsOfPHP/PHP-CS-Fixer.git", + "reference": "c1cc52c242f17c4d52d9601159631da488fac7a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/FriendsOfPHP/PHP-CS-Fixer/zipball/c1cc52c242f17c4d52d9601159631da488fac7a4", + "reference": "c1cc52c242f17c4d52d9601159631da488fac7a4", + "shasum": "" + }, + "require": { + "doctrine/annotations": "^1.2", + "ext-json": "*", + "ext-tokenizer": "*", + "gecko-packages/gecko-php-unit": "^2.0", + "php": "^5.3.6 || >=7.0 <7.2", + "sebastian/diff": "^1.4", + "symfony/console": "^2.4 || ^3.0", + "symfony/event-dispatcher": "^2.1 || ^3.0", + "symfony/filesystem": "^2.4 || ^3.0", + "symfony/finder": "^2.2 || ^3.0", + "symfony/options-resolver": "^2.6 || ^3.0", + "symfony/polyfill-php54": "^1.0", + "symfony/polyfill-php55": "^1.3", + "symfony/polyfill-php70": "^1.0", + "symfony/polyfill-php72": "^1.4", + "symfony/process": "^2.3 || ^3.0", + "symfony/stopwatch": "^2.5 || ^3.0" + }, + "conflict": { + "hhvm": "<3.18" + }, + "require-dev": { + "johnkary/phpunit-speedtrap": "^1.0.1", + "justinrainbow/json-schema": "^5.0", + "phpunit/phpunit": "^4.8.35 || ^5.4.3", + "satooshi/php-coveralls": "^1.0", + "symfony/phpunit-bridge": "^3.2.2" + }, + "suggest": { + "ext-mbstring": "For handling non-UTF8 characters in cache signature.", + "symfony/polyfill-mbstring": "When enabling `ext-mbstring` is not possible." + }, + "bin": [ + "php-cs-fixer" + ], + "type": "application", + "extra": { + "branch-alias": { + "dev-master": "2.2-dev" + } + }, + "autoload": { + "psr-4": { + "PhpCsFixer\\": "src/" + }, + "classmap": [ + "tests/Test/AbstractFixerTestCase.php", + "tests/Test/AbstractIntegrationTestCase.php", + "tests/Test/IntegrationCase.php", + "tests/Test/IntegrationCaseFactory.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Dariusz Rumiński", + "email": "dariusz.ruminski@gmail.com" + }, + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + } + ], + "description": "A tool to automatically fix PHP code style", + "time": "2017-08-22T14:08:16+00:00" + }, + { + "name": "gecko-packages/gecko-php-unit", + "version": "v2.2", + "source": { + "type": "git", + "url": "https://github.com/GeckoPackages/GeckoPHPUnit.git", + "reference": "ab525fac9a9ffea219687f261b02008b18ebf2d1" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/GeckoPackages/GeckoPHPUnit/zipball/ab525fac9a9ffea219687f261b02008b18ebf2d1", + "reference": "ab525fac9a9ffea219687f261b02008b18ebf2d1", + "shasum": "" + }, + "require": { + "php": "^5.3.6 || ^7.0" + }, + "require-dev": { + "phpunit/phpunit": "^4.8.35 || ^5.4.3" + }, + "suggest": { + "ext-dom": "When testing with xml.", + "ext-libxml": "When testing with xml.", + "phpunit/phpunit": "This is an extension for it so make sure you have it some way." + }, + "type": "library", + "autoload": { + "psr-4": { + "GeckoPackages\\PHPUnit\\": "src/PHPUnit" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "Additional PHPUnit asserts and constraints.", + "homepage": "https://github.com/GeckoPackages", + "keywords": [ + "extension", + "filesystem", + "phpunit" + ], + "time": "2017-08-23T07:39:54+00:00" + }, { "name": "herrera-io/json", "version": "1.0.3", "source": { "type": "git", - "url": "https://github.com/kherge-abandoned/php-json.git", + "url": "https://github.com/kherge-php/json.git", "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/kherge-abandoned/php-json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1", + "url": "https://api.github.com/repos/kherge-php/json/zipball/60c696c9370a1e5136816ca557c17f82a6fa83f1", "reference": "60c696c9370a1e5136816ca557c17f82a6fa83f1", "shasum": "" }, @@ -433,6 +561,7 @@ "schema", "validate" ], + "abandoned": "kherge/json", "time": "2013-10-30T16:51:34+00:00" }, { @@ -491,8 +620,51 @@ "phar", "update" ], + "abandoned": true, "time": "2013-10-30T17:23:01+00:00" }, + { + "name": "ircmaxell/password-compat", + "version": "v1.0.4", + "source": { + "type": "git", + "url": "https://github.com/ircmaxell/password_compat.git", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ircmaxell/password_compat/zipball/5c5cde8822a69545767f7c7f3058cb15ff84614c", + "reference": "5c5cde8822a69545767f7c7f3058cb15ff84614c", + "shasum": "" + }, + "require-dev": { + "phpunit/phpunit": "4.*" + }, + "type": "library", + "autoload": { + "files": [ + "lib/password.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Anthony Ferrara", + "email": "ircmaxell@php.net", + "homepage": "http://blog.ircmaxell.com" + } + ], + "description": "A compatibility library for the proposed simplified password hashing algorithm: https://wiki.php.net/rfc/password_hash", + "homepage": "https://github.com/ircmaxell/password_compat", + "keywords": [ + "hashing", + "password" + ], + "time": "2014-11-20T16:49:30+00:00" + }, { "name": "jms/metadata", "version": "1.6.0", @@ -765,6 +937,7 @@ ], "description": "A parsing and comparison library for semantic versioning.", "homepage": "http://github.com/kherge/Version", + "abandoned": true, "time": "2012-08-16T17:13:03+00:00" }, { @@ -890,6 +1063,54 @@ ], "time": "2015-09-19T14:15:08+00:00" }, + { + "name": "paragonie/random_compat", + "version": "v2.0.10", + "source": { + "type": "git", + "url": "https://github.com/paragonie/random_compat.git", + "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/random_compat/zipball/634bae8e911eefa89c1abfbf1b66da679ac8f54d", + "reference": "634bae8e911eefa89c1abfbf1b66da679ac8f54d", + "shasum": "" + }, + "require": { + "php": ">=5.2.0" + }, + "require-dev": { + "phpunit/phpunit": "4.*|5.*" + }, + "suggest": { + "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes." + }, + "type": "library", + "autoload": { + "files": [ + "lib/random.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com", + "homepage": "https://paragonie.com" + } + ], + "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7", + "keywords": [ + "csprng", + "pseudorandom", + "random" + ], + "time": "2017-03-13T16:27:32+00:00" + }, { "name": "phpcollection/phpcollection", "version": "0.5.0", @@ -1738,7 +1959,9 @@ "authors": [ { "name": "Fabien Potencier", - "email": "fabien@symfony.com" + "email": "fabien@symfony.com", + "homepage": "http://fabien.potencier.org", + "role": "Lead Developer" } ], "description": "Pimple is a simple Dependency Injection Container for PHP 5.3", @@ -2598,6 +2821,60 @@ "homepage": "https://symfony.com", "time": "2017-06-01T20:52:29+00:00" }, + { + "name": "symfony/options-resolver", + "version": "v3.3.8", + "source": { + "type": "git", + "url": "https://github.com/symfony/options-resolver.git", + "reference": "ee4e22978fe885b54ee5da8c7964f0a5301abfb6" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/ee4e22978fe885b54ee5da8c7964f0a5301abfb6", + "reference": "ee4e22978fe885b54ee5da8c7964f0a5301abfb6", + "shasum": "" + }, + "require": { + "php": "^5.5.9|>=7.0.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.3-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Component\\OptionsResolver\\": "" + }, + "exclude-from-classmap": [ + "/Tests/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fabien Potencier", + "email": "fabien@symfony.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony OptionsResolver Component", + "homepage": "https://symfony.com", + "keywords": [ + "config", + "configuration", + "options" + ], + "time": "2017-07-29T21:54:42+00:00" + }, { "name": "symfony/polyfill-mbstring", "version": "v1.4.0", @@ -2657,6 +2934,234 @@ ], "time": "2017-06-09T14:24:12+00:00" }, + { + "name": "symfony/polyfill-php54", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php54.git", + "reference": "b7763422a5334c914ef0298ed21b253d25913a6e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php54/zipball/b7763422a5334c914ef0298ed21b253d25913a6e", + "reference": "b7763422a5334c914ef0298ed21b253d25913a6e", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php54\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 5.4+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2017-06-14T15:44:48+00:00" + }, + { + "name": "symfony/polyfill-php55", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php55.git", + "reference": "29b1381d66f16e0581aab0b9f678ccf073288f68" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php55/zipball/29b1381d66f16e0581aab0b9f678ccf073288f68", + "reference": "29b1381d66f16e0581aab0b9f678ccf073288f68", + "shasum": "" + }, + "require": { + "ircmaxell/password-compat": "~1.0", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php55\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 5.5+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2017-06-14T15:44:48+00:00" + }, + { + "name": "symfony/polyfill-php70", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php70.git", + "reference": "b6482e68974486984f59449ecea1fbbb22ff840f" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php70/zipball/b6482e68974486984f59449ecea1fbbb22ff840f", + "reference": "b6482e68974486984f59449ecea1fbbb22ff840f", + "shasum": "" + }, + "require": { + "paragonie/random_compat": "~1.0|~2.0", + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php70\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2017-06-14T15:44:48+00:00" + }, + { + "name": "symfony/polyfill-php72", + "version": "v1.5.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php72.git", + "reference": "8abc9097f5001d310f0edba727469c988acc6ea7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php72/zipball/8abc9097f5001d310f0edba727469c988acc6ea7", + "reference": "8abc9097f5001d310f0edba727469c988acc6ea7", + "shasum": "" + }, + "require": { + "php": ">=5.3.3" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.5-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php72\\": "" + }, + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 7.2+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "time": "2017-07-11T13:25:55+00:00" + }, { "name": "symfony/process", "version": "v2.8.22", diff --git a/examples/DKIM_gen_keys.phps b/examples/DKIM_gen_keys.phps index 7c2dbff57..f732c173d 100644 --- a/examples/DKIM_gen_keys.phps +++ b/examples/DKIM_gen_keys.phps @@ -40,7 +40,7 @@ if (file_exists($privatekeyfile)) { [ 'digest_alg' => 'sha256', 'private_key_bits' => 2048, - 'private_key_type' => OPENSSL_KEYTYPE_RSA + 'private_key_type' => OPENSSL_KEYTYPE_RSA, ] ); //Save private key @@ -71,7 +71,7 @@ $publickey = str_replace(["\r", "\n"], '', $publickey); $keyparts = str_split($publickey, 253); //Becomes 255 when quotes are included //Quote each chunk foreach ($keyparts as $keypart) { - $dnsvalue .= '"'.trim($keypart).'" '; + $dnsvalue .= '"' . trim($keypart) . '" '; } echo "\n\nDNS key:\n\n" . trim($dnskey); echo "\n\nDNS value:\n\n" . trim($dnsvalue); diff --git a/examples/callback.phps b/examples/callback.phps index 595145a0f..080f167a4 100644 --- a/examples/callback.phps +++ b/examples/callback.phps @@ -13,12 +13,13 @@ require '../vendor/autoload.php'; * Example PHPMailer callback function. * This is a global function, but you can also pass a closure (or any other callable) * to the `action_function` property. - * @param bool $result result of the send action - * @param array $to email address of the recipient - * @param array $cc cc email addresses - * @param array $bcc bcc email addresses - * @param string $subject the subject - * @param string $body the email body + * + * @param bool $result result of the send action + * @param array $to email address of the recipient + * @param array $cc cc email addresses + * @param array $bcc bcc email addresses + * @param string $subject the subject + * @param string $body the email body */ function callbackAction($result, $to, $cc, $bcc, $subject, $body) { diff --git a/examples/extending.phps b/examples/extending.phps index f2658ce87..e7b2d880e 100644 --- a/examples/extending.phps +++ b/examples/extending.phps @@ -20,8 +20,9 @@ class myPHPMailer extends PHPMailer { /** * myPHPMailer constructor. + * * @param bool|null $exceptions - * @param string $body A default HTML message body + * @param string $body A default HTML message body */ public function __construct($exceptions, $body = '') { @@ -48,7 +49,8 @@ class myPHPMailer extends PHPMailer { $this->Subject = '[Yay for me!] ' . $this->Subject; $r = parent::send(); - echo "I sent a message with subject ". $this->Subject; + echo "I sent a message with subject " . $this->Subject; + return $r; } } @@ -64,5 +66,5 @@ try { $mail->send(); //no need to check for errors - the exception handler will do it } catch (Exception $e) { //Note that this is catching the PHPMailer Exception class, not the global \Exception type! - echo "Caught a ".get_class($e).": " . $e->getMessage(); + echo "Caught a " . get_class($e) . ": " . $e->getMessage(); } diff --git a/examples/gmail.phps b/examples/gmail.phps index 775a4bde6..83fe0fad9 100644 --- a/examples/gmail.phps +++ b/examples/gmail.phps @@ -83,7 +83,8 @@ if (!$mail->send()) { //Function to call which uses the PHP imap_*() functions to save messages: https://php.net/manual/en/book.imap.php //You can use imap_getmailboxes($imapStream, '/imap/ssl') to get a list of available folders or labels, this can //be useful if you are trying to get this working on a non-Gmail IMAP server. -function save_mail($mail) { +function save_mail($mail) +{ //You can change 'Sent Mail' to any other folder or tag $path = "{imap.gmail.com:993/imap/ssl}[Gmail]/Sent Mail"; diff --git a/examples/gmail_xoauth.phps b/examples/gmail_xoauth.phps index 850f26040..30b87a305 100644 --- a/examples/gmail_xoauth.phps +++ b/examples/gmail_xoauth.phps @@ -56,20 +56,24 @@ $clientSecret = 'RANDOMCHARS-----lGyjPcRtvP'; $refreshToken = 'RANDOMCHARS-----DWxgOvPT003r-yFUV49TQYag7_Aod7y0'; //Create a new OAuth2 provider instance -$provider = new Google([ - 'clientId' => $clientId, - 'clientSecret' => $clientSecret -]); +$provider = new Google( + [ + 'clientId' => $clientId, + 'clientSecret' => $clientSecret, + ] +); //Pass the OAuth provider instance to PHPMailer $mail->setOAuth( - new OAuth([ - 'provider' => $provider, - 'clientId' => $clientId, - 'clientSecret' => $clientSecret, - 'refreshToken' => $refreshToken, - 'userName' => $email - ]) + new OAuth( + [ + 'provider' => $provider, + 'clientId' => $clientId, + 'clientSecret' => $clientSecret, + 'refreshToken' => $refreshToken, + 'userName' => $email, + ] + ) ); //Set who the message is to be sent from diff --git a/examples/mailing_list.phps b/examples/mailing_list.phps index d62bc461e..828be195a 100644 --- a/examples/mailing_list.phps +++ b/examples/mailing_list.phps @@ -39,7 +39,7 @@ $mail->AltBody = 'To view the message, please use an HTML compatible email viewe //You'll need to alter this to match your database $mysql = mysqli_connect('localhost', 'username', 'password'); mysqli_select_db($mysql, 'mydb'); -$result = mysqli_query($mysql, 'SELECT full_name, email, photo FROM mailinglist WHERE sent = false'); +$result = mysqli_query($mysql, 'SELECT full_name, email, photo FROM mailinglist WHERE sent = FALSE'); foreach ($result as $row) { $mail->addAddress($row['email'], $row['full_name']); @@ -55,7 +55,7 @@ foreach ($result as $row) { //Mark it as sent in the DB mysqli_query( $mysql, - "UPDATE mailinglist SET sent = true WHERE email = '" . + "UPDATE mailinglist SET sent = TRUE WHERE email = '" . mysqli_real_escape_string($mysql, $row['email']) . "'" ); } diff --git a/examples/simple_contact_form.phps b/examples/simple_contact_form.phps index c5db55921..650364cdf 100644 --- a/examples/simple_contact_form.phps +++ b/examples/simple_contact_form.phps @@ -38,8 +38,8 @@ if (array_key_exists('to', $_POST)) { //Validate to address //Never allow arbitrary input for the 'to' address as it will turn your form into a spam gateway! //Substitute appropriate addresses from your own domain, or simply use a single, fixed address - if (array_key_exists('to', $_POST) and in_array($_POST['to'], ['sales','support','accounts'])) { - $to = $_POST['to'].'@example.com'; + if (array_key_exists('to', $_POST) and in_array($_POST['to'], ['sales', 'support', 'accounts'])) { + $to = $_POST['to'] . '@example.com'; } else { $to = 'support@example.com'; } @@ -59,7 +59,7 @@ if (array_key_exists('to', $_POST)) { //It's important not to use the submitter's address as the from address as it's forgery, //which will cause your messages to fail SPF checks. //Use an address in your own domain as the from address, put the submitter's address in a reply-to - $mail->setFrom('contact@example.com', (empty($name)? 'Contact form': $name)); + $mail->setFrom('contact@example.com', (empty($name) ? 'Contact form' : $name)); $mail->addAddress($to); $mail->addReplyTo($email, $name); $mail->Subject = 'Contact form: ' . $subject; @@ -70,7 +70,7 @@ if (array_key_exists('to', $_POST)) { $msg .= "Message sent!"; } } -}?> +} ?> @@ -96,6 +96,6 @@ if (array_key_exists('to', $_POST)) { +} ?> \ No newline at end of file diff --git a/examples/smtp_low_memory.phps b/examples/smtp_low_memory.phps index 463c2416c..9c0ff0a3f 100644 --- a/examples/smtp_low_memory.phps +++ b/examples/smtp_low_memory.phps @@ -104,6 +104,7 @@ class SMTPLowMemory extends SMTP $result = $this->sendCommand('DATA END', '.', 250); //Restore timelimit $this->Timelimit = $savetimelimit; + return $result; } } @@ -123,6 +124,7 @@ class PHPMailerLowMemory extends PHPMailer if (!is_object($this->smtp)) { $this->smtp = new SMTPLowMemory; } + return $this->smtp; } } diff --git a/examples/ssl_options.phps b/examples/ssl_options.phps index 1f5865fac..114ddffe0 100644 --- a/examples/ssl_options.phps +++ b/examples/ssl_options.phps @@ -35,14 +35,14 @@ $mail->SMTPSecure = 'tls'; //Custom connection options //Note that these settings are INSECURE -$mail->SMTPOptions = array ( +$mail->SMTPOptions = array( 'ssl' => [ - 'verify_peer' => true, + 'verify_peer' => true, 'verify_depth' => 3, 'allow_self_signed' => true, 'peer_name' => 'smtp.example.com', - 'cafile' => '/etc/ssl/ca_cert.pem' - ] + 'cafile' => '/etc/ssl/ca_cert.pem', + ], ); //Whether to use SMTP authentication diff --git a/get_oauth_token.php b/get_oauth_token.php index 825310279..1237b57be 100644 --- a/get_oauth_token.php +++ b/get_oauth_token.php @@ -8,7 +8,7 @@ * @author Jim Jagielski (jimjag) * @author Andy Prevost (codeworxtech) * @author Brent R. Matzelle (original founder) - * @copyright 2012 - 2016 Marcus Bointon + * @copyright 2012 - 2017 Marcus Bointon * @copyright 2010 - 2012 Jim Jagielski * @copyright 2004 - 2009 Andy Prevost * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License diff --git a/src/Exception.php b/src/Exception.php index 11b52e9d2..9a05dec3c 100644 --- a/src/Exception.php +++ b/src/Exception.php @@ -1,15 +1,15 @@ * @author Jim Jagielski (jimjag) * @author Andy Prevost (codeworxtech) * @author Brent R. Matzelle (original founder) - * @copyright 2012 - 2016 Marcus Bointon + * @copyright 2012 - 2017 Marcus Bointon * @copyright 2010 - 2012 Jim Jagielski * @copyright 2004 - 2009 Andy Prevost * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License @@ -21,15 +21,14 @@ namespace PHPMailer\PHPMailer; /** - * PHPMailer exception handler + * PHPMailer exception handler. * - * @package PHPMailer * @author Marcus Bointon */ class Exception extends \Exception { /** - * Prettify error message output + * Prettify error message output. * * @return string */ diff --git a/src/OAuth.php b/src/OAuth.php index ae7660abb..b2309a1fc 100644 --- a/src/OAuth.php +++ b/src/OAuth.php @@ -1,11 +1,10 @@ * @author Jim Jagielski (jimjag) * @author Andy Prevost (codeworxtech) @@ -22,15 +21,15 @@ namespace PHPMailer\PHPMailer; use League\OAuth2\Client\Grant\RefreshToken; -use League\OAuth2\Client\Token\AccessToken; use League\OAuth2\Client\Provider\AbstractProvider; +use League\OAuth2\Client\Token\AccessToken; /** * OAuth - OAuth2 authentication wrapper class. - * Uses the oauth2-client package from the League of Extraordinary Packages + * Uses the oauth2-client package from the League of Extraordinary Packages. * * @see http://oauth2-client.thephpleague.com - * @package PHPMailer + * * @author Marcus Bointon (Synchro/coolbru) */ class OAuth @@ -82,7 +81,7 @@ class OAuth * OAuth constructor. * * @param array $options Associative array containing - * `provider`, `userName`, `clientSecret`, `clientId` and `refreshToken` elements + * `provider`, `userName`, `clientSecret`, `clientId` and `refreshToken` elements */ public function __construct($options) { @@ -100,7 +99,7 @@ public function __construct($options) */ protected function getGrant() { - return new RefreshToken; + return new RefreshToken(); } /** @@ -127,6 +126,7 @@ public function getOauth64() if (null === $this->oauthToken or $this->oauthToken->hasExpired()) { $this->oauthToken = $this->getToken(); } + return base64_encode( 'user=' . $this->oauthUserEmail . diff --git a/src/PHPMailer.php b/src/PHPMailer.php index c5d5db65a..3c3a6b94e 100644 --- a/src/PHPMailer.php +++ b/src/PHPMailer.php @@ -1,15 +1,15 @@ * @author Jim Jagielski (jimjag) * @author Andy Prevost (codeworxtech) * @author Brent R. Matzelle (original founder) - * @copyright 2012 - 2016 Marcus Bointon + * @copyright 2012 - 2017 Marcus Bointon * @copyright 2010 - 2012 Jim Jagielski * @copyright 2004 - 2009 Andy Prevost * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License @@ -23,7 +23,6 @@ /** * PHPMailer - PHP email creation and transport class. * - * @package PHPMailer * @author Marcus Bointon (Synchro/coolbru) * @author Jim Jagielski (jimjag) * @author Andy Prevost (codeworxtech) @@ -121,10 +120,11 @@ class PHPMailer /** * An iCal message part body. * Only supported in simple alt or alt_inline message types - * To generate iCal event structures, use classes like EasyPeasyICS or iCalcreator + * To generate iCal event structures, use classes like EasyPeasyICS or iCalcreator. * * @see http://sprain.ch/blog/downloads/php-class-easypeasyics-create-ical-files-with-php/ * @see http://kigkonsult.se/iCalcreator/ + * * @var string */ public $Ical = ''; @@ -153,6 +153,7 @@ class PHPMailer /** * 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. + * * @see static::STD_LINE_LENGTH * * @var int @@ -204,6 +205,7 @@ class PHPMailer * If empty, a unique id will be generated. * You can set your own, but it must be in the format "", * as defined in RFC5322 section 3.6.4 or it will be ignored. + * * @see https://tools.ietf.org/html/rfc5322#section-3.6.4 * * @var string @@ -244,14 +246,15 @@ class PHPMailer * Default is $Hostname. If $Hostname is empty, PHPMailer attempts to find * one with the same method described above for $Hostname. * - * @var string * @see PHPMailer::$Hostname + * + * @var string */ public $Helo = ''; /** * What kind of encryption to use on the SMTP connection. - * Options: '', 'ssl' or 'tls' + * Options: '', 'ssl' or 'tls'. * * @var string */ @@ -270,9 +273,10 @@ class PHPMailer * Whether to use SMTP authentication. * Uses the Username and Password properties. * - * @var bool * @see PHPMailer::$Username * @see PHPMailer::$Password + * + * @var bool */ public $SMTPAuth = false; @@ -299,7 +303,7 @@ class PHPMailer /** * SMTP auth type. - * Options are CRAM-MD5, LOGIN, PLAIN, XOAUTH2, attempted in that order if not specified + * Options are CRAM-MD5, LOGIN, PLAIN, XOAUTH2, attempted in that order if not specified. * * @var string */ @@ -314,7 +318,7 @@ class PHPMailer /** * The SMTP server timeout in seconds. - * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2. * * @var int */ @@ -328,10 +332,11 @@ class PHPMailer * * `1` Commands * * `2` Data and commands * * `3` As 2 plus connection status - * * `4` Low-level data output + * * `4` Low-level data output. * - * @var int * @see SMTP::$do_debug + * + * @var int */ public $SMTPDebug = 0; @@ -351,8 +356,10 @@ class PHPMailer * * $mail->Debugoutput = new myPsr3Logger; * - * @var string|callable|\Psr\Log\LoggerInterface + * * @see SMTP::$Debugoutput + * + * @var string|callable|\Psr\Log\LoggerInterface */ public $Debugoutput = 'echo'; @@ -387,6 +394,7 @@ class PHPMailer * * @see https://en.wikipedia.org/wiki/Variable_envelope_return_path * @see http://www.postfix.org/VERP_README.html Postfix VERP info + * * @var bool */ public $do_verp = false; @@ -425,6 +433,7 @@ class PHPMailer * DKIM signing domain name. * * @example 'example.com' + * * @var string */ public $DKIM_domain = ''; @@ -440,6 +449,7 @@ class PHPMailer * DKIM private key string. * * If set, takes precedence over `$DKIM_private`. + * * @var string */ public $DKIM_private_string = ''; @@ -467,7 +477,7 @@ class PHPMailer /** * What to put in the X-Mailer header. - * Options: An empty string for PHPMailer default, whitespace for none, or a string to use + * Options: An empty string for PHPMailer default, whitespace for none, or a string to use. * * @var string */ @@ -479,6 +489,7 @@ class PHPMailer * The default validator uses PHP's FILTER_VALIDATE_EMAIL filter_var option. * * @see PHPMailer::validateAddress() + * * @var string|callable */ public static $validator = 'php'; @@ -520,10 +531,13 @@ class PHPMailer /** * An array of all kinds of addresses. - * Includes all of $to, $cc, $bcc + * Includes all of $to, $cc, $bcc. + * + * @see PHPMailer::$to + * @see PHPMailer::$cc + * @see PHPMailer::$bcc * * @var array - * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc */ protected $all_recipients = []; @@ -533,9 +547,12 @@ class PHPMailer * and one of $to, $cc, or $bcc. * This array is used only for addresses with IDN. * - * @var array - * @see PHPMailer::$to @see PHPMailer::$cc @see PHPMailer::$bcc + * @see PHPMailer::$to + * @see PHPMailer::$cc + * @see PHPMailer::$bcc * @see PHPMailer::$all_recipients + * + * @var array */ protected $RecipientsQueue = []; @@ -544,8 +561,9 @@ class PHPMailer * In send(), valid and non duplicate entries are moved to $ReplyTo. * This array is used only for addresses with IDN. * - * @var array * @see PHPMailer::$ReplyTo + * + * @var array */ protected $ReplyToQueue = []; @@ -677,14 +695,14 @@ class PHPMailer protected static $LE = "\r\n"; /** - * The maximum line length allowed by RFC 2822 section 2.1.1 + * The maximum line length allowed by RFC 2822 section 2.1.1. * * @var int */ const MAX_LINE_LENGTH = 998; /** - * The lower maximum line length allowed by RFC 2822 section 2.1.1 + * The lower maximum line length allowed by RFC 2822 section 2.1.1. * * @var int */ @@ -698,7 +716,7 @@ class PHPMailer public function __construct($exceptions = null) { if (null !== $exceptions) { - $this->exceptions = (bool)$exceptions; + $this->exceptions = (bool) $exceptions; } //Pick an appropriate debug output format automatically $this->Debugoutput = (strpos(PHP_SAPI, 'cli') !== false ? 'echo' : 'html'); @@ -717,12 +735,12 @@ public function __destruct() * Call mail() in a safe_mode-aware fashion. * Also, unless sendmail_path points to sendmail (or something that * claims to be sendmail), don't pass params (not a perfect fix, - * but it will do) + * but it will do). * - * @param string $to To + * @param string $to To * @param string $subject Subject - * @param string $body Message Body - * @param string $header Additional Header(s) + * @param string $body Message Body + * @param string $header Additional Header(s) * @param ?string $params Params * * @return bool @@ -741,6 +759,7 @@ private function mailPassthru($to, $subject, $body, $header, $params) } else { $result = @mail($to, $subject, $body, $header, $params); } + return $result; } @@ -748,10 +767,10 @@ private function mailPassthru($to, $subject, $body, $header, $params) * Output debugging info via user-defined method. * Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug). * - * @param string $str - * * @see PHPMailer::$Debugoutput * @see PHPMailer::$SMTPDebug + * + * @param string $str */ protected function edebug($str) { @@ -761,11 +780,13 @@ protected function edebug($str) //Is this a PSR-3 logger? if (is_a($this->Debugoutput, 'Psr\Log\LoggerInterface')) { $this->Debugoutput->debug($str); + return; } //Avoid clash with built-in function names if (!in_array($this->Debugoutput, ['error_log', 'html', 'echo']) and is_callable($this->Debugoutput)) { call_user_func($this->Debugoutput, $str, $this->SMTPDebug); + return; } switch ($this->Debugoutput) { @@ -786,17 +807,17 @@ protected function edebug($str) //Normalize line breaks $str = preg_replace('/\r\n|\r/ms', "\n", $str); echo gmdate('Y-m-d H:i:s'), - "\t", + "\t", //Trim trailing space - trim( - //Indent for readability, except for trailing break - str_replace( - "\n", - "\n \t ", - trim($str) - ) - ), - "\n"; + trim( + //Indent for readability, except for trailing break + str_replace( + "\n", + "\n \t ", + trim($str) + ) + ), + "\n"; } } @@ -918,11 +939,12 @@ public function addReplyTo($address, $name = '') * be modified after calling this function), addition of such addresses is delayed until send(). * Addresses that have been added already return false, but do not throw exceptions. * - * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' + * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' * @param string $address The email address to send, resp. to reply to * @param string $name * * @throws Exception + * * @return bool true on success, false if address already used or invalid in some way */ protected function addOrEnqueueAnAddress($kind, $address, $name) @@ -938,6 +960,7 @@ protected function addOrEnqueueAnAddress($kind, $address, $name) if ($this->exceptions) { throw new Exception($error_message); } + return false; } $params = [$kind, $address, $name]; @@ -946,16 +969,20 @@ protected function addOrEnqueueAnAddress($kind, $address, $name) if ('Reply-To' != $kind) { if (!array_key_exists($address, $this->RecipientsQueue)) { $this->RecipientsQueue[$address] = $params; + return true; } } else { if (!array_key_exists($address, $this->ReplyToQueue)) { $this->ReplyToQueue[$address] = $params; + return true; } } + return false; } + // Immediately add standard addresses without IDN. return call_user_func_array([$this, 'addAnAddress'], $params); } @@ -964,11 +991,12 @@ protected function addOrEnqueueAnAddress($kind, $address, $name) * Add an address to one of the recipient arrays or to the ReplyTo array. * Addresses that have been added already return false, but do not throw exceptions. * - * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' + * @param string $kind One of 'to', 'cc', 'bcc', or 'ReplyTo' * @param string $address The email address to send, resp. to reply to * @param string $name * * @throws Exception + * * @return bool true on success, false if address already used or invalid in some way */ protected function addAnAddress($kind, $address, $name = '') @@ -980,6 +1008,7 @@ protected function addAnAddress($kind, $address, $name = '') if ($this->exceptions) { throw new Exception($error_message); } + return false; } if (!static::validateAddress($address)) { @@ -989,20 +1018,24 @@ protected function addAnAddress($kind, $address, $name = '') if ($this->exceptions) { throw new Exception($error_message); } + return false; } if ('Reply-To' != $kind) { if (!array_key_exists(strtolower($address), $this->all_recipients)) { array_push($this->$kind, [$address, $name]); $this->all_recipients[strtolower($address)] = true; + return true; } } else { if (!array_key_exists(strtolower($address), $this->ReplyTo)) { $this->ReplyTo[strtolower($address)] = [$address, $name]; + return true; } } + return false; } @@ -1012,11 +1045,12 @@ protected function addAnAddress($kind, $address, $name = '') * Uses the imap_rfc822_parse_adrlist function if the IMAP extension is available. * Note that quotes in the name part are removed. * + * @see http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation + * * @param string $addrstr The address list string - * @param bool $useimap Whether to use the IMAP extension to parse the list + * @param bool $useimap Whether to use the IMAP extension to parse the list * * @return array - * @see http://www.andrew.cmu.edu/user/agreen1/testing/mrbs/web/Mail/RFC822.php A more careful implementation */ public static function parseAddresses($addrstr, $useimap = true) { @@ -1029,7 +1063,7 @@ public static function parseAddresses($addrstr, $useimap = true) if (static::validateAddress($address->mailbox . '@' . $address->host)) { $addresses[] = [ 'name' => (property_exists($address, 'personal') ? $address->personal : ''), - 'address' => $address->mailbox . '@' . $address->host + 'address' => $address->mailbox . '@' . $address->host, ]; } } @@ -1045,7 +1079,7 @@ public static function parseAddresses($addrstr, $useimap = true) if (static::validateAddress($address)) { $addresses[] = [ 'name' => '', - 'address' => $address + 'address' => $address, ]; } } else { @@ -1054,12 +1088,13 @@ public static function parseAddresses($addrstr, $useimap = true) if (static::validateAddress($email)) { $addresses[] = [ 'name' => trim(str_replace(['"', "'"], '', $name)), - 'address' => $email + 'address' => $email, ]; } } } } + return $addresses; } @@ -1068,9 +1103,10 @@ public static function parseAddresses($addrstr, $useimap = true) * * @param string $address * @param string $name - * @param bool $auto Whether to also set the Sender address, defaults to true + * @param bool $auto Whether to also set the Sender address, defaults to true * * @throws Exception + * * @return bool */ public function setFrom($address, $name = '', $auto = true) @@ -1088,6 +1124,7 @@ public function setFrom($address, $name = '', $auto = true) if ($this->exceptions) { throw new Exception($error_message); } + return false; } $this->From = $address; @@ -1097,6 +1134,7 @@ public function setFrom($address, $name = '', $auto = true) $this->Sender = $address; } } + return true; } @@ -1115,9 +1153,7 @@ public function getLastMessageID() /** * Check that a string looks like an email address. - * - * @param string $address The email address to check - * @param string|callable $patternselect A selector for the validation pattern to use : + * Validation patterns supported: * * `auto` Pick best pattern automatically; * * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0; * * `pcre` Use old PCRE implementation; @@ -1125,11 +1161,16 @@ public function getLastMessageID() * * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements. * * `noregex` Don't use a regex: super fast, really dumb. * Alternatively you may pass in a callable to inject your own validator, for example: + * * PHPMailer::validateAddress('user@example.com', function($address) { * return (strpos($address, '@') !== false); * }); + * * You can also set the PHPMailer::$validator static to a callable, allowing built-in methods to use your validator. * + * @param string $address The email address to check + * @param string|callable $patternselect Which pattern to use + * * @return bool */ public static function validateAddress($address, $patternselect = null) @@ -1147,7 +1188,7 @@ public static function validateAddress($address, $patternselect = null) switch ($patternselect) { case 'pcre': //Kept for BC case 'pcre8': - /** + /* * A more complex and more permissive version of the RFC5322 regex on which FILTER_VALIDATE_EMAIL * is based. * In addition to the addresses allowed by filter_var, also permits: @@ -1163,7 +1204,7 @@ public static function validateAddress($address, $patternselect = null) * @copyright 2009-2010 Michael Rushton * Feel free to use and redistribute this code. But please keep this copyright notice. */ - return (bool)preg_match( + return (bool) preg_match( '/^(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){255,})(?!(?>(?1)"?(?>\\\[ -~]|[^"])"?(?1)){65,}@)' . '((?>(?>(?>((?>(?>(?>\x0D\x0A)?[\t ])+|(?>[\t ]*\x0D\x0A)?[\t ]+)?)(\((?>(?2)' . '(?>[\x01-\x08\x0B\x0C\x0E-\'*-\[\]-\x7F]|\\\[\x00-\x7F]|(?3)))*(?2)\)))+(?2))|(?2))?)' . @@ -1176,20 +1217,19 @@ public static function validateAddress($address, $patternselect = null) $address ); case 'html5': - /** + /* * This is the pattern used in the HTML5 spec for validation of 'email' type form input elements. * * @see http://www.whatwg.org/specs/web-apps/current-work/#e-mail-state-(type=email) */ - return (bool)preg_match( + return (bool) preg_match( '/^[a-zA-Z0-9.!#$%&\'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}' . '[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/sD', $address ); - case 'noregex': //Kept for BC case 'php': default: - return (bool)filter_var($address, FILTER_VALIDATE_EMAIL); + return (bool) filter_var($address, FILTER_VALIDATE_EMAIL); } } @@ -1210,11 +1250,12 @@ public function idnSupported() * This function silently returns unmodified address if: * - No conversion is necessary (i.e. domain name is not an IDN, or is already in ASCII form) * - Conversion to punycode is impossible (e.g. required PHP functions are not available) - * or fails for any reason (e.g. domain has characters not allowed in an IDN) + * or fails for any reason (e.g. domain contains characters not allowed in an IDN). + * + * @see PHPMailer::$CharSet * * @param string $address The email address to convert * - * @see PHPMailer::$CharSet * @return string The encoded address in ASCII form */ public function punyencodeAddress($address) @@ -1237,6 +1278,7 @@ public function punyencodeAddress($address) } } } + return $address; } @@ -1244,8 +1286,9 @@ public function punyencodeAddress($address) * Create a message and send it. * Uses the sending method specified by $Mailer. * - * @return bool false on error - See the ErrorInfo property for details of the error. * @throws Exception + * + * @return bool false on error - See the ErrorInfo property for details of the error */ public function send() { @@ -1253,6 +1296,7 @@ public function send() if (!$this->preSend()) { return false; } + return $this->postSend(); } catch (Exception $exc) { $this->mailHeader = ''; @@ -1260,6 +1304,7 @@ public function send() if ($this->exceptions) { throw $exc; } + return false; } } @@ -1268,6 +1313,7 @@ public function send() * Prepare a message for sending. * * @throws Exception + * * @return bool */ public function preSend() @@ -1326,6 +1372,7 @@ public function preSend() if ($this->exceptions) { throw new Exception($error_message); } + return false; } } @@ -1369,7 +1416,7 @@ public function preSend() if (!empty($this->DKIM_domain) and !empty($this->DKIM_selector) and (!empty($this->DKIM_private_string) - or (!empty($this->DKIM_private) and file_exists($this->DKIM_private)) + or (!empty($this->DKIM_private) and file_exists($this->DKIM_private)) ) ) { $header_dkim = $this->DKIM_Add( @@ -1380,22 +1427,24 @@ public function preSend() $this->MIMEHeader = rtrim($this->MIMEHeader, "\r\n ") . static::$LE . static::normalizeBreaks($header_dkim) . static::$LE; } + return true; } catch (Exception $exc) { $this->setError($exc->getMessage()); if ($this->exceptions) { throw $exc; } + return false; } } /** - * Actually send a message. - * Send the email via the selected mechanism + * Actually send a message via the selected mechanism. * - * @return bool * @throws Exception + * + * @return bool */ public function postSend() { @@ -1410,7 +1459,7 @@ public function postSend() case 'mail': return $this->mailSend($this->MIMEHeader, $this->MIMEBody); default: - $sendMethod = $this->Mailer.'Send'; + $sendMethod = $this->Mailer . 'Send'; if (method_exists($this, $sendMethod)) { return $this->$sendMethod($this->MIMEHeader, $this->MIMEBody); } @@ -1424,17 +1473,20 @@ public function postSend() throw $exc; } } + return false; } /** * Send mail using the $Sendmail program. * + * @see PHPMailer::$Sendmail + * * @param string $header The message headers - * @param string $body The message body + * @param string $body The message body * - * @see PHPMailer::$Sendmail * @throws Exception + * * @return bool */ protected function sendmailSend($header, $body) @@ -1500,16 +1552,18 @@ protected function sendmailSend($header, $body) throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL); } } + return true; } /** * Fix CVE-2016-10033 and CVE-2016-10045 by disallowing potentially unsafe shell characters. - * * Note that escapeshellarg and escapeshellcmd are inadequate for our purposes, especially on Windows. - * @param string $string The string to be validated + * * @see https://github.com/PHPMailer/PHPMailer/issues/924 CVE-2016-10045 bug report - * @access protected + * + * @param string $string The string to be validated + * * @return bool */ protected static function isShellSafe($string) @@ -1540,11 +1594,13 @@ protected static function isShellSafe($string) /** * Send mail using the PHP mail() function. * + * @see http://www.php.net/manual/en/book.mail.php + * * @param string $header The message headers - * @param string $body The message body + * @param string $body The message body * - * @see http://www.php.net/manual/en/book.mail.php * @throws Exception + * * @return bool */ protected function mailSend($header, $body) @@ -1569,7 +1625,7 @@ protected function mailSend($header, $body) $params = sprintf('-f%s', $this->Sender); } } - if (!empty($this->Sender)and static::validateAddress($this->Sender)) { + if (!empty($this->Sender) and static::validateAddress($this->Sender)) { $old_from = ini_get('sendmail_from'); ini_set('sendmail_from', $this->Sender); } @@ -1589,6 +1645,7 @@ protected function mailSend($header, $body) if (!$result) { throw new Exception($this->lang('instantiate'), self::STOP_CRITICAL); } + return true; } @@ -1602,8 +1659,9 @@ protected function mailSend($header, $body) public function getSMTPInstance() { if (!is_object($this->smtp)) { - $this->smtp = new SMTP; + $this->smtp = new SMTP(); } + return $this->smtp; } @@ -1611,11 +1669,13 @@ public function getSMTPInstance() * Provide an instance to use for SMTP operations. * * @param SMTP $smtp + * * @return SMTP */ public function setSMTPInstance(SMTP $smtp) { $this->smtp = $smtp; + return $this->smtp; } @@ -1624,12 +1684,14 @@ public function setSMTPInstance(SMTP $smtp) * Returns false if there is a bad MAIL FROM, RCPT, or DATA input. * Uses the PHPMailerSMTP class by default. * + * @see PHPMailer::getSMTPInstance() to use a different class. + * @uses SMTP + * * @param string $header The message headers - * @param string $body The message body + * @param string $body The message body * - * @see PHPMailer::getSMTPInstance() to use a different class. * @throws Exception - * @uses SMTP + * * @return bool */ protected function smtpSend($header, $body) @@ -1684,6 +1746,7 @@ protected function smtpSend($header, $body) self::STOP_CONTINUE ); } + return true; } @@ -1693,9 +1756,11 @@ protected function smtpSend($header, $body) * * @param array $options An array of options compatible with stream_context_create() * - * @return bool * @throws Exception + * * @uses SMTP + * + * @return bool */ public function smtpConnect($options = null) { @@ -1722,7 +1787,11 @@ public function smtpConnect($options = null) foreach ($hosts as $hostentry) { $hostinfo = []; - if (!preg_match('/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*|\[[a-fA-F0-9:]+\]):?([0-9]*)$/', trim($hostentry), $hostinfo)) { + if (!preg_match( + '/^((ssl|tls):\/\/)*([a-zA-Z0-9\.-]*|\[[a-fA-F0-9:]+\]):?([0-9]*)$/', + trim($hostentry), + $hostinfo + )) { static::edebug($this->lang('connect_host') . ' ' . $hostentry); // Not a valid host entry continue; @@ -1735,7 +1804,7 @@ public function smtpConnect($options = null) //Check the host name is a valid name or IP address before trying to use it if (!static::isValidHost($hostinfo[3])) { - static::edebug($this->lang('connect_host'). ' ' . $hostentry); + static::edebug($this->lang('connect_host') . ' ' . $hostentry); continue; } $prefix = ''; @@ -1755,12 +1824,12 @@ public function smtpConnect($options = null) if ('tls' === $secure or 'ssl' === $secure) { //Check for an OpenSSL constant rather than using extension_loaded, which is sometimes disabled if (!$sslext) { - throw new Exception($this->lang('extension_missing').'openssl', self::STOP_CRITICAL); + throw new Exception($this->lang('extension_missing') . 'openssl', self::STOP_CRITICAL); } } $host = $hostinfo[3]; $port = $this->Port; - $tport = (integer)$hostinfo[4]; + $tport = (int) $hostinfo[4]; if ($tport > 0 and $tport < 65536) { $port = $tport; } @@ -1798,6 +1867,7 @@ public function smtpConnect($options = null) throw new Exception($this->lang('authenticate')); } } + return true; } catch (Exception $exc) { $lastexception = $exc; @@ -1813,6 +1883,7 @@ public function smtpConnect($options = null) if ($this->exceptions and null !== $lastexception) { throw $lastexception; } + return false; } @@ -1834,7 +1905,7 @@ public function smtpClose() * Returns false if it cannot load the language file. * The default language is English. * - * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr") + * @param string $langcode ISO 639-1 2-character language code (e.g. French is "fr") * @param string $lang_path Path to the language file directory, with trailing separator (slash) * * @return bool @@ -1848,7 +1919,7 @@ public function setLanguage($langcode = 'en', $lang_path = '') 'dk' => 'da', 'no' => 'nb', 'se' => 'sv', - 'sr' => 'rs' + 'sr' => 'rs', ]; if (isset($renamed_langcodes[$langcode])) { @@ -1875,11 +1946,11 @@ public function setLanguage($langcode = 'en', $lang_path = '') 'smtp_connect_failed' => 'SMTP connect() failed.', 'smtp_error' => 'SMTP server error: ', 'variable_set' => 'Cannot set or reset variable: ', - 'extension_missing' => 'Extension missing: ' + 'extension_missing' => 'Extension missing: ', ]; if (empty($lang_path)) { // Calculate an absolute path so it can work if CWD is not here - $lang_path = dirname(__FILE__). DIRECTORY_SEPARATOR . 'language'. DIRECTORY_SEPARATOR; + $lang_path = __DIR__ . DIRECTORY_SEPARATOR . 'language' . DIRECTORY_SEPARATOR; } //Validate $langcode if (!preg_match('/^[a-z]{2}(?:_[a-zA-Z]{2})?$/', $langcode)) { @@ -1899,7 +1970,8 @@ public function setLanguage($langcode = 'en', $lang_path = '') } } $this->language = $PHPMAILER_LANG; - return (bool)$foundlang; // Returns false if language not found + + return (bool) $foundlang; // Returns false if language not found } /** @@ -1916,10 +1988,10 @@ public function getTranslations() * Create recipient headers. * * @param string $type - * @param array $addr An array of recipient, - * where each recipient is a 2-element indexed array with element 0 containing an address - * and element 1 containing a name, like: - * [['joe@example.com', 'Joe User'], ['zoe@example.com', 'Zoe User']] + * @param array $addr An array of recipients, + * where each recipient is a 2-element indexed array with element 0 containing an address + * and element 1 containing a name, like: + * [['joe@example.com', 'Joe User'], ['zoe@example.com', 'Zoe User']] * * @return string */ @@ -1929,14 +2001,15 @@ public function addrAppend($type, $addr) foreach ($addr as $address) { $addresses[] = $this->addrFormat($address); } + return $type . ': ' . implode(', ', $addresses) . static::$LE; } /** * Format an address for use in a message header. * - * @param array $addr A 2-element indexed array, element 0 containing an address, element 1 containing a name - * like ['joe@example.com', 'Joe User'] + * @param array $addr A 2-element indexed array, element 0 containing an address, element 1 containing a name like + * ['joe@example.com', 'Joe User'] * * @return string */ @@ -1944,11 +2017,11 @@ public function addrFormat($addr) { if (empty($addr[1])) { // No name provided return $this->secureHeader($addr[0]); - } else { - return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader( + } + + return $this->encodeHeader($this->secureHeader($addr[1]), 'phrase') . ' <' . $this->secureHeader( $addr[0] ) . '>'; - } } /** @@ -1958,8 +2031,8 @@ public function addrFormat($addr) * Original written by philippe. * * @param string $message The message to wrap - * @param int $length The line length to wrap to - * @param bool $qp_mode Whether to run in Quoted-Printable mode + * @param int $length The line length to wrap to + * @param bool $qp_mode Whether to run in Quoted-Printable mode * * @return string */ @@ -2059,7 +2132,7 @@ public function wrapText($message, $length, $qp_mode = false) * Original written by Colin Brown. * * @param string $encodedText utf-8 QP text - * @param int $maxLength Find the last character boundary prior to this length + * @param int $maxLength Find the last character boundary prior to this length * * @return int */ @@ -2097,6 +2170,7 @@ public function utf8CharBoundary($encodedText, $maxLength) $foundSplitPos = true; } } + return $maxLength; } @@ -2162,7 +2236,7 @@ public function createHeader() // sendmail and mail() extract Bcc from the header before sending if (( - 'sendmail' == $this->Mailer or 'qmail' == $this->Mailer or 'mail' == $this->Mailer + 'sendmail' == $this->Mailer or 'qmail' == $this->Mailer or 'mail' == $this->Mailer ) and count($this->bcc) > 0 ) { @@ -2277,7 +2351,8 @@ public function getMailMIME() * Includes complete headers and body. * Only valid post preSend(). * - * @see PHPMailer::preSend() + * @see PHPMailer::preSend() + * * @return string */ public function getSentMIMEMessage() @@ -2293,13 +2368,14 @@ public function getSentMIMEMessage() protected function generateId() { $len = 23; - if (function_exists("random_bytes")) { + if (function_exists('random_bytes')) { $bytes = random_bytes($len); - } elseif (function_exists("openssl_random_pseudo_bytes")) { + } elseif (function_exists('openssl_random_pseudo_bytes')) { $bytes = openssl_random_pseudo_bytes($len); } else { - $bytes = uniqid((string)mt_rand(), true); + $bytes = uniqid((string) mt_rand(), true); } + return hash('sha256', $bytes); } @@ -2308,6 +2384,7 @@ protected function generateId() * Returns an empty string on failure. * * @throws Exception + * * @return string The assembled message body */ public function createBody() @@ -2353,7 +2430,7 @@ public function createBody() $altBodyEncoding = 'quoted-printable'; } //Use this as a preamble in all multipart message types - $mimepre = "This is a multi-part message in MIME format." . static::$LE; + $mimepre = 'This is a multi-part message in MIME format.' . static::$LE; switch ($this->message_type) { case 'inline': $body .= $mimepre; @@ -2518,6 +2595,7 @@ public function createBody() } } } + return $body; } @@ -2593,7 +2671,7 @@ protected function setMessageType() /** * Format a header line. * - * @param string $name + * @param string $name * @param string|int $value * * @return string @@ -2620,13 +2698,14 @@ public function textLine($value) * Never use a user-supplied path to a file! * Returns false if the file could not be found or read. * - * @param string $path Path to the attachment - * @param string $name Overrides the attachment name - * @param string $encoding File encoding (see $Encoding) - * @param string $type File extension (MIME) type + * @param string $path Path to the attachment + * @param string $name Overrides the attachment name + * @param string $encoding File encoding (see $Encoding) + * @param string $type File extension (MIME) type * @param string $disposition Disposition to use * * @throws Exception + * * @return bool */ public function addAttachment($path, $name = '', $encoding = 'base64', $type = '', $disposition = 'attachment') @@ -2654,7 +2733,7 @@ public function addAttachment($path, $name = '', $encoding = 'base64', $type = ' 4 => $type, 5 => false, // isStringAttachment 6 => $disposition, - 7 => 0 + 7 => 0, ]; } catch (Exception $exc) { $this->setError($exc->getMessage()); @@ -2662,8 +2741,10 @@ public function addAttachment($path, $name = '', $encoding = 'base64', $type = ' if ($this->exceptions) { throw $exc; } + return false; } + return true; } @@ -2802,10 +2883,11 @@ protected function attachAll($disposition_type, $boundary) * Encode a file attachment in requested format. * Returns an empty string on failure. * - * @param string $path The full path to the file + * @param string $path The full path to the file * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable' * * @throws Exception + * * @return string */ protected function encodeFile($path, $encoding = 'base64') @@ -2819,9 +2901,11 @@ protected function encodeFile($path, $encoding = 'base64') throw new Exception($this->lang('file_open') . $path, self::STOP_CONTINUE); } $file_buffer = $this->encodeString($file_buffer, $encoding); + return $file_buffer; } catch (Exception $exc) { $this->setError($exc->getMessage()); + return ''; } } @@ -2830,7 +2914,7 @@ protected function encodeFile($path, $encoding = 'base64') * Encode a string in requested format. * Returns an empty string on failure. * - * @param string $str The text to encode + * @param string $str The text to encode * @param string $encoding The encoding to use; one of 'base64', '7bit', '8bit', 'binary', 'quoted-printable * * @return string @@ -2864,16 +2948,17 @@ public function encodeString($str, $encoding = 'base64') $this->setError($this->lang('encoding') . $encoding); break; } + return $encoded; } /** * Encode a header value (not including its label) optimally. * Picks shortest of Q, B, or none. Result includes folding if needed. + * See RFC822 definitions for phrase, comment and text positions. * - * @param string $str The header value to encode + * @param string $str The header value to encode * @param string $position What context the string will be used in - * See RFC822 definitions for phrase, comment and text * * @return string */ @@ -2887,16 +2972,16 @@ public function encodeHeader($str, $position = 'text') $encoded = addcslashes($str, "\0..\37\177\\\""); if (($str == $encoded) and !preg_match('/[^A-Za-z0-9!#$%&\'*+\/=?^_`{|}~ -]/', $str)) { return $encoded; - } else { - return "\"$encoded\""; } + + return "\"$encoded\""; } $matchcount = preg_match_all('/[^\040\041\043-\133\135-\176]/', $str, $matches); break; - /** @noinspection PhpMissingBreakStatementInspection */ + /* @noinspection PhpMissingBreakStatementInspection */ case 'comment': $matchcount = preg_match_all('/[()"]/', $str, $matches); - //fallthrough + //fallthrough case 'text': default: $matchcount += preg_match_all('/[\000-\010\013\014\016-\037\177-\377]/', $str, $matches); @@ -2905,7 +2990,7 @@ public function encodeHeader($str, $position = 'text') //RFCs specify a maximum line length of 78 chars, however mail() will sometimes //corrupt messages with headers longer than 65 chars. See #818 - $lengthsub = 'mail' == $this->Mailer ? 13: 0; + $lengthsub = 'mail' == $this->Mailer ? 13 : 0; $maxlen = static::STD_LINE_LENGTH - $lengthsub; // Try to select the encoding which should produce the shortest output if ($matchcount > strlen($str) / 3) { @@ -2964,9 +3049,10 @@ public function hasMultiBytes($str) { if (function_exists('mb_strlen')) { return strlen($str) > mb_strlen($str, $this->CharSet); - } else { // Assume no multibytes (we can't handle without mbstring functions anyway) - return false; } + + // Assume no multibytes (we can't handle without mbstring functions anyway) + return false; } /** @@ -2978,19 +3064,20 @@ public function hasMultiBytes($str) */ public function has8bitChars($text) { - return (bool)preg_match('/[\x80-\xFF]/', $text); + return (bool) preg_match('/[\x80-\xFF]/', $text); } /** * Encode and wrap long multibyte strings for mail headers * without breaking lines within a character. - * Adapted from a function by paravoid + * Adapted from a function by paravoid. * - * @param string $str multi-byte text to wrap encode + * @see http://www.php.net/manual/en/function.mb-encode-mimeheader.php#60283 + * + * @param string $str multi-byte text to wrap encode * @param string $linebreak string to use as linefeed/end-of-line * * @return string - * @see http://www.php.net/manual/en/function.mb-encode-mimeheader.php#60283 */ public function base64EncodeWrapMB($str, $linebreak = null) { @@ -3021,8 +3108,7 @@ public function base64EncodeWrapMB($str, $linebreak = null) } // Chomp the last linefeed - $encoded = substr($encoded, 0, -strlen($linebreak)); - return $encoded; + return substr($encoded, 0, -strlen($linebreak)); } /** @@ -3041,11 +3127,12 @@ public function encodeQP($string) /** * Encode a string using Q encoding. * - * @param string $str the text to encode + * @see http://tools.ietf.org/html/rfc2047#section-4.2 + * + * @param string $str the text to encode * @param string $position Where the text is going to be used, see the RFC for what that means * * @return string - * @see http://tools.ietf.org/html/rfc2047 */ public function encodeQ($str, $position = 'text') { @@ -3057,14 +3144,14 @@ public function encodeQ($str, $position = 'text') // RFC 2047 section 5.3 $pattern = '^A-Za-z0-9!*+\/ -'; break; - /** + /* * RFC 2047 section 5.2. * Build $pattern without including delimiters and [] */ - /** @noinspection PhpMissingBreakStatementInspection */ + /* @noinspection PhpMissingBreakStatementInspection */ case 'comment': - $pattern = '\(\)"'; - /* Intentional fall through */ + $pattern = '\(\)"'; + /* Intentional fall through */ case 'text': default: // RFC 2047 section 5.1 @@ -3095,10 +3182,10 @@ public function encodeQ($str, $position = 'text') * This method can be used to attach ascii or binary data, * such as a BLOB record from a database. * - * @param string $string String attachment data - * @param string $filename Name of the attachment - * @param string $encoding File encoding (see $Encoding) - * @param string $type File extension (MIME) type + * @param string $string String attachment data + * @param string $filename Name of the attachment + * @param string $encoding File encoding (see $Encoding) + * @param string $type File extension (MIME) type * @param string $disposition Disposition to use */ public function addStringAttachment( @@ -3121,7 +3208,7 @@ public function addStringAttachment( 4 => $type, 5 => true, // isStringAttachment 6 => $disposition, - 7 => 0 + 7 => 0, ]; } @@ -3134,12 +3221,12 @@ public function addStringAttachment( * the HTML refers to using the $cid value. * Never use a user-supplied path to a file! * - * @param string $path Path to the attachment - * @param string $cid Content ID of the attachment; Use this to reference - * the content when using an embedded image in HTML - * @param string $name Overrides the attachment name - * @param string $encoding File encoding (see $Encoding) - * @param string $type File MIME type + * @param string $path Path to the attachment + * @param string $cid Content ID of the attachment; Use this to reference + * the content when using an embedded image in HTML + * @param string $name Overrides the attachment name + * @param string $encoding File encoding (see $Encoding) + * @param string $type File MIME type * @param string $disposition Disposition to use * * @return bool True on successfully adding an attachment @@ -3148,6 +3235,7 @@ public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', { if (!@is_file($path)) { $this->setError($this->lang('file_access') . $path); + return false; } @@ -3170,8 +3258,9 @@ public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', 4 => $type, 5 => false, // isStringAttachment 6 => $disposition, - 7 => $cid + 7 => $cid, ]; + return true; } @@ -3181,12 +3270,12 @@ public function addEmbeddedImage($path, $cid, $name = '', $encoding = 'base64', * Be sure to set the $type to an image type for images: * JPEG images use 'image/jpeg', GIF uses 'image/gif', PNG uses 'image/png'. * - * @param string $string The attachment binary data - * @param string $cid Content ID of the attachment; Use this to reference - * the content when using an embedded image in HTML + * @param string $string The attachment binary data + * @param string $cid Content ID of the attachment; Use this to reference + * the content when using an embedded image in HTML * @param string $name - * @param string $encoding File encoding (see $Encoding) - * @param string $type MIME type + * @param string $encoding File encoding (see $Encoding) + * @param string $type MIME type * @param string $disposition Disposition to use * * @return bool True on successfully adding an attachment @@ -3213,8 +3302,9 @@ public function addStringEmbeddedImage( 4 => $type, 5 => true, // isStringAttachment 6 => $disposition, - 7 => $cid + 7 => $cid, ]; + return true; } @@ -3232,6 +3322,7 @@ protected function cidExists($cid) return true; } } + return false; } @@ -3247,6 +3338,7 @@ public function inlineImageExists() return true; } } + return false; } @@ -3262,6 +3354,7 @@ public function attachmentExists() return true; } } + return false; } @@ -3376,7 +3469,7 @@ protected function setError($msg) if (!empty($lasterror['error'])) { $msg .= $this->lang('smtp_error') . $lasterror['error']; if (!empty($lasterror['detail'])) { - $msg .= ' Detail: '. $lasterror['detail']; + $msg .= ' Detail: ' . $lasterror['detail']; } if (!empty($lasterror['smtp_code'])) { $msg .= ' SMTP code: ' . $lasterror['smtp_code']; @@ -3399,6 +3492,7 @@ public static function rfcDate() // Set the time zone to whatever the default is to avoid 500 errors // Will default to UTC if it's not set properly in php.ini date_default_timezone_set(@date_default_timezone_get()); + return date('D, j M Y H:i:s O'); } @@ -3422,9 +3516,9 @@ protected function serverHostname() } if (!static::isValidHost($result)) { return 'localhost.localdomain'; - } else { - return $result; } + + return $result; } /** @@ -3432,6 +3526,7 @@ protected function serverHostname() * IPv6 addresses must include [], e.g. `[::1]`, not just `::1`. * * @param string $host The host name or IP address to check + * * @return bool */ public static function isValidHost($host) @@ -3445,18 +3540,19 @@ public static function isValidHost($host) } //Looks like a bracketed IPv6 address if (trim($host, '[]') != $host) { - return (bool)filter_var(trim($host, '[]'), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); + return (bool) filter_var(trim($host, '[]'), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6); } //If removing all the dots results in a numeric string, it must be an IPv4 address. //Need to check this first because otherwise things like `999.0.0.0` are considered valid host names if (is_numeric(str_replace('.', '', $host))) { //Is it a valid IPv4 address? - return (bool)filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); + return (bool) filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4); } if (filter_var('http://' . $host, FILTER_VALIDATE_URL, FILTER_FLAG_HOST_REQUIRED)) { //Is it a syntactically valid hostname? return true; } + return false; } @@ -3480,30 +3576,31 @@ protected function lang($key) //but it's usually not PHPMailer's fault. return $this->language[$key] . ' https://github.com/PHPMailer/PHPMailer/wiki/Troubleshooting'; } + return $this->language[$key]; - } else { - //Return the key as a fallback - return $key; } + + //Return the key as a fallback + return $key; } /** * Check if an error occurred. * - * @return bool True if an error did occur. + * @return bool True if an error did occur */ public function isError() { - return ($this->error_count > 0); + return $this->error_count > 0; } /** * Add a custom header. * $name value can be overloaded to contain - * both header name and value (name:value) + * both header name and value (name:value). * * @param string $name Custom header name - * @param string $value Header value + * @param ?string $value Header value */ public function addCustomHeader($name, $value = null) { @@ -3536,14 +3633,12 @@ public function getCustomHeaders() * Converts data-uri images into embedded attachments. * If you don't want to apply these transformations to your HTML, just set Body and AltBody directly. * - * @access public - * @param string $message HTML message string - * @param string $basedir Absolute path to a base directory to prepend to relative paths to images + * @param string $message HTML message string + * @param string $basedir Absolute path to a base directory to prepend to relative paths to images * @param bool|callable $advanced Whether to use the internal HTML to text converter - * or your own custom converter @see PHPMailer::html2text() - * @return string $message The transformed message Body + * or your own custom converter @see PHPMailer::html2text(). * - * @return string $message + * @return string $message The transformed message Body */ public function msgHTML($message, $basedir = '', $advanced = false) { @@ -3605,7 +3700,7 @@ public function msgHTML($message, $basedir = '', $advanced = false) $cid, $filename, 'base64', - static::_mime_types((string)static::mb_pathinfo($filename, PATHINFO_EXTENSION)) + static::_mime_types((string) static::mb_pathinfo($filename, PATHINFO_EXTENSION)) ) ) { $message = preg_replace( @@ -3625,6 +3720,7 @@ public function msgHTML($message, $basedir = '', $advanced = false) $this->AltBody = 'This is an HTML-only message. To view it, activate HTML in your email application.' . static::$LE; } + return $this->Body; } @@ -3644,9 +3740,9 @@ public function msgHTML($message, $basedir = '', $advanced = false) * }); * * - * @param string $html The HTML text to convert + * @param string $html The HTML text to convert * @param bool|callable $advanced Any boolean value to use the internal converter, - * or provide your own callable for custom conversion. + * or provide your own callable for custom conversion. * * @return string */ @@ -3655,6 +3751,7 @@ public function html2text($html, $advanced = false) if (is_callable($advanced)) { return call_user_func($advanced, $html); } + return html_entity_decode( trim(strip_tags(preg_replace('/<(head|title|style|script)[^>]*>.*?<\/\\1>/si', '', $html))), ENT_QUOTES, @@ -3667,114 +3764,115 @@ public function html2text($html, $advanced = false) * * @param string $ext File extension * - * @return string MIME type of file. + * @return string MIME type of file */ public static function _mime_types($ext = '') { $mimes = [ - 'xl' => 'application/excel', - 'js' => 'application/javascript', - 'hqx' => 'application/mac-binhex40', - 'cpt' => 'application/mac-compactpro', - 'bin' => 'application/macbinary', - 'doc' => 'application/msword', - 'word' => 'application/msword', - 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', - 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', - 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', - 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', - 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', - 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', - 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', - 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', - 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', + 'xl' => 'application/excel', + 'js' => 'application/javascript', + 'hqx' => 'application/mac-binhex40', + 'cpt' => 'application/mac-compactpro', + 'bin' => 'application/macbinary', + 'doc' => 'application/msword', + 'word' => 'application/msword', + 'xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', + 'xltx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.template', + 'potx' => 'application/vnd.openxmlformats-officedocument.presentationml.template', + 'ppsx' => 'application/vnd.openxmlformats-officedocument.presentationml.slideshow', + 'pptx' => 'application/vnd.openxmlformats-officedocument.presentationml.presentation', + 'sldx' => 'application/vnd.openxmlformats-officedocument.presentationml.slide', + 'docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', + 'dotx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.template', + 'xlam' => 'application/vnd.ms-excel.addin.macroEnabled.12', + 'xlsb' => 'application/vnd.ms-excel.sheet.binary.macroEnabled.12', 'class' => 'application/octet-stream', - 'dll' => 'application/octet-stream', - 'dms' => 'application/octet-stream', - 'exe' => 'application/octet-stream', - 'lha' => 'application/octet-stream', - 'lzh' => 'application/octet-stream', - 'psd' => 'application/octet-stream', - 'sea' => 'application/octet-stream', - 'so' => 'application/octet-stream', - 'oda' => 'application/oda', - 'pdf' => 'application/pdf', - 'ai' => 'application/postscript', - 'eps' => 'application/postscript', - 'ps' => 'application/postscript', - 'smi' => 'application/smil', - 'smil' => 'application/smil', - 'mif' => 'application/vnd.mif', - 'xls' => 'application/vnd.ms-excel', - 'ppt' => 'application/vnd.ms-powerpoint', + 'dll' => 'application/octet-stream', + 'dms' => 'application/octet-stream', + 'exe' => 'application/octet-stream', + 'lha' => 'application/octet-stream', + 'lzh' => 'application/octet-stream', + 'psd' => 'application/octet-stream', + 'sea' => 'application/octet-stream', + 'so' => 'application/octet-stream', + 'oda' => 'application/oda', + 'pdf' => 'application/pdf', + 'ai' => 'application/postscript', + 'eps' => 'application/postscript', + 'ps' => 'application/postscript', + 'smi' => 'application/smil', + 'smil' => 'application/smil', + 'mif' => 'application/vnd.mif', + 'xls' => 'application/vnd.ms-excel', + 'ppt' => 'application/vnd.ms-powerpoint', 'wbxml' => 'application/vnd.wap.wbxml', - 'wmlc' => 'application/vnd.wap.wmlc', - 'dcr' => 'application/x-director', - 'dir' => 'application/x-director', - 'dxr' => 'application/x-director', - 'dvi' => 'application/x-dvi', - 'gtar' => 'application/x-gtar', - 'php3' => 'application/x-httpd-php', - 'php4' => 'application/x-httpd-php', - 'php' => 'application/x-httpd-php', + 'wmlc' => 'application/vnd.wap.wmlc', + 'dcr' => 'application/x-director', + 'dir' => 'application/x-director', + 'dxr' => 'application/x-director', + 'dvi' => 'application/x-dvi', + 'gtar' => 'application/x-gtar', + 'php3' => 'application/x-httpd-php', + 'php4' => 'application/x-httpd-php', + 'php' => 'application/x-httpd-php', 'phtml' => 'application/x-httpd-php', - 'phps' => 'application/x-httpd-php-source', - 'swf' => 'application/x-shockwave-flash', - 'sit' => 'application/x-stuffit', - 'tar' => 'application/x-tar', - 'tgz' => 'application/x-tar', - 'xht' => 'application/xhtml+xml', + 'phps' => 'application/x-httpd-php-source', + 'swf' => 'application/x-shockwave-flash', + 'sit' => 'application/x-stuffit', + 'tar' => 'application/x-tar', + 'tgz' => 'application/x-tar', + 'xht' => 'application/xhtml+xml', 'xhtml' => 'application/xhtml+xml', - 'zip' => 'application/zip', - 'mid' => 'audio/midi', - 'midi' => 'audio/midi', - 'mp2' => 'audio/mpeg', - 'mp3' => 'audio/mpeg', - 'mpga' => 'audio/mpeg', - 'aif' => 'audio/x-aiff', - 'aifc' => 'audio/x-aiff', - 'aiff' => 'audio/x-aiff', - 'ram' => 'audio/x-pn-realaudio', - 'rm' => 'audio/x-pn-realaudio', - 'rpm' => 'audio/x-pn-realaudio-plugin', - 'ra' => 'audio/x-realaudio', - 'wav' => 'audio/x-wav', - 'bmp' => 'image/bmp', - 'gif' => 'image/gif', - 'jpeg' => 'image/jpeg', - 'jpe' => 'image/jpeg', - 'jpg' => 'image/jpeg', - 'png' => 'image/png', - 'tiff' => 'image/tiff', - 'tif' => 'image/tiff', - 'eml' => 'message/rfc822', - 'css' => 'text/css', - 'html' => 'text/html', - 'htm' => 'text/html', + 'zip' => 'application/zip', + 'mid' => 'audio/midi', + 'midi' => 'audio/midi', + 'mp2' => 'audio/mpeg', + 'mp3' => 'audio/mpeg', + 'mpga' => 'audio/mpeg', + 'aif' => 'audio/x-aiff', + 'aifc' => 'audio/x-aiff', + 'aiff' => 'audio/x-aiff', + 'ram' => 'audio/x-pn-realaudio', + 'rm' => 'audio/x-pn-realaudio', + 'rpm' => 'audio/x-pn-realaudio-plugin', + 'ra' => 'audio/x-realaudio', + 'wav' => 'audio/x-wav', + 'bmp' => 'image/bmp', + 'gif' => 'image/gif', + 'jpeg' => 'image/jpeg', + 'jpe' => 'image/jpeg', + 'jpg' => 'image/jpeg', + 'png' => 'image/png', + 'tiff' => 'image/tiff', + 'tif' => 'image/tiff', + 'eml' => 'message/rfc822', + 'css' => 'text/css', + 'html' => 'text/html', + 'htm' => 'text/html', 'shtml' => 'text/html', - 'log' => 'text/plain', - 'text' => 'text/plain', - 'txt' => 'text/plain', - 'rtx' => 'text/richtext', - 'rtf' => 'text/rtf', - 'vcf' => 'text/vcard', + 'log' => 'text/plain', + 'text' => 'text/plain', + 'txt' => 'text/plain', + 'rtx' => 'text/richtext', + 'rtf' => 'text/rtf', + 'vcf' => 'text/vcard', 'vcard' => 'text/vcard', - 'ics' => 'text/calendar', - 'xml' => 'text/xml', - 'xsl' => 'text/xml', - 'mpeg' => 'video/mpeg', - 'mpe' => 'video/mpeg', - 'mpg' => 'video/mpeg', - 'mov' => 'video/quicktime', - 'qt' => 'video/quicktime', - 'rv' => 'video/vnd.rn-realvideo', - 'avi' => 'video/x-msvideo', - 'movie' => 'video/x-sgi-movie' + 'ics' => 'text/calendar', + 'xml' => 'text/xml', + 'xsl' => 'text/xml', + 'mpeg' => 'video/mpeg', + 'mpe' => 'video/mpeg', + 'mpg' => 'video/mpeg', + 'mov' => 'video/quicktime', + 'qt' => 'video/quicktime', + 'rv' => 'video/vnd.rn-realvideo', + 'avi' => 'video/x-msvideo', + 'movie' => 'video/x-sgi-movie', ]; if (array_key_exists(strtolower($ext), $mimes)) { return $mimes[strtolower($ext)]; } + return 'application/octet-stream'; } @@ -3794,18 +3892,20 @@ public static function filenameToType($filename) $filename = substr($filename, 0, $qpos); } $ext = static::mb_pathinfo($filename, PATHINFO_EXTENSION); + return static::_mime_types($ext); } /** * Multi-byte-safe pathinfo replacement. - * Drop-in replacement for pathinfo(), but multibyte- and cross-platform-safe + * Drop-in replacement for pathinfo(), but multibyte- and cross-platform-safe. * - * @param string $path A filename or path, does not need to exist as a file + * @see http://www.php.net/manual/en/function.pathinfo.php#107461 + * + * @param string $path A filename or path, does not need to exist as a file * @param int|string $options Either a PATHINFO_* constant, - * or a string name to return only the specified piece + * or a string name to return only the specified piece * - * @see http://www.php.net/manual/en/function.pathinfo.php#107461 * @return string|array */ public static function mb_pathinfo($path, $options = null) @@ -3851,10 +3951,10 @@ public static function mb_pathinfo($path, $options = null) * Usage Example: * `$mail->set('SMTPSecure', 'tls');` * is the same as: - * `$mail->SMTPSecure = 'tls';` + * `$mail->SMTPSecure = 'tls';`. * - * @param string $name The property name to set - * @param mixed $value The value to set the property to + * @param string $name The property name to set + * @param mixed $value The value to set the property to * * @return bool */ @@ -3862,11 +3962,12 @@ public function set($name, $value = '') { if (property_exists($this, $name)) { $this->$name = $value; + return true; - } else { - $this->setError($this->lang('variable_set') . $name); - return false; } + $this->setError($this->lang('variable_set') . $name); + + return false; } /** @@ -3902,6 +4003,7 @@ public static function normalizeBreaks($text, $breaktype = null) if ("\n" !== static::$LE) { $text = str_replace("\n", $breaktype, $text); } + return $text; } @@ -3930,7 +4032,7 @@ protected static function setLE($le) * * @param string $cert_filename * @param string $key_filename - * @param string $key_pass Password for private key + * @param string $key_pass Password for private key * @param string $extracerts_filename Optional path to chain certificate */ public function sign($cert_filename, $key_filename, $key_pass, $extracerts_filename = '') @@ -3960,6 +4062,7 @@ public function DKIM_QP($txt) $line .= '=' . sprintf('%02X', $ord); } } + return $line; } @@ -3969,6 +4072,7 @@ public function DKIM_QP($txt) * @param string $signHeader * * @throws Exception + * * @return string The DKIM signature value */ public function DKIM_Sign($signHeader) @@ -3977,11 +4081,12 @@ public function DKIM_Sign($signHeader) if ($this->exceptions) { throw new Exception($this->lang('extension_missing') . 'openssl'); } + return ''; } $privKeyStr = !empty($this->DKIM_private_string) ? - $this->DKIM_private_string : - file_get_contents($this->DKIM_private); + $this->DKIM_private_string : + file_get_contents($this->DKIM_private); if ('' != $this->DKIM_passphrase) { $privKey = openssl_pkey_get_private($privKeyStr, $this->DKIM_passphrase); } else { @@ -3989,26 +4094,29 @@ public function DKIM_Sign($signHeader) } if (openssl_sign($signHeader, $signature, $privKey, 'sha256WithRSAEncryption')) { openssl_pkey_free($privKey); + return base64_encode($signature); } openssl_pkey_free($privKey); + return ''; } /** * Generate a DKIM canonicalization header. - * Uses the 'relaxed' algorithm from RFC6376 section 3.4.2 + * Uses the 'relaxed' algorithm from RFC6376 section 3.4.2. + * + * @see https://tools.ietf.org/html/rfc6376#section-3.4.2 * * @param string $signHeader Header * * @return string - * @see https://tools.ietf.org/html/rfc6376#section-3.4.2 */ public function DKIM_HeaderC($signHeader) { //Unfold all header continuation lines //Also collapses folded whitespace. - //Note PCRE \s is too broad a definition of whitespace; RFC5322 defines it as [ \t] + //Note PCRE \s is too broad a definition of whitespace; RFC5322 defines it as `[ \t]` //@see https://tools.ietf.org/html/rfc5322#section-2.2 //That means this may break if you do something daft like put vertical tabs in your headers. $signHeader = preg_replace('/\r\n[ \t]+/', ' ', $signHeader); @@ -4031,18 +4139,19 @@ public function DKIM_HeaderC($signHeader) //by elimination, the same applies to the field name $lines[$key] = trim($heading, " \t") . ':' . trim($value, " \t"); } - $signHeader = implode(static::$LE, $lines); - return $signHeader; + + return implode(static::$LE, $lines); } /** * Generate a DKIM canonicalization body. - * Uses the 'simple' algorithm from RFC6376 section 3.4.3 + * Uses the 'simple' algorithm from RFC6376 section 3.4.3. + * + * @see https://tools.ietf.org/html/rfc6376#section-3.4.3 * * @param string $body Message Body * * @return string - * @see https://tools.ietf.org/html/rfc6376#section-3.4.3 */ public function DKIM_BodyC($body) { @@ -4051,6 +4160,7 @@ public function DKIM_BodyC($body) } // Normalize line endings $body = static::normalizeBreaks($body); + //Reduce multiple trailing line breaks to a single one return rtrim($body, "\r\n") . static::$LE; } @@ -4059,8 +4169,8 @@ public function DKIM_BodyC($body) * Create the DKIM header and body in a new message header. * * @param string $headers_line Header lines - * @param string $subject Subject - * @param string $body Body + * @param string $subject Subject + * @param string $body Body * * @return string */ @@ -4133,6 +4243,7 @@ public function DKIM_Add($headers_line, $subject, $body) $dkimhdrs ); $signed = $this->DKIM_Sign($toSign); + return static::normalizeBreaks($dkimhdrs . $signed) . static::$LE; } @@ -4146,12 +4257,11 @@ public function DKIM_Add($headers_line, $subject, $body) */ public static function hasLineLongerThanMax($str) { - return (bool)preg_match('/^(.{'.(self::MAX_LINE_LENGTH + strlen(static::$LE)).',})/m', $str); + return (bool) preg_match('/^(.{' . (self::MAX_LINE_LENGTH + strlen(static::$LE)) . ',})/m', $str); } /** * Allows for public read access to 'to' property. - * * Before the send() call, queued addresses (i.e. with IDN) are not yet included. * * @return array @@ -4163,7 +4273,6 @@ public function getToAddresses() /** * Allows for public read access to 'cc' property. - * * Before the send() call, queued addresses (i.e. with IDN) are not yet included. * * @return array @@ -4175,7 +4284,6 @@ public function getCcAddresses() /** * Allows for public read access to 'bcc' property. - * * Before the send() call, queued addresses (i.e. with IDN) are not yet included. * * @return array @@ -4187,7 +4295,6 @@ public function getBccAddresses() /** * Allows for public read access to 'ReplyTo' property. - * * Before the send() call, queued addresses (i.e. with IDN) are not yet included. * * @return array @@ -4199,7 +4306,6 @@ public function getReplyToAddresses() /** * Allows for public read access to 'all_recipients' property. - * * Before the send() call, queued addresses (i.e. with IDN) are not yet included. * * @return array @@ -4212,10 +4318,10 @@ public function getAllRecipientAddresses() /** * Perform a callback. * - * @param bool $isSent - * @param array $to - * @param array $cc - * @param array $bcc + * @param bool $isSent + * @param array $to + * @param array $cc + * @param array $bcc * @param string $subject * @param string $body * @param string $from diff --git a/src/POP3.php b/src/POP3.php index b0b86138f..62e01f9e0 100644 --- a/src/POP3.php +++ b/src/POP3.php @@ -1,15 +1,15 @@ * @author Jim Jagielski (jimjag) * @author Andy Prevost (codeworxtech) * @author Brent R. Matzelle (original founder) - * @copyright 2012 - 2016 Marcus Bointon + * @copyright 2012 - 2017 Marcus Bointon * @copyright 2010 - 2012 Jim Jagielski * @copyright 2004 - 2009 Andy Prevost * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License @@ -33,7 +33,6 @@ * enough to do authentication. * If you want a more complete class there are other POP3 classes for PHP available. * - * @package PHPMailer * @author Richard Davey (original author) * @author Marcus Bointon (Synchro/coolbru) * @author Jim Jagielski (jimjag) @@ -64,7 +63,7 @@ class POP3 /** * Debug display level. - * Options: 0 = no, 1+ = yes + * Options: 0 = no, 1+ = yes. * * @var int */ @@ -92,7 +91,7 @@ class POP3 public $tval; /** - * POP3 username + * POP3 username. * * @var string */ @@ -127,19 +126,19 @@ class POP3 protected $errors = []; /** - * Line break constant + * Line break constant. */ const LE = "\r\n"; /** - * Simple static wrapper for all-in-one POP before SMTP + * Simple static wrapper for all-in-one POP before SMTP. * - * @param string $host - * @param int|bool $port The port number to connect to + * @param string $host + * @param int|bool $port The port number to connect to * @param int|bool $timeout The timeout value - * @param string $username - * @param string $password - * @param int $debug_level + * @param string $username + * @param string $password + * @param int $debug_level * * @return bool */ @@ -151,7 +150,8 @@ public static function popBeforeSmtp( $password = '', $debug_level = 0 ) { - $pop = new POP3; + $pop = new self(); + return $pop->authorise($host, $port, $timeout, $username, $password, $debug_level); } @@ -160,12 +160,12 @@ public static function popBeforeSmtp( * A connect, login, disconnect sequence * appropriate for POP-before SMTP authorisation. * - * @param string $host The hostname to connect to - * @param int|bool $port The port number to connect to + * @param string $host The hostname to connect to + * @param int|bool $port The port number to connect to * @param int|bool $timeout The timeout value - * @param string $username - * @param string $password - * @param int $debug_level + * @param string $username + * @param string $password + * @param int $debug_level * * @return bool */ @@ -176,13 +176,13 @@ public function authorise($host, $port = false, $timeout = false, $username = '' if (false === $port) { $this->port = static::DEFAULT_PORT; } else { - $this->port = (integer)$port; + $this->port = (int) $port; } // If no timeout value provided, use default if (false === $timeout) { $this->tval = static::DEFAULT_TIMEOUT; } else { - $this->tval = (integer)$timeout; + $this->tval = (int) $timeout; } $this->do_debug = $debug_level; $this->username = $username; @@ -195,20 +195,22 @@ public function authorise($host, $port = false, $timeout = false, $username = '' $login_result = $this->login($this->username, $this->password); if ($login_result) { $this->disconnect(); + return true; } } // We need to disconnect regardless of whether the login succeeded $this->disconnect(); + return false; } /** * Connect to a POP3 server. * - * @param string $host + * @param string $host * @param int|bool $port - * @param int $tval + * @param int $tval * * @return bool */ @@ -244,6 +246,7 @@ public function connect($host, $port = false, $tval = 30) $this->setError( "Failed to connect to server $host on port $port. errno: $errno; errstr: $errstr" ); + return false; } @@ -256,8 +259,10 @@ public function connect($host, $port = false, $tval = 30) if ($this->checkResponse($pop3_response)) { // The connection is established and the POP3 server is talking $this->connected = true; + return true; } + return false; } @@ -293,6 +298,7 @@ public function login($username = '', $password = '') return true; } } + return false; } @@ -308,14 +314,13 @@ public function disconnect() @fclose($this->pop_conn); } catch (Exception $e) { //Do nothing - }; + } } /** * Get a response from the POP3 server. - * $size is the maximum number of bytes to retrieve * - * @param int $size + * @param int $size The maximum number of bytes to retrieve * * @return string */ @@ -325,6 +330,7 @@ protected function getResponse($size = 128) if ($this->do_debug >= 1) { echo 'Server -> Client: ', $response; } + return $response; } @@ -341,8 +347,10 @@ protected function sendString($string) if ($this->do_debug >= 2) { //Show client messages when debug >= 2 echo 'Client -> Server: ', $string; } + return fwrite($this->pop_conn, $string, strlen($string)); } + return 0; } @@ -358,10 +366,11 @@ protected function checkResponse($string) { if (substr($string, 0, 3) !== '+OK') { $this->setError("Server reported an error: $string"); + return false; - } else { - return true; } + + return true; } /** @@ -395,15 +404,15 @@ public function getErrors() /** * POP3 connection error handler. * - * @param int $errno + * @param int $errno * @param string $errstr * @param string $errfile - * @param int $errline + * @param int $errline */ protected function catchWarning($errno, $errstr, $errfile, $errline) { $this->setError( - 'Connecting to the POP3 server raised a PHP warning:'. + 'Connecting to the POP3 server raised a PHP warning:' . "errno: $errno errstr: $errstr; errfile: $errfile; errline: $errline" ); } diff --git a/src/SMTP.php b/src/SMTP.php index 1c55aadd2..22c47d96c 100644 --- a/src/SMTP.php +++ b/src/SMTP.php @@ -1,15 +1,14 @@ * @author Jim Jagielski (jimjag) * @author Andy Prevost (codeworxtech) * @author Brent R. Matzelle (original founder) - * @copyright 2012 - 2016 Marcus Bointon + * @copyright 2012 - 2017 Marcus Bointon * @copyright 2010 - 2012 Jim Jagielski * @copyright 2004 - 2009 Andy Prevost * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License @@ -24,7 +23,6 @@ * PHPMailer RFC821 SMTP email transport class. * Implements RFC 821 SMTP commands and provides some utility methods for sending mail to an SMTP server. * - * @package PHPMailer * @author Chris Ryan * @author Marcus Bointon */ @@ -52,34 +50,34 @@ class SMTP const DEFAULT_PORT = 25; /** - * The maximum line length allowed by RFC 2822 section 2.1.1 + * The maximum line length allowed by RFC 2822 section 2.1.1. * * @var int */ const MAX_LINE_LENGTH = 998; /** - * Debug level for no output + * Debug level for no output. */ const DEBUG_OFF = 0; /** - * Debug level to show client -> server messages + * Debug level to show client -> server messages. */ const DEBUG_CLIENT = 1; /** - * Debug level to show client -> server and server -> client messages + * Debug level to show client -> server and server -> client messages. */ const DEBUG_SERVER = 2; /** - * Debug level to show connection status, client -> server and server -> client messages + * Debug level to show connection status, client -> server and server -> client messages. */ const DEBUG_CONNECTION = 3; /** - * Debug level to show all messages + * Debug level to show all messages. */ const DEBUG_LOWLEVEL = 4; @@ -90,7 +88,7 @@ class SMTP * * self::DEBUG_CLIENT (`1`) Client commands * * self::DEBUG_SERVER (`2`) Client commands and server responses * * self::DEBUG_CONNECTION (`3`) As DEBUG_SERVER plus connection status - * * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages + * * self::DEBUG_LOWLEVEL (`4`) Low-level data output, all messages. * * @var int */ @@ -121,23 +119,25 @@ class SMTP * * @see http://en.wikipedia.org/wiki/Variable_envelope_return_path * @see http://www.postfix.org/VERP_README.html Info on VERP + * * @var bool */ public $do_verp = false; /** * The timeout value for connection, in seconds. - * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2. * This needs to be quite high to function correctly with hosts using greetdelay as an anti-spam measure. * * @see http://tools.ietf.org/html/rfc2821#section-4.5.3.2 + * * @var int */ public $Timeout = 300; /** * How long to wait for commands to complete, in seconds. - * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2 + * Default of 5 minutes (300sec) is from RFC2821 section 4.5.3.2. * * @var int */ @@ -152,7 +152,7 @@ class SMTP 'exim' => '/[0-9]{3} OK id=(.*)/', 'sendmail' => '/[0-9]{3} 2.0.0 (.*) Message/', 'postfix' => '/[0-9]{3} 2.0.0 Ok: queued as (.*)/', - 'Microsoft_ESMTP' => '/[0-9]{3} 2.[0-9].0 (.*)@(?:.*) Queued mail for delivery/' + 'Microsoft_ESMTP' => '/[0-9]{3} 2.[0-9].0 (.*)@(?:.*) Queued mail for delivery/', ]; /** @@ -210,8 +210,8 @@ class SMTP /** * Output debugging info via a user-selected method. * - * @param string $str Debug string to output - * @param int $level The debug level of this message; see DEBUG_* constants + * @param string $str Debug string to output + * @param int $level The debug level of this message; see DEBUG_* constants * * @see SMTP::$Debugoutput * @see SMTP::$do_debug @@ -224,11 +224,13 @@ protected function edebug($str, $level = 0) //Is this a PSR-3 logger? if (is_a($this->Debugoutput, 'Psr\Log\LoggerInterface')) { $this->Debugoutput->debug($str); + return; } //Avoid clash with built-in function names if (!in_array($this->Debugoutput, ['error_log', 'html', 'echo']) and is_callable($this->Debugoutput)) { call_user_func($this->Debugoutput, $str, $level); + return; } switch ($this->Debugoutput) { @@ -249,27 +251,27 @@ protected function edebug($str, $level = 0) //Normalize line breaks $str = preg_replace('/\r\n|\r/ms', "\n", $str); echo gmdate('Y-m-d H:i:s'), - "\t", + "\t", //Trim trailing space - trim( - //Indent for readability, except for trailing break - str_replace( - "\n", - "\n \t ", - trim($str) - ) - ), - "\n"; + trim( + //Indent for readability, except for trailing break + str_replace( + "\n", + "\n \t ", + trim($str) + ) + ), + "\n"; } } /** * Connect to an SMTP server. * - * @param string $host SMTP server IP or host name - * @param int $port The port number to connect to - * @param int $timeout How long to wait for the connection to open - * @param array $options An array of options for stream_context_create() + * @param string $host SMTP server IP or host name + * @param int $port The port number to connect to + * @param int $timeout How long to wait for the connection to open + * @param array $options An array of options for stream_context_create() * * @return bool */ @@ -287,6 +289,7 @@ public function connect($host, $port = null, $timeout = 30, $options = []) if ($this->connected()) { // Already connected, generate error $this->setError('Already connected to a server'); + return false; } if (empty($port)) { @@ -295,7 +298,7 @@ public function connect($host, $port = null, $timeout = 30, $options = []) // Connect to the SMTP server $this->edebug( "Connection: opening to $host:$port, timeout=$timeout, options=" . - (count($options) > 0 ? var_export($options, true): 'array()'), + (count($options) > 0 ? var_export($options, true) : 'array()'), self::DEBUG_CONNECTION ); $errno = 0; @@ -304,7 +307,7 @@ public function connect($host, $port = null, $timeout = 30, $options = []) $socket_context = stream_context_create($options); set_error_handler([$this, 'errorHandler']); $this->smtp_conn = stream_socket_client( - $host . ":" . $port, + $host . ':' . $port, $errno, $errstr, $timeout, @@ -315,7 +318,7 @@ public function connect($host, $port = null, $timeout = 30, $options = []) } else { //Fall back to fsockopen which should work in more places, but is missing some features $this->edebug( - "Connection: stream_socket_client not available, falling back to fsockopen", + 'Connection: stream_socket_client not available, falling back to fsockopen', self::DEBUG_CONNECTION ); set_error_handler([$this, 'errorHandler']); @@ -333,14 +336,15 @@ public function connect($host, $port = null, $timeout = 30, $options = []) $this->setError( 'Failed to connect to server', '', - (string)$errno, - (string)$errstr + (string) $errno, + (string) $errstr ); $this->edebug( 'SMTP ERROR: ' . $this->error['error'] . ": $errstr ($errno)", self::DEBUG_CLIENT ); + return false; } $this->edebug('Connection: opened', self::DEBUG_CONNECTION); @@ -357,6 +361,7 @@ public function connect($host, $port = null, $timeout = 30, $options = []) // Get any announcement $announce = $this->get_lines(); $this->edebug('SERVER -> CLIENT: ' . $announce, self::DEBUG_SERVER); + return true; } @@ -389,20 +394,22 @@ public function startTLS() $crypto_method ); restore_error_handler(); - return (bool)$crypto_ok; + + return (bool) $crypto_ok; } /** * Perform SMTP authentication. * Must be run after hello(). * + * @see hello() + * * @param string $username The user name * @param string $password The password * @param string $authtype The auth type (CRAM-MD5, PLAIN, LOGIN, XOAUTH2) - * @param OAuth $OAuth An optional OAuth instance for XOAUTH2 authentication + * @param OAuth $OAuth An optional OAuth instance for XOAUTH2 authentication * - * @return bool True if successfully authenticated. - * @see hello() + * @return bool True if successfully authenticated */ public function authenticate( $username, @@ -412,6 +419,7 @@ public function authenticate( ) { if (!$this->server_caps) { $this->setError('Authentication is not allowed before HELO/EHLO'); + return false; } @@ -421,6 +429,7 @@ public function authenticate( $this->setError('Authentication is not allowed at this stage'); // 'at this stage' means that auth may be allowed after the stage changes // e.g. after STARTTLS + return false; } @@ -447,6 +456,7 @@ public function authenticate( } if (empty($authtype)) { $this->setError('No supported authentication methods found'); + return false; } self::edebug('Auth method selected: ' . $authtype, self::DEBUG_LOWLEVEL); @@ -454,6 +464,7 @@ public function authenticate( if (!in_array($authtype, $this->server_caps['AUTH'])) { $this->setError("The requested authentication method \"$authtype\" is not supported by the server"); + return false; } } elseif (empty($authtype)) { @@ -480,10 +491,10 @@ public function authenticate( if (!$this->sendCommand('AUTH', 'AUTH LOGIN', 334)) { return false; } - if (!$this->sendCommand("Username", base64_encode($username), 334)) { + if (!$this->sendCommand('Username', base64_encode($username), 334)) { return false; } - if (!$this->sendCommand("Password", base64_encode($password), 235)) { + if (!$this->sendCommand('Password', base64_encode($password), 235)) { return false; } break; @@ -514,18 +525,20 @@ public function authenticate( break; default: $this->setError("Authentication method \"$authtype\" is not supported"); + return false; } + return true; } /** * Calculate an MD5 HMAC hash. * Works like hash_hmac('md5', $data, $key) - * in case that function is not available + * in case that function is not available. * * @param string $data The data to hash - * @param string $key The key to hash with + * @param string $key The key to hash with * * @return string */ @@ -559,7 +572,7 @@ protected function hmac($data, $key) /** * Check connection state. * - * @return bool True if connected. + * @return bool True if connected */ public function connected() { @@ -572,10 +585,13 @@ public function connected() self::DEBUG_CLIENT ); $this->close(); + return false; } + return true; // everything looks good } + return false; } @@ -605,7 +621,7 @@ public function close() * that is to be send with the headers. Each header needs to be * on a single line followed by a with the message headers * and the message body being separated by an additional . - * Implements RFC 821: DATA + * Implements RFC 821: DATA . * * @param string $msg_data Message data to send * @@ -688,6 +704,7 @@ public function data($msg_data) $this->recordLastTransactionID(); //Restore timelimit $this->Timelimit = $savetimelimit; + return $result; } @@ -705,17 +722,18 @@ public function data($msg_data) public function hello($host = '') { //Try extended hello first (RFC 2821) - return (bool)($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host)); + return (bool) ($this->sendHello('EHLO', $host) or $this->sendHello('HELO', $host)); } /** * Send an SMTP HELO or EHLO command. - * Low-level implementation used by hello() + * Low-level implementation used by hello(). * * @param string $hello The HELO string - * @param string $host The hostname to say we are + * @param string $host The hostname to say we are * * @return bool + * * @see hello() */ protected function sendHello($hello, $host) @@ -727,6 +745,7 @@ protected function sendHello($hello, $host) } else { $this->server_caps = null; } + return $noerror; } @@ -778,7 +797,7 @@ protected function parseHelloFields($type) * $from. Returns true if successful or false otherwise. If True * the mail transaction is started and then one or more recipient * commands may be called followed by a data command. - * Implements RFC 821: MAIL FROM: + * Implements RFC 821: MAIL FROM: . * * @param string $from Source address of this message * @@ -787,6 +806,7 @@ protected function parseHelloFields($type) public function mail($from) { $useVerp = ($this->do_verp ? ' XVERP' : ''); + return $this->sendCommand( 'MAIL FROM', 'MAIL FROM:<' . $from . '>' . $useVerp, @@ -797,7 +817,7 @@ public function mail($from) /** * Send an SMTP QUIT command. * Closes the socket if there is no error or the $close_on_error argument is true. - * Implements from RFC 821: QUIT + * Implements from RFC 821: QUIT . * * @param bool $close_on_error Should the connection close if an error occurs? * @@ -811,6 +831,7 @@ public function quit($close_on_error = true) $this->close(); $this->error = $err; //Restore any error from the quit command } + return $noerror; } @@ -818,7 +839,7 @@ public function quit($close_on_error = true) * Send an SMTP RCPT command. * Sets the TO argument to $toaddr. * Returns true if the recipient was accepted false if it was rejected. - * Implements from RFC 821: RCPT TO: + * Implements from RFC 821: RCPT TO: . * * @param string $address The address the message is being sent to * @@ -836,9 +857,9 @@ public function recipient($address) /** * Send an SMTP RSET command. * Abort any transaction that is currently in progress. - * Implements RFC 821: RSET + * Implements RFC 821: RSET . * - * @return bool True on success. + * @return bool True on success */ public function reset() { @@ -848,21 +869,23 @@ public function reset() /** * Send a command to an SMTP server and check its return code. * - * @param string $command The command name - not sent to the server - * @param string $commandstring The actual command to send - * @param int|array $expect One or more expected integer success codes + * @param string $command The command name - not sent to the server + * @param string $commandstring The actual command to send + * @param int|array $expect One or more expected integer success codes * - * @return bool True on success. + * @return bool True on success */ protected function sendCommand($command, $commandstring, $expect) { if (!$this->connected()) { $this->setError("Called $command without being connected"); + return false; } //Reject line breaks in all commands if (strpos($commandstring, "\n") !== false or strpos($commandstring, "\r") !== false) { $this->setError("Command '$command' contained line breaks"); + return false; } $this->client_send($commandstring . static::LE); @@ -870,13 +893,13 @@ protected function sendCommand($command, $commandstring, $expect) $this->last_reply = $this->get_lines(); // Fetch SMTP code and possible error code explanation $matches = []; - if (preg_match("/^([0-9]{3})[ -](?:([0-9]\\.[0-9]\\.[0-9]) )?/", $this->last_reply, $matches)) { + if (preg_match('/^([0-9]{3})[ -](?:([0-9]\\.[0-9]\\.[0-9]) )?/', $this->last_reply, $matches)) { $code = $matches[1]; $code_ex = (count($matches) > 2 ? $matches[2] : null); // Cut off error code from each response line $detail = preg_replace( "/{$code}[ -]" . - ($code_ex ? str_replace('.', '\\.', $code_ex) . ' ' : '') . "/m", + ($code_ex ? str_replace('.', '\\.', $code_ex) . ' ' : '') . '/m', '', $this->last_reply ); @@ -889,7 +912,7 @@ protected function sendCommand($command, $commandstring, $expect) $this->edebug('SERVER -> CLIENT: ' . $this->last_reply, self::DEBUG_SERVER); - if (!in_array($code, (array)$expect)) { + if (!in_array($code, (array) $expect)) { $this->setError( "$command command failed", $detail, @@ -900,10 +923,12 @@ protected function sendCommand($command, $commandstring, $expect) 'SMTP ERROR: ' . $this->error['error'] . ': ' . $this->last_reply, self::DEBUG_CLIENT ); + return false; } $this->setError(''); + return true; } @@ -915,7 +940,7 @@ protected function sendCommand($command, $commandstring, $expect) * commands may be called followed by a data command. This command * will send the message to the users terminal if they are logged * in and send them an email. - * Implements RFC 821: SAML FROM: + * Implements RFC 821: SAML FROM: . * * @param string $from The address the message is from * @@ -940,7 +965,7 @@ public function verify($name) /** * Send an SMTP NOOP command. - * Used to keep keep-alives alive, doesn't actually do anything + * Used to keep keep-alives alive, doesn't actually do anything. * * @return bool */ @@ -953,8 +978,8 @@ public function noop() * Send an SMTP TURN command. * This is an optional command for SMTP that this class does not support. * This method is here to make the RFC821 Definition complete for this class - * and _may_ be implemented in future - * Implements from RFC 821: TURN + * and _may_ be implemented in future. + * Implements from RFC 821: TURN . * * @return bool */ @@ -962,6 +987,7 @@ public function turn() { $this->setError('The SMTP TURN command is not implemented'); $this->edebug('SMTP NOTICE: ' . $this->error['error'], self::DEBUG_CLIENT); + return false; } @@ -978,6 +1004,7 @@ public function client_send($data) set_error_handler([$this, 'errorHandler']); $result = fwrite($this->smtp_conn, $data); restore_error_handler(); + return $result; } @@ -992,7 +1019,7 @@ public function getError() } /** - * Get SMTP extensions available on the server + * Get SMTP extensions available on the server. * * @return array|null */ @@ -1002,21 +1029,17 @@ public function getServerExtList() } /** - * A multipurpose method - * The method works in three ways, dependent on argument value and current state - * 1. HELO/EHLO was not sent - returns null and set up $this->error - * 2. HELO was sent - * $name = 'HELO': returns server name - * $name = 'EHLO': returns boolean false - * $name = any string: returns null and set up $this->error - * 3. EHLO was sent - * $name = 'HELO'|'EHLO': returns server name - * $name = any string: if extension $name exists, returns boolean True - * or its options. Otherwise returns boolean False - * In other words, one can use this method to detect 3 conditions: - * - null returned: handshake was not or we don't know about ext (refer to $this->error) - * - false returned: the requested feature exactly not exists - * - positive value returned: the requested feature exists + * Get metadata about the SMTP server from its HELO/EHLO response. + * The method works in three ways, dependent on argument value and current state: + * 1. HELO/EHLO has not been sent - returns null and populates $this->error. + * 2. HELO has been sent - + * $name == 'HELO': returns server name + * $name == 'EHLO': returns boolean false + * $name == any other string: returns null and populates $this->error + * 3. EHLO has been sent - + * $name == 'HELO'|'EHLO': returns the server name + * $name == any other string: if extension $name exists, returns True + * or its options (e.g. AUTH mechanisms supported). Otherwise returns False. * * @param string $name Name of SMTP extension or 'HELO'|'EHLO' * @@ -1026,10 +1049,10 @@ public function getServerExt($name) { if (!$this->server_caps) { $this->setError('No HELO/EHLO was sent'); - return null; + + return; } - // the tight logic knot ;) if (!array_key_exists($name, $this->server_caps)) { if ('HELO' == $name) { return $this->server_caps['EHLO']; @@ -1037,8 +1060,9 @@ public function getServerExt($name) if ('EHLO' == $name || array_key_exists('EHLO', $this->server_caps)) { return false; } - $this->setError('HELO handshake was used. Client knows nothing about server extensions'); - return null; + $this->setError('HELO handshake was used; No information about server extensions available'); + + return; } return $this->server_caps[$name]; @@ -1115,6 +1139,7 @@ protected function get_lines() break; } } + return $data; } @@ -1141,9 +1166,9 @@ public function getVerp() /** * Set error messages and codes. * - * @param string $message The error message - * @param string $detail Further detail on the error - * @param string $smtp_code An associated SMTP error code + * @param string $message The error message + * @param string $detail Further detail on the error + * @param string $smtp_code An associated SMTP error code * @param string $smtp_code_ex Extended SMTP code */ protected function setError($message, $detail = '', $smtp_code = '', $smtp_code_ex = '') @@ -1152,7 +1177,7 @@ protected function setError($message, $detail = '', $smtp_code = '', $smtp_code_ 'error' => $message, 'detail' => $detail, 'smtp_code' => $smtp_code, - 'smtp_code_ex' => $smtp_code_ex + 'smtp_code_ex' => $smtp_code_ex, ]; } @@ -1199,7 +1224,7 @@ public function getDebugLevel() /** * Set SMTP timeout. * - * @param int $timeout + * @param int $timeout The timeout duration in seconds */ public function setTimeout($timeout = 0) { @@ -1219,10 +1244,10 @@ public function getTimeout() /** * Reports an error number and string. * - * @param int $errno The error number returned by PHP - * @param string $errmsg The error message returned by PHP + * @param int $errno The error number returned by PHP + * @param string $errmsg The error message returned by PHP * @param string $errfile The file the error occurred in - * @param int $errline The line number the error occurred on + * @param int $errline The line number the error occurred on */ protected function errorHandler($errno, $errmsg, $errfile = '', $errline = 0) { @@ -1230,7 +1255,7 @@ protected function errorHandler($errno, $errmsg, $errfile = '', $errline = 0) $this->setError( $notice, $errmsg, - (string)$errno + (string) $errno ); $this->edebug( "$notice Error #$errno: $errmsg [$errfile line $errline]", @@ -1244,6 +1269,7 @@ protected function errorHandler($errno, $errmsg, $errfile = '', $errline = 0) * Relies on the host providing the ID in response to a DATA command. * If no reply has been received yet, it will return null. * If no pattern was matched, it will return false. + * * @return bool|null|string */ protected function recordLastTransactionID() @@ -1268,7 +1294,9 @@ protected function recordLastTransactionID() * Get the queue/transaction ID of the last SMTP transaction * If no reply has been received yet, it will return null. * If no pattern was matched, it will return false. + * * @return bool|null|string + * * @see recordLastTransactionID() */ public function getLastTransactionID() diff --git a/test/bootstrap.php b/test/bootstrap.php index 53f277e7e..bff07b9fc 100644 --- a/test/bootstrap.php +++ b/test/bootstrap.php @@ -1,6 +1,6 @@ * @author Andy Prevost - * @copyright 2010 - 2016 Marcus Bointon + * @copyright 2010 - 2017 Marcus Bointon * @copyright 2004 - 2009 Andy Prevost * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ @@ -15,8 +14,7 @@ namespace PHPMailer\PHPMailer; /** - * PHPMailer - PHP email transport unit test class - * Performs authentication tests + * Check language files for missing or excess translations. */ class PHPMailerLangTest extends \PHPUnit_Framework_TestCase { @@ -28,7 +26,7 @@ class PHPMailerLangTest extends \PHPUnit_Framework_TestCase public $Mail; /** - * Default include path + * Default include path. * * @var string */ @@ -39,12 +37,12 @@ class PHPMailerLangTest extends \PHPUnit_Framework_TestCase */ public function setUp() { - $this->Mail = new PHPMailer; + $this->Mail = new PHPMailer(); } /** - * Test language files for missing and excess translations - * All languages are compared with English + * Test language files for missing and excess translations. + * All languages are compared with English. * * @group languages */ diff --git a/test/phpmailerTest.php b/test/phpmailerTest.php index d08bb1022..0ea6ae0a7 100644 --- a/test/phpmailerTest.php +++ b/test/phpmailerTest.php @@ -1,13 +1,11 @@ * @author Andy Prevost - * @copyright 2012 - 2016 Marcus Bointon + * @copyright 2012 - 2017 Marcus Bointon * @copyright 2004 - 2009 Andy Prevost * @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License */ @@ -20,7 +18,7 @@ class PHPMailerTest extends \PHPUnit_Framework_TestCase { /** - * Holds the phpmailer instance. + * Holds the PHPMailer instance. * * @var PHPMailer */ @@ -48,14 +46,14 @@ class PHPMailerTest extends \PHPUnit_Framework_TestCase public $NoteLog = []; /** - * Default include path + * Default include path. * * @var string */ public $INCLUDE_DIR = '..'; /** - * PIDs of any processes we need to kill + * PIDs of any processes we need to kill. * * @var array */ @@ -70,7 +68,7 @@ public function setUp() if (file_exists($this->INCLUDE_DIR . '/test/testbootstrap.php')) { include $this->INCLUDE_DIR . '/test/testbootstrap.php'; //Overrides go in here } - $this->Mail = new PHPMailer; + $this->Mail = new PHPMailer(); $this->Mail->SMTPDebug = 3; //Full debug output $this->Mail->Priority = 3; $this->Mail->Encoding = '8bit'; @@ -186,7 +184,7 @@ public function buildBody() $ReportBody .= '-------' . $eol; $ReportBody .= $list_start; - for ($i = 0; $i < count($this->ChangeLog); $i++) { + for ($i = 0; $i < count($this->ChangeLog); ++$i) { $ReportBody .= $bullet_start . $this->ChangeLog[$i][0] . ' was changed to [' . $this->ChangeLog[$i][1] . ']' . $bullet_end; } @@ -199,7 +197,7 @@ public function buildBody() $ReportBody .= '-----' . $eol; $ReportBody .= $list_start; - for ($i = 0; $i < count($this->NoteLog); $i++) { + for ($i = 0; $i < count($this->NoteLog); ++$i) { $ReportBody .= $bullet_start . $this->NoteLog[$i] . $bullet_end; } $ReportBody .= $list_end; @@ -265,7 +263,7 @@ public function addNote($sValue) } /** - * Adds all of the addresses + * Adds all of the addresses. * * @param string $sAddress * @param string $sName @@ -283,6 +281,7 @@ public function setAddress($sAddress, $sName = '', $sType = 'to') case 'bcc': return $this->Mail->addBCC($sAddress, $sName); } + return false; } @@ -292,15 +291,15 @@ public function setAddress($sAddress, $sName = '', $sType = 'to') */ public function testBootstrap() { - $this->assertTrue( - file_exists($this->INCLUDE_DIR . '/test/testbootstrap.php'), + $this->assertFileExists( + $this->INCLUDE_DIR . '/test/testbootstrap.php', 'Test config params missing - copy testbootstrap.php to testbootstrap-dist.php and change as appropriate' ); } /** * Test CRAM-MD5 authentication. - * Needs a connection to a server that supports this auth mechanism, so commented out by default + * Needs a connection to a server that supports this auth mechanism, so commented out by default. */ public function testAuthCRAMMD5() { @@ -399,7 +398,7 @@ public function testValidate() 'cdburgess+!#$%&\'*-/=?+_{}|~test@example.com', 'test@test.com', 'test@xn--example.com', - 'test@example.com' + 'test@example.com', ]; //These are invalid according to PHP's filter_var //which doesn't allow dotless domains, numeric TLDs or unbracketed IPv4 literals @@ -474,7 +473,7 @@ public function testValidate() 'first.last@sub.do,com', 'first\@last@iana.org', '123456789012345678901234567890123456789012345678901234567890' . - '@12345678901234567890123456789012345678901234 [...]', + '@12345678901234567890123456789012345678901234 [...]', 'first.last', '12345678901234567890123456789012345678901234567890123456789012345@iana.org', '.first.last@iana.org', @@ -487,7 +486,7 @@ public function testValidate() 'first\@last@iana.org', 'first.last@', 'x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.' . - 'x23456789.x23456789.x23456789.x23 [...]', + 'x23456789.x23456789.x23456789.x23 [...]', 'first.last@[.12.34.56.78]', 'first.last@[12.34.56.789]', 'first.last@[::12.34.56.78]', @@ -534,7 +533,7 @@ public function testValidate() 'test@example.', 'test@.org', 'test@12345678901234567890123456789012345678901234567890123456789012345678901234567890' . - '12345678901234567890 [...]', + '12345678901234567890 [...]', 'test@[123.123.123.123', 'test@123.123.123.123]', 'NotAnEmail', @@ -559,10 +558,10 @@ public function testValidate() 'cal(foo)bar)@iamcal.com', 'cal(foo\)@iamcal.com', 'first(12345678901234567890123456789012345678901234567890)last@(1234567890123456789' . - '01234567890123456789012 [...]', + '01234567890123456789012 [...]', 'first(middle)last@iana.org', 'first(abc("def".ghi).mno)middle(abc("def".ghi).mno).last@(abc("def".ghi).mno)example' . - '(abc("def".ghi).mno). [...]', + '(abc("def".ghi).mno). [...]', 'a(a(b(c)d(e(f))g)(h(i)j)@iana.org', '.@', '@bar.com', @@ -609,9 +608,9 @@ public function testValidate() 'first.last@[IPv6:a1:a2:a3:a4:b1:b2:b3:]', 'first.last@[IPv6::a2:a3:a4:b1:b2:b3:b4]', 'first.last@[IPv6:a1:a2:a3:a4::b1:b2:b3:b4]', - //This is a valid RCC5322 address, but we don't want to allow it for obvious reasons! + //This is a valid RFC5322 address, but we don't want to allow it for obvious reasons! "(\r\n RCPT TO:user@example.com\r\n DATA \\\nSubject: spam10\\\n\r\n Hello," . - "\r\n this is a spam mail.\\\n.\r\n QUIT\r\n ) a@example.net" + "\r\n this is a spam mail.\\\n.\r\n QUIT\r\n ) a@example.net", ]; // IDNs in Unicode and ASCII forms. $unicodeaddresses = [ @@ -672,7 +671,7 @@ public function testCustomValidator() PHPMailer::validateAddress( 'user@example.com', function ($address) { - return (strpos($address, '@') !== false); + return strpos($address, '@') !== false; } ), 'Custom validator false negative' @@ -681,29 +680,29 @@ function ($address) { PHPMailer::validateAddress( 'userexample.com', function ($address) { - return (strpos($address, '@') !== false); + return strpos($address, '@') !== false; } ), 'Custom validator false positive' ); //Set the default validator to an injected function PHPMailer::$validator = function ($address) { - return ('user@example.com' === $address); + return 'user@example.com' === $address; }; $this->assertTrue( $this->Mail->addAddress('user@example.com'), 'Custom default validator false negative' ); $this->assertFalse( - //Need to pick a failing value which would pass all other validators - //to be sure we're using our custom one + //Need to pick a failing value which would pass all other validators + //to be sure we're using our custom one $this->Mail->addAddress('bananas@example.com'), 'Custom default validator false positive' ); //Set default validator to PHP built-in PHPMailer::$validator = 'php'; $this->assertFalse( - //This is a valid address that FILTER_VALIDATE_EMAIL thinks is invalid + //This is a valid address that FILTER_VALIDATE_EMAIL thinks is invalid $this->Mail->addAddress('first.last@example.123'), 'PHP validator not behaving as expected' ); @@ -778,11 +777,13 @@ public function testMultiplePlainFileAttachment() if (!$this->Mail->addAttachment(realpath($this->INCLUDE_DIR . '/examples/images/phpmailer.png'))) { $this->assertTrue(false, $this->Mail->ErrorInfo); + return; } if (!$this->Mail->addAttachment(__FILE__, 'test.txt')) { $this->assertTrue(false, $this->Mail->ErrorInfo); + return; } @@ -858,7 +859,7 @@ public function testHeaderEncoding() $noencode = 'eeeeeeeeee'; $this->Mail->isMail(); //Expected results - $bencoderes = '=?UTF-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6k=?='.PHPMailer::getLE(). + $bencoderes = '=?UTF-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6k=?=' . PHPMailer::getLE() . ' =?UTF-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6k=?=' . PHPMailer::getLE() . ' =?UTF-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6k=?=' . PHPMailer::getLE() . ' =?UTF-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6nDqcOpw6k=?='; @@ -866,7 +867,7 @@ public function testHeaderEncoding() ' =?UTF-8?Q?eeeeeeeeeeeeeeeeeeeeeeeeee=C3=A9?='; $bencodenofoldres = '=?UTF-8?B?w6nDqcOpw6nDqcOpw6nDqcOpw6k=?='; $qencodenofoldres = '=?UTF-8?Q?eeeeeeeee=C3=A9?='; - $justfoldres = 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee'. + $justfoldres = 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' . 'eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee' . PHPMailer::getLE() . ' eeeeeeeeee'; $noencoderes = 'eeeeeeeeee'; $this->assertEquals( @@ -907,9 +908,9 @@ public function testHeaderEncoding() public function testHtml() { $this->Mail->isHTML(true); - $this->Mail->Subject .= ": HTML only"; + $this->Mail->Subject .= ': HTML only'; - $this->Mail->Body = <<Mail->Body = <<<'EOT' HTML email test @@ -935,7 +936,7 @@ public function testHtml() public function testHtmlIso8859() { $this->Mail->isHTML(true); - $this->Mail->Subject .= ": ISO-8859-1 HTML"; + $this->Mail->Subject .= ': ISO-8859-1 HTML'; $this->Mail->CharSet = 'iso-8859-1'; //This file is in ISO-8859-1 charset @@ -947,8 +948,8 @@ public function testHtmlIso8859() $this->Mail->msgHTML( mb_convert_encoding( $content, - "ISO-8859-1", - mb_detect_encoding($content, "UTF-8, ISO-8859-1, ISO-8859-15", true) + 'ISO-8859-1', + mb_detect_encoding($content, 'UTF-8, ISO-8859-1, ISO-8859-15', true) ), realpath($this->INCLUDE_DIR . '/examples') ); @@ -966,10 +967,10 @@ public function testHtmlIso8859() public function testHtmlUtf8() { $this->Mail->isHTML(true); - $this->Mail->Subject .= ": UTF-8 HTML Пустое тело сообщения"; + $this->Mail->Subject .= ': UTF-8 HTML Пустое тело сообщения'; $this->Mail->CharSet = 'UTF-8'; - $this->Mail->Body = <<Mail->Body = <<<'EOT' @@ -995,10 +996,10 @@ public function testHtmlUtf8() public function testUtf8WithEmbeddedImage() { $this->Mail->isHTML(true); - $this->Mail->Subject .= ": UTF-8 with embedded image"; + $this->Mail->Subject .= ': UTF-8 with embedded image'; $this->Mail->CharSet = 'UTF-8'; - $this->Mail->Body = <<Mail->Body = <<<'EOT' @@ -1030,10 +1031,10 @@ public function testUtf8WithEmbeddedImage() public function testPlainUtf8() { $this->Mail->isHTML(false); - $this->Mail->Subject .= ": UTF-8 plain text"; + $this->Mail->Subject .= ': UTF-8 plain text'; $this->Mail->CharSet = 'UTF-8'; - $this->Mail->Body = <<Mail->Body = <<<'EOT' Chinese text: 郵件內容為空 Russian text: Пустое тело сообщения Armenian text: Հաղորդագրությունը դատարկ է @@ -1046,7 +1047,7 @@ public function testPlainUtf8() } /** - * Test simple message builder and html2text converters + * Test simple message builder and html2text converters. */ public function testMsgHTML() { @@ -1067,7 +1068,7 @@ public function testMsgHTML() $this->Mail->AltBody = ''; $this->Mail->msgHTML( $message, - realpath($this->INCLUDE_DIR .'/examples'), + realpath($this->INCLUDE_DIR . '/examples'), function ($html) { return strtoupper(strip_tags($html)); } @@ -1092,7 +1093,10 @@ function ($html) { //Test that absolute URLs are ignored $this->Mail->msgHTML('test'); $this->assertTrue( - strpos($this->Mail->Body, 'src="https://github.com/PHPMailer/PHPMailer/blob/master/composer.json"') !== false + strpos( + $this->Mail->Body, + 'src="https://github.com/PHPMailer/PHPMailer/blob/master/composer.json"' + ) !== false ); //Test that absolute URLs with anonymous/relative protocol are ignored //Note that such URLs will not work in email anyway because they have no protocol to be relative to @@ -1106,7 +1110,7 @@ function ($html) { } /** - * Simple HTML and attachment test + * Simple HTML and attachment test. */ public function testHTMLAttachment() { @@ -1121,6 +1125,7 @@ public function testHTMLAttachment() ) ) { $this->assertTrue(false, $this->Mail->ErrorInfo); + return; } @@ -1132,7 +1137,7 @@ public function testHTMLAttachment() } /** - * Test embedded image without a name + * Test embedded image without a name. */ public function testHTMLStringEmbedNoName() { @@ -1142,13 +1147,14 @@ public function testHTMLStringEmbedNoName() if (!$this->Mail->addStringEmbeddedImage( file_get_contents(realpath($this->INCLUDE_DIR . '/examples/images/phpmailer_mini.png')), - hash('sha256', 'phpmailer_mini.png').'@phpmailer.0', + hash('sha256', 'phpmailer_mini.png') . '@phpmailer.0', '', //Intentionally empty name 'base64', '', //Intentionally empty MIME type 'inline' )) { $this->assertTrue(false, $this->Mail->ErrorInfo); + return; } @@ -1157,7 +1163,7 @@ public function testHTMLStringEmbedNoName() } /** - * Simple HTML and multiple attachment test + * Simple HTML and multiple attachment test. */ public function testHTMLMultiAttachment() { @@ -1171,6 +1177,7 @@ public function testHTMLMultiAttachment() ) ) { $this->assertTrue(false, $this->Mail->ErrorInfo); + return; } @@ -1180,6 +1187,7 @@ public function testHTMLMultiAttachment() ) ) { $this->assertTrue(false, $this->Mail->ErrorInfo); + return; } @@ -1207,6 +1215,7 @@ public function testEmbeddedImage() ) ) { $this->assertTrue(false, $this->Mail->ErrorInfo); + return; } @@ -1237,11 +1246,13 @@ public function testMultiEmbeddedImage() ) ) { $this->assertTrue(false, $this->Mail->ErrorInfo); + return; } if (!$this->Mail->addAttachment(__FILE__, 'test.txt')) { $this->assertTrue(false, $this->Mail->ErrorInfo); + return; } @@ -1255,11 +1266,11 @@ public function testMultiEmbeddedImage() public function testAltBody() { $this->Mail->Body = 'This is the HTML part of the email.'; - $this->Mail->AltBody = 'Here is the text body of this message. ' . - 'It should be quite a few lines. It should be wrapped at the ' . + $this->Mail->AltBody = 'Here is the plain text body of this message. ' . + 'It should be quite a few lines. It should be wrapped at ' . '40 characters. Make sure that it is.'; $this->Mail->WordWrap = 40; - $this->addNote('This is a mulipart alternative email'); + $this->addNote('This is a multipart/alternative email'); $this->Mail->Subject .= ': AltBody + Word Wrap'; $this->buildBody(); @@ -1267,7 +1278,7 @@ public function testAltBody() } /** - * Simple HTML and attachment test + * Simple HTML and attachment test. */ public function testAltBodyAttachment() { @@ -1278,6 +1289,7 @@ public function testAltBodyAttachment() if (!$this->Mail->addAttachment(__FILE__, 'test_attach.txt')) { $this->assertTrue(false, $this->Mail->ErrorInfo); + return; } @@ -1379,7 +1391,7 @@ public function testLongBody() //Use +2 to ensure line length is over limit - LE may only be 1 char $badlen = str_repeat(str_repeat('1', PHPMailer::MAX_LINE_LENGTH + 2) . PHPMailer::getLE(), 2); - $this->Mail->Body = "This message contains lines that are too long.". + $this->Mail->Body = 'This message contains lines that are too long.' . PHPMailer::getLE() . $oklen . $badlen . $oklen; $this->assertTrue( PHPMailer::hasLineLongerThanMax($this->Mail->Body), @@ -1393,7 +1405,7 @@ public function testLongBody() $message = $this->Mail->getSentMIMEMessage(); $this->assertFalse( PHPMailer::hasLineLongerThanMax($message), - 'Long line not corrected (Max: '.(PHPMailer::MAX_LINE_LENGTH + strlen(PHPMailer::getLE())). ' chars)' + 'Long line not corrected (Max: ' . (PHPMailer::MAX_LINE_LENGTH + strlen(PHPMailer::getLE())) . ' chars)' ); $this->assertContains( 'Content-Transfer-Encoding: quoted-printable', @@ -1409,7 +1421,7 @@ public function testShortBody() { $oklen = str_repeat(str_repeat('0', PHPMailer::MAX_LINE_LENGTH) . PHPMailer::getLE(), 10); - $this->Mail->Body = "This message does not contain lines that are too long.". + $this->Mail->Body = 'This message does not contain lines that are too long.' . PHPMailer::getLE() . $oklen; $this->assertFalse( PHPMailer::hasLineLongerThanMax($this->Mail->Body), @@ -1446,7 +1458,7 @@ public function testSmtpKeepAlive() } /** - * Tests this denial of service attack: + * Test this denial of service attack. * * @see http://www.cybsec.com/vuln/PHPMailer-DOS.pdf */ @@ -1460,7 +1472,7 @@ public function testDenialOfServiceAttack() } /** - * Tests this denial of service attack: + * Tests this denial of service attack. * * @see https://sourceforge.net/p/phpmailer/bugs/383/ * According to the ticket, this should get stuck in a loop, though I can't make it happen. @@ -1534,15 +1546,15 @@ public function testAddressSplitting() 'Failed to recognise address list (IMAP parser)' ); $this->assertEquals( - array( - array("name" => 'Joe User', 'address' => 'joe@example.com'), - array("name" => 'Jill User', 'address' => 'jill@example.net'), - array("name" => '', 'address' => 'frank@example.com'), - ), + [ + ['name' => 'Joe User', 'address' => 'joe@example.com'], + ['name' => 'Jill User', 'address' => 'jill@example.net'], + ['name' => '', 'address' => 'frank@example.com'], + ], $this->Mail->parseAddresses( 'Joe User ,' - . 'Jill User ,' - . 'frank@example.com,' + . 'Jill User ,' + . 'frank@example.com,' ), 'Parsed addresses' ); @@ -1643,8 +1655,8 @@ public function testMIMEStructure() $this->buildBody(); $this->Mail->preSend(); $this->assertRegExp( - "/Content-Transfer-Encoding: 8bit\r\n\r\n". - "This is a multi-part message in MIME format./", + "/Content-Transfer-Encoding: 8bit\r\n\r\n" . + 'This is a multi-part message in MIME format./', $this->Mail->getSentMIMEMessage(), 'MIME structure broken' ); @@ -1712,6 +1724,7 @@ public function testBase64() $this->buildBody(); $this->assertTrue($this->Mail->send(), 'Base64 encoding failed'); } + /** * S/MIME Signing tests (self-signed). * @@ -1730,12 +1743,12 @@ public function testSigning() 'organizationName' => 'PHP', 'organizationalUnitName' => 'PHPMailer', 'commonName' => 'PHPMailer Test', - 'emailAddress' => 'phpmailer@example.com' + 'emailAddress' => 'phpmailer@example.com', ]; $keyconfig = [ - "digest_alg" => "sha256", - "private_key_bits" => 2048, - "private_key_type" => OPENSSL_KEYTYPE_RSA, + 'digest_alg' => 'sha256', + 'private_key_bits' => 2048, + 'private_key_type' => OPENSSL_KEYTYPE_RSA, ]; $password = 'password'; $certfile = 'certfile.pem'; @@ -1771,7 +1784,7 @@ public function testSigning() * S/MIME Signing tests using a CA chain cert. * To test that a generated message is signed correctly, save the message in a file called `signed.eml` * and use openssl along with the certs generated by this script: - * `openssl smime -verify -in signed.eml -signer certfile.pem -CAfile cacertfile.pem` + * `openssl smime -verify -in signed.eml -signer certfile.pem -CAfile cacertfile.pem`. * * @requires extension openssl */ @@ -1788,7 +1801,7 @@ public function testSigningWithCA() 'organizationName' => 'PHP', 'organizationalUnitName' => 'PHPMailer', 'commonName' => 'PHPMailer Test', - 'emailAddress' => 'phpmailer@example.com' + 'emailAddress' => 'phpmailer@example.com', ]; $cacertprops = [ 'countryName' => 'UK', @@ -1797,7 +1810,7 @@ public function testSigningWithCA() 'organizationName' => 'PHP', 'organizationalUnitName' => 'PHPMailer CA', 'commonName' => 'PHPMailer Test CA', - 'emailAddress' => 'phpmailer@example.com' + 'emailAddress' => 'phpmailer@example.com', ]; $keyconfig = [ 'digest_alg' => 'sha256', @@ -1905,7 +1918,7 @@ public function testDKIM() $pk = openssl_pkey_new( [ 'private_key_bits' => 2048, - 'private_key_type' => OPENSSL_KEYTYPE_RSA + 'private_key_type' => OPENSSL_KEYTYPE_RSA, ] ); openssl_pkey_export_to_file($pk, $privatekeyfile); @@ -1952,11 +1965,11 @@ public function testLineBreaks() } /** - * Test line length detection + * Test line length detection. */ public function testLineLength() { - $oklen = str_repeat(str_repeat('0', PHPMailer::MAX_LINE_LENGTH)."\r\n", 2); + $oklen = str_repeat(str_repeat('0', PHPMailer::MAX_LINE_LENGTH) . "\r\n", 2); $badlen = str_repeat(str_repeat('1', PHPMailer::MAX_LINE_LENGTH + 1) . "\r\n", 2); $this->assertTrue(PHPMailer::hasLineLongerThanMax($badlen), 'Long line not detected (only)'); $this->assertTrue(PHPMailer::hasLineLongerThanMax($oklen . $badlen), 'Long line not detected (first)'); @@ -1967,7 +1980,7 @@ public function testLineLength() ); $this->assertFalse(PHPMailer::hasLineLongerThanMax($oklen), 'Long line false positive'); $this->Mail->isHTML(false); - $this->Mail->Subject .= ": Line length test"; + $this->Mail->Subject .= ': Line length test'; $this->Mail->CharSet = 'UTF-8'; $this->Mail->Encoding = '8bit'; $this->Mail->Body = $oklen . $badlen . $oklen . $badlen; @@ -1988,7 +2001,7 @@ public function testMessageID() $this->Mail->preSend(); $lastid = $this->Mail->getLastMessageID(); $this->assertNotEquals($lastid, $id, 'Invalid Message ID allowed'); - $id = '<'. hash('sha256', 12345).'@example.com>'; + $id = '<' . hash('sha256', 12345) . '@example.com>'; $this->Mail->MessageID = $id; $this->buildBody(); $this->Mail->preSend(); @@ -2086,13 +2099,13 @@ public function testHostValidation() '127.0.0.1', trim(str_repeat('a0123456789.', 21), '.'), '[::1]', - '[0:1234:dc0:41:216:3eff:fe67:3e01]' + '[0:1234:dc0:41:216:3eff:fe67:3e01]', ]; $bad = [ null, 123, 1.5, - new \stdClass, + new \stdClass(), [], '', '999.0.0.0', @@ -2100,17 +2113,18 @@ public function testHostValidation() '[1234:::1]', trim(str_repeat('a0123456789.', 22), '.'), '0:1234:dc0:41:216:3eff:fe67:3e01', - '[012q:1234:dc0:41:216:3eff:fe67:3e01]' + '[012q:1234:dc0:41:216:3eff:fe67:3e01]', ]; foreach ($good as $h) { - $this->assertTrue(PHPMailer::isValidHost($h), 'Good hostname denied: '.$h); + $this->assertTrue(PHPMailer::isValidHost($h), 'Good hostname denied: ' . $h); } foreach ($bad as $h) { $this->assertFalse(PHPMailer::isValidHost($h), 'Bad hostname accepted: ' . var_export($h, true)); } } + /** - * Tests the Custom header getter + * Tests the Custom header getter. */ public function testCustomHeaderGetter() { @@ -2121,7 +2135,7 @@ public function testCustomHeaderGetter() $this->assertEquals( [ ['foo', 'bar'], - ['foo', 'baz'] + ['foo', 'baz'], ], $this->Mail->getCustomHeaders() ); @@ -2136,7 +2150,7 @@ public function testCustomHeaderGetter() $this->assertEquals( [ ['yux'], - ['Content-Type', ' application/json'] + ['Content-Type', ' application/json'], ], $this->Mail->getCustomHeaders() ); @@ -2272,8 +2286,7 @@ public function testDuplicateIDNRemoved() } /** - * Use a fake POP3 server to test POP-before-SMTP auth. - * With a known-good login + * Use a fake POP3 server to test POP-before-SMTP auth with a known-good login. * * @group pop3 */ @@ -2328,7 +2341,7 @@ public function testPopBeforeSmtpBad() /** * Test SMTP host connections. - * This test can take a long time, so run it last + * This test can take a long time, so run it last. * * @group slow */ @@ -2337,14 +2350,14 @@ public function testSmtpConnect() $this->Mail->SMTPDebug = 4; //Show connection-level errors $this->assertTrue($this->Mail->smtpConnect(), 'SMTP single connect failed'); $this->Mail->smtpClose(); - $this->Mail->Host = "localhost:12345;10.10.10.10:54321;" . $_REQUEST['mail_host']; + $this->Mail->Host = 'localhost:12345;10.10.10.10:54321;' . $_REQUEST['mail_host']; $this->assertTrue($this->Mail->smtpConnect(), 'SMTP multi-connect failed'); $this->Mail->smtpClose(); - $this->Mail->Host = "[::1]:" . $this->Mail->Port . ';' . $_REQUEST['mail_host']; + $this->Mail->Host = '[::1]:' . $this->Mail->Port . ';' . $_REQUEST['mail_host']; $this->assertTrue($this->Mail->smtpConnect(), 'SMTP IPv6 literal multi-connect failed'); $this->Mail->smtpClose(); //All these hosts are expected to fail - $this->Mail->Host = "xyz://bogus:25;tls://[bogus]:25;ssl://localhost:12345;tls://localhost:587;10.10.10.10:54321;localhost:12345;10.10.10.10"; + $this->Mail->Host = 'xyz://bogus:25;tls://[bogus]:25;ssl://localhost:12345;tls://localhost:587;10.10.10.10:54321;localhost:12345;10.10.10.10'; $this->assertFalse($this->Mail->smtpConnect(), 'SMTP bad multi-connect succeeded'); $this->Mail->smtpClose(); $this->Mail->Host = ' localhost:12345 ; ' . $_REQUEST['mail_host'] . ' '; @@ -2359,7 +2372,7 @@ public function testSmtpConnect() } } -/** +/* * This is a sample form for setting appropriate test values through a browser * These values can also be set using a file called testbootstrap.php (not in repo) in the same folder as this script * which is probably more useful if you run these tests a lot diff --git a/test/testbootstrap-dist.php b/test/testbootstrap-dist.php index 3440655cc..61386584f 100644 --- a/test/testbootstrap-dist.php +++ b/test/testbootstrap-dist.php @@ -1,4 +1,5 @@