This commit is contained in:
Jim Jagielski 2017-09-15 07:41:51 -04:00
commit dd548ca002
15 changed files with 227 additions and 3794 deletions

2
.gitignore vendored
View File

@ -5,3 +5,5 @@ test/testbootstrap.php
build/
vendor/
*.pem
composer.lock
.php_cs.cache

31
.php_cs Normal file
View File

@ -0,0 +1,31 @@
<?php
return PhpCsFixer\Config::create()
->setRiskyAllowed(true)
->setRules([
'@Symfony' => true,
'@Symfony:risky' => true,
'array_syntax' => ['syntax' => 'short'],
'binary_operator_spaces' => false,
'concat_space' => ['spacing' => 'one'],
'heredoc_to_nowdoc' => true,
'method_argument_space' => true,
'no_extra_consecutive_blank_lines' => ['break', 'continue', 'extra', 'return', 'throw', 'use', 'parenthesis_brace_block', 'square_brace_block', 'curly_brace_block'],
'no_php4_constructor' => true,
'no_short_echo_tag' => true,
'no_unreachable_default_argument_value' => true,
'no_useless_else' => true,
'no_useless_return' => true,
'ordered_imports' => true,
'php_unit_fqcn_annotation' => false,
'phpdoc_add_missing_param_annotation' => true,
'phpdoc_order' => true,
'phpdoc_summary' => false,
'semicolon_after_instruction' => true,
'simplified_null_return' => true,
])
->setFinder(
PhpCsFixer\Finder::create()
->in(__DIR__ . '/src')
->in(__DIR__ . '/test')
)
;

View File

@ -1,18 +1,19 @@
language: php
php:
- 7.1
- 7.0
- 5.6
- 5.5
matrix:
include:
- php: hhvm
dist: trusty
cache:
directories:
- $HOME/.composer/cache
before_install:
- sudo apt-get update -qq
- sudo apt-get install -y -qq postfix
install:
- REMOVE_PACKAGE="friendsofphp/php-cs-fixer"; if [ "$CS_CHECK" = 1 ]; then REMOVE_PACKAGE="phpunit/phpunit"; fi; composer remove --no-update --no-scripts --dev $REMOVE_PACKAGE
- composer remove --no-update --no-scripts --dev phpdocumentor/phpdocumentor
- composer install
- if [ "$CODE_COVERAGE" != 1 ]; then phpenv config-rm xdebug.ini || true; fi
before_script:
- sudo service postfix stop
- smtp-sink -d "%d.%H.%M.%S" localhost:2500 1000 &
@ -28,8 +29,32 @@ before_script:
else
echo 'sendmail_path = "/usr/sbin/sendmail -t -i "' > $(php --ini|grep -m 1 "ini files in:"|cut -d ":" -f 2)/sendmail.ini
fi
script:
- ./vendor/bin/phpunit --configuration ./travis.phpunit.xml.dist --bootstrap ./vendor/autoload.php
script: ./vendor/bin/phpunit --configuration ./travis.phpunit.xml.dist
after_script:
- wget https://scrutinizer-ci.com/ocular.phar
- php ocular.phar code-coverage:upload --format=php-clover ../build/logs/clover.xml
- if [ "$CODE_COVERAGE" = 1 ]; then wget https://scrutinizer-ci.com/ocular.phar; fi
- if [ "$CODE_COVERAGE" = 1 ]; then php ocular.phar code-coverage:upload --format=php-clover ../build/logs/clover.xml; fi
stages:
- coding-standard
- test
jobs:
include:
- stage: coding-standard
before_install:
before_script:
script: ./vendor/bin/php-cs-fixer --diff --dry-run --verbose fix
after_script:
php: 5.5
env: CS_CHECK=1
- stage: test
php: 5.5
- php: 5.6
- php: 7.0
- php: 7.1
env: CODE_COVERAGE=1
- php: 7.2
- php: hhvm
dist: trusty

View File

@ -127,7 +127,7 @@ PHPMailer defaults to English, but in the [language](https://github.com/PHPMaile
$mail->setLanguage('fr', '/optional/path/to/language/directory/');
```
We welcome corrections and new languages - if you're looking for corrections to do, run the [phpmailerLangTest.php](https://github.com/PHPMailer/PHPMailer/tree/master/test/phpmailerLangTest.php) script in the tests folder and it will show any missing translations.
We welcome corrections and new languages - if you're looking for corrections to do, run the [PHPMailerLangTest.php](https://github.com/PHPMailer/PHPMailer/tree/master/test/PHPMailerLangTest.php) script in the tests folder and it will show any missing translations.
## Documentation
Start reading at the [GitHub wiki](https://github.com/PHPMailer/PHPMailer/wiki). If you're having trouble, this should be the first place you look as it's the most frequently updated.

View File

@ -1 +1 @@
6.0.0
6.0.1

View File

@ -1,6 +1,17 @@
# PHPMailer Change Log
## Version 6.0
## Version 6.0.1 (September 14th 2017)
* Use shorter Message-ID headers (with more entropy) to avoid iCloud blackhole bug
* Switch to Symfony code style (though it's not well defined)
* CI builds now apply syntax & code style checks, so make your PRs tidy!
* CI code coverage only applied on latest version of PHP to speed up builds (thanks to @Slamdunk for these CI changes)
* Remove `composer.lock` - it's important that libraries break early; keeping it is for apps
* Rename test scripts to PSR-4 spec
* Make content-id values settable on attachments, not just embedded items
* Add SMTP transaction IDs to callbacks & allow for future expansion
* Expand test coverage
## Version 6.0 (August 28th 2017)
This is a major update that breaks backwards compatibility.
* **Requires PHP 5.5 or later**

View File

@ -24,8 +24,9 @@
"ext-ctype": "*"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.2",
"phpdocumentor/phpdocumentor": "2.*",
"phpunit/phpunit": "4.*",
"phpunit/phpunit": "^4.8 || ^5.7",
"zendframework/zend-serializer": "2.7.*",
"doctrine/annotations": "1.2.*",
"zendframework/zend-eventmanager": "3.0.*",
@ -44,5 +45,10 @@
"PHPMailer\\PHPMailer\\": "src/"
}
},
"autoload-dev": {
"psr-4": {
"PHPMailer\\Test\\": "test/"
}
},
"license": "LGPL-2.1"
}

3727
composer.lock generated

File diff suppressed because it is too large Load Diff

View File

@ -473,6 +473,8 @@ class PHPMailer
* string $subject the subject
* string $body the email body
* string $from email address of sender
* string $extra extra information of possible use
* "smtp_transaction_id' => last smtp transaction id
*
* @var string
*/
@ -667,7 +669,7 @@ class PHPMailer
*
* @var string
*/
const VERSION = '6.0.0';
const VERSION = '6.0.1';
/**
* Error severity: message only, continue processing.
@ -1106,7 +1108,7 @@ class PHPMailer
*
* @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
*
@ -1530,7 +1532,8 @@ class PHPMailer
$this->bcc,
$this->Subject,
$body,
$this->From
$this->From,
[]
);
if (0 !== $result) {
throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
@ -1551,7 +1554,8 @@ class PHPMailer
$this->bcc,
$this->Subject,
$body,
$this->From
$this->From,
[]
);
if (0 !== $result) {
throw new Exception($this->lang('execute') . $this->Sendmail, self::STOP_CRITICAL);
@ -1638,11 +1642,11 @@ class PHPMailer
if ($this->SingleTo and count($toArr) > 1) {
foreach ($toArr as $toAddr) {
$result = $this->mailPassthru($toAddr, $this->Subject, $body, $header, $params);
$this->doCallback($result, [$toAddr], $this->cc, $this->bcc, $this->Subject, $body, $this->From);
$this->doCallback($result, [$toAddr], $this->cc, $this->bcc, $this->Subject, $body, $this->From, []);
}
} else {
$result = $this->mailPassthru($to, $this->Subject, $body, $header, $params);
$this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From);
$this->doCallback($result, $this->to, $this->cc, $this->bcc, $this->Subject, $body, $this->From, []);
}
if (isset($old_from)) {
ini_set('sendmail_from', $old_from);
@ -1689,6 +1693,7 @@ class PHPMailer
* Returns false if there is a bad MAIL FROM, RCPT, or DATA input.
*
* @see PHPMailer::setSMTPInstance() to use a different class.
*
* @uses \PHPMailer\PHPMailer\SMTP
*
* @param string $header The message headers
@ -1715,6 +1720,7 @@ class PHPMailer
throw new Exception($this->ErrorInfo, self::STOP_CRITICAL);
}
$callbacks = [];
// Attempt to send to all recipients
foreach ([$this->to, $this->cc, $this->bcc] as $togroup) {
foreach ($togroup as $to) {
@ -1725,7 +1731,8 @@ class PHPMailer
} else {
$isSent = true;
}
$this->doCallback($isSent, [$to[0]], [], [], $this->Subject, $body, $this->From);
$callbacks[] = ['issent'=>$isSent, 'to'=>$to[0]];
}
}
@ -1733,12 +1740,29 @@ class PHPMailer
if ((count($this->all_recipients) > count($bad_rcpt)) and !$this->smtp->data($header . $body)) {
throw new Exception($this->lang('data_not_accepted'), self::STOP_CRITICAL);
}
$smtp_transaction_id = $this->smtp->getLastTransactionID();
if ($this->SMTPKeepAlive) {
$this->smtp->reset();
} else {
$this->smtp->quit();
$this->smtp->close();
}
foreach ($callbacks as $cb) {
$this->doCallback(
$cb['issent'],
[$cb['to']],
[],
[],
$this->Subject,
$body,
$this->From,
['smtp_transaction_id' => $smtp_transaction_id]
);
}
//Create error message for any bad addresses
if (count($bad_rcpt) > 0) {
$errstr = '';
@ -1762,7 +1786,7 @@ class PHPMailer
*
* @throws Exception
*
* @uses SMTP
* @uses \PHPMailer\PHPMailer\SMTP
*
* @return bool
*/
@ -2371,16 +2395,18 @@ class PHPMailer
*/
protected function generateId()
{
$len = 23;
$len = 32; //32 bytes = 256 bits
if (function_exists('random_bytes')) {
$bytes = random_bytes($len);
} elseif (function_exists('openssl_random_pseudo_bytes')) {
$bytes = openssl_random_pseudo_bytes($len);
} else {
$bytes = uniqid((string) mt_rand(), true);
//Use a hash to force the length to the same as the other methods
$bytes = hash('sha256', uniqid((string) mt_rand(), true), true);
}
return hash('sha256', $bytes);
//We don't care about messing up base64 format here, just want a random string
return str_replace(['=', '+', '/'], '', base64_encode(hash('sha256', $bytes, true)));
}
/**
@ -2737,7 +2763,7 @@ class PHPMailer
4 => $type,
5 => false, // isStringAttachment
6 => $disposition,
7 => 0,
7 => $name,
];
} catch (Exception $exc) {
$this->setError($exc->getMessage());
@ -2828,7 +2854,7 @@ class PHPMailer
$mime[] = sprintf('Content-Transfer-Encoding: %s%s', $encoding, static::$LE);
}
if ('inline' == $disposition) {
if (!empty($cid)) {
$mime[] = sprintf('Content-ID: <%s>%s', $cid, static::$LE);
}
@ -4330,11 +4356,12 @@ class PHPMailer
* @param string $subject
* @param string $body
* @param string $from
* @param array $extra
*/
protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from)
protected function doCallback($isSent, $to, $cc, $bcc, $subject, $body, $from, $extra)
{
if (!empty($this->action_function) and is_callable($this->action_function)) {
call_user_func_array($this->action_function, [$isSent, $to, $cc, $bcc, $subject, $body, $from]);
call_user_func_array($this->action_function, [$isSent, $to, $cc, $bcc, $subject, $body, $from, $extra]);
}
}

View File

@ -45,7 +45,7 @@ class POP3
*
* @var string
*/
const VERSION = '6.0.0';
const VERSION = '6.0.1';
/**
* Default POP3 port number.
@ -133,9 +133,9 @@ class POP3
/**
* Simple static wrapper for all-in-one POP before SMTP.
*
* @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 $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
@ -160,9 +160,9 @@ class POP3
* 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 int|bool $timeout The timeout value
* @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

View File

@ -34,7 +34,7 @@ class SMTP
*
* @var string
*/
const VERSION = '6.0.0';
const VERSION = '6.0.1';
/**
* SMTP line break constant.
@ -159,6 +159,7 @@ class SMTP
'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/',
'Amazon_SES' => '/[0-9]{3} Ok (.*)/',
];
/**
@ -1291,6 +1292,7 @@ class SMTP
foreach ($this->smtp_transaction_id_patterns as $smtp_transaction_id_pattern) {
if (preg_match($smtp_transaction_id_pattern, $reply, $matches)) {
$this->last_smtp_transaction_id = $matches[1];
break;
}
}
}

View File

@ -0,0 +1,39 @@
<?php
/**
* PHPMailer - language file tests.
*
* PHP version 5.5.
*
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
* @author Andy Prevost
* @copyright 2010 - 2017 Marcus Bointon
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace PHPMailer\Test;
class DebugLogTestListener extends \PHPUnit_Framework_BaseTestListener
{
private static $debugLog = '';
public function addError(\PHPUnit_Framework_Test $test, \Exception $e, $time)
{
echo self::$debugLog;
}
public function addFailure(\PHPUnit_Framework_Test $test, \PHPUnit_Framework_AssertionFailedError $e, $time)
{
echo self::$debugLog;
}
public function startTest(\PHPUnit_Framework_Test $test)
{
self::$debugLog = '';
}
public static function debugLog($str)
{
self::$debugLog .= $str . PHP_EOL;
}
}

View File

@ -11,31 +11,27 @@
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace PHPMailer\PHPMailer;
namespace PHPMailer\Test;
use PHPMailer\PHPMailer\PHPMailer;
use PHPUnit\Framework\TestCase;
/**
* Check language files for missing or excess translations.
*/
class PHPMailerLangTest extends \PHPUnit_Framework_TestCase
final class PHPMailerLangTest extends TestCase
{
/**
* Holds a PHPMailer instance.
*
* @var PHPMailer
*/
public $Mail;
/**
* Default include path.
*
* @var string
*/
public $INCLUDE_DIR = '../';
private $Mail;
/**
* Run before each test is started.
*/
public function setUp()
protected function setUp()
{
$this->Mail = new PHPMailer();
}

View File

@ -10,47 +10,50 @@
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace PHPMailer\PHPMailer;
namespace PHPMailer\Test;
use PHPMailer\PHPMailer\PHPMailer;
use PHPUnit\Framework\TestCase;
/**
* PHPMailer - PHP email transport unit test class.
*/
class PHPMailerTest extends \PHPUnit_Framework_TestCase
final class PHPMailerTest extends TestCase
{
/**
* Holds the PHPMailer instance.
*
* @var PHPMailer
*/
public $Mail;
private $Mail;
/**
* Holds the SMTP mail host.
*
* @var string
*/
public $Host = '';
private $Host = '';
/**
* Holds the change log.
*
* @var string[]
*/
public $ChangeLog = [];
private $ChangeLog = [];
/**
* Holds the note log.
*
* @var string[]
*/
public $NoteLog = [];
private $NoteLog = [];
/**
* Default include path.
*
* @var string
*/
public $INCLUDE_DIR = '..';
private $INCLUDE_DIR = '..';
/**
* PIDs of any processes we need to kill.
@ -62,7 +65,7 @@ class PHPMailerTest extends \PHPUnit_Framework_TestCase
/**
* Run before each test is started.
*/
public function setUp()
protected function setUp()
{
$this->INCLUDE_DIR = dirname(__DIR__); //Default to the dir above the test dir, i.e. the project home dir
if (file_exists($this->INCLUDE_DIR . '/test/testbootstrap.php')) {
@ -70,6 +73,7 @@ class PHPMailerTest extends \PHPUnit_Framework_TestCase
}
$this->Mail = new PHPMailer();
$this->Mail->SMTPDebug = 3; //Full debug output
$this->Mail->Debugoutput = ['PHPMailer\Test\DebugLogTestListener', 'debugLog'];
$this->Mail->Priority = 3;
$this->Mail->Encoding = '8bit';
$this->Mail->CharSet = 'iso-8859-1';
@ -116,7 +120,7 @@ class PHPMailerTest extends \PHPUnit_Framework_TestCase
/**
* Run after each test is completed.
*/
public function tearDown()
protected function tearDown()
{
// Clean global variables
$this->Mail = null;
@ -132,7 +136,7 @@ class PHPMailerTest extends \PHPUnit_Framework_TestCase
/**
* Build the body of the message in the appropriate format.
*/
public function buildBody()
private function buildBody()
{
$this->checkChanges();
@ -209,7 +213,7 @@ class PHPMailerTest extends \PHPUnit_Framework_TestCase
/**
* Check which default settings have been changed for the report.
*/
public function checkChanges()
private function checkChanges()
{
if (3 != $this->Mail->Priority) {
$this->addChange('Priority', $this->Mail->Priority);
@ -246,7 +250,7 @@ class PHPMailerTest extends \PHPUnit_Framework_TestCase
* @param string $sName
* @param string $sNewValue
*/
public function addChange($sName, $sNewValue)
private function addChange($sName, $sNewValue)
{
$this->ChangeLog[] = [$sName, $sNewValue];
}
@ -256,7 +260,7 @@ class PHPMailerTest extends \PHPUnit_Framework_TestCase
*
* @param string $sValue
*/
public function addNote($sValue)
private function addNote($sValue)
{
$this->NoteLog[] = $sValue;
}
@ -270,7 +274,7 @@ class PHPMailerTest extends \PHPUnit_Framework_TestCase
*
* @return bool
*/
public function setAddress($sAddress, $sName = '', $sType = 'to')
private function setAddress($sAddress, $sName = '', $sType = 'to')
{
switch ($sType) {
case 'to':
@ -1926,6 +1930,8 @@ EOT;
$this->Mail->DKIM_selector = 'phpmailer';
$this->Mail->DKIM_passphrase = ''; //key is not encrypted
$this->assertTrue($this->Mail->send(), 'DKIM signed mail failed');
$this->Mail->isMail();
$this->assertTrue($this->Mail->send(), 'DKIM signed mail via mail() failed');
unlink($privatekeyfile);
}
@ -1934,6 +1940,9 @@ EOT;
*/
public function testLineBreaks()
{
//May have been altered by earlier tests, can interfere with line break format
$this->Mail->isSMTP();
$this->Mail->preSend();
$unixsrc = "hello\nWorld\nAgain\n";
$macsrc = "hello\rWorld\rAgain\r";
$windowssrc = "hello\r\nWorld\r\nAgain\r\n";
@ -1968,6 +1977,9 @@ EOT;
*/
public function testLineLength()
{
//May have been altered by earlier tests, can interfere with line break format
$this->Mail->isSMTP();
$this->Mail->preSend();
$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)');

View File

@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit
verbose="false"
bootstrap="vendor/autoload.php"
verbose="true"
stopOnError="false"
stopOnFailure="false"
stopOnIncomplete="false"
@ -8,7 +9,7 @@
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
colors="false"
colors="true"
forceCoversAnnotation="false"
processIsolation="false">
<testsuites>
@ -16,12 +17,20 @@
<directory>./test/</directory>
</testsuite>
</testsuites>
<listeners>
<listener class="PHPMailer\Test\DebugLogTestListener" />
</listeners>
<groups>
<exclude>
<group>languages</group>
<group>pop3</group>
</exclude>
</groups>
<filter>
<whitelist>
<directory suffix=".php">./src</directory>
</whitelist>
</filter>
<logging>
<log type="coverage-text" target="php://stdout" showUncoveredFiles="true"/>
<log type="coverage-clover" target="build/logs/clover.xml"/>