Merge remote-tracking branch 'origin/master'

This commit is contained in:
christian 2023-04-14 12:04:23 +02:00
commit bb5ee3cf07
11 changed files with 497 additions and 16 deletions

View File

@ -30,7 +30,7 @@ jobs:
persist-credentials: false
- name: "Run analysis"
uses: ossf/scorecard-action@e38b1902ae4f44df626f11ba0734b14fb91f8f86
uses: ossf/scorecard-action@80e868c13c90f172d68d1f4501dee99e2479f7af
with:
results_file: results.sarif
results_format: sarif

View File

@ -31,8 +31,8 @@ jobs:
- name: Install Composer dependencies
uses: "ramsey/composer-install@v2"
with:
# Bust the cache at least once a month - output format: YYYY-MM-DD.
custom-cache-suffix: $(date -u -d "-0 month -$(($(date +%d)-1)) days" "+%F")
# Bust the cache at least once a month - output format: YYYY-MM.
custom-cache-suffix: $(date -u "+%Y-%m")
- name: Check coding standards
id: phpcs
@ -71,8 +71,8 @@ jobs:
- name: Install Composer dependencies
uses: "ramsey/composer-install@v2"
with:
# Bust the cache at least once a month - output format: YYYY-MM-DD.
custom-cache-suffix: $(date -u -d "-0 month -$(($(date +%d)-1)) days" "+%F")
# Bust the cache at least once a month - output format: YYYY-MM.
custom-cache-suffix: $(date -u "+%Y-%m")
- name: Lint against parse errors
if: ${{ matrix.php != '8.3' }}
@ -126,16 +126,16 @@ jobs:
if: ${{ matrix.php != '8.3' }}
uses: "ramsey/composer-install@v2"
with:
# Bust the cache at least once a month - output format: YYYY-MM-DD.
custom-cache-suffix: $(date -u -d "-0 month -$(($(date +%d)-1)) days" "+%F")
# Bust the cache at least once a month - output format: YYYY-MM.
custom-cache-suffix: $(date -u "+%Y-%m")
- name: Install PHP packages - ignore-platform-reqs
if: ${{ matrix.php == '8.3' }}
uses: "ramsey/composer-install@v2"
with:
composer-options: --ignore-platform-reqs
# Bust the cache at least once a month - output format: YYYY-MM-DD.
custom-cache-suffix: $(date -u -d "-0 month -$(($(date +%d)-1)) days" "+%F")
# Bust the cache at least once a month - output format: YYYY-MM.
custom-cache-suffix: $(date -u "+%Y-%m")
# Install postfix and automatically retry if the install failed, which happens reguarly.
# @link https://github.com/marketplace/actions/retry-step

View File

@ -47,7 +47,7 @@ This software is distributed under the [LGPL 2.1](http://www.gnu.org/licenses/lg
PHPMailer is available on [Packagist](https://packagist.org/packages/phpmailer/phpmailer) (using semantic versioning), and installation via [Composer](https://getcomposer.org) is the recommended way to install PHPMailer. Just add this line to your `composer.json` file:
```json
"phpmailer/phpmailer": "^6.7.1"
"phpmailer/phpmailer": "^6.8.0"
```
or run

View File

@ -1 +1 @@
6.7.1
6.8.0

View File

@ -1,5 +1,11 @@
# PHPMailer Change Log
## Version 6.8.0 (March 6th, 2023)
* Add DSN parsing class, thanks to @voronkovich
* Fix some name edge cases, expand tests
* Add pattern for ZonMTA message IDs
* Improve Hindi translation
## Version 6.7.1 (December 8th, 2022)
* Add official support for PHP 8.2
* Add PHP 8.3 to test suite with "experimental" status

View File

@ -37,13 +37,13 @@
"ext-hash": "*"
},
"require-dev": {
"dealerdirect/phpcodesniffer-composer-installer": "^0.7.2",
"dealerdirect/phpcodesniffer-composer-installer": "^1.0",
"doctrine/annotations": "^1.2.6 || ^1.13.3",
"php-parallel-lint/php-console-highlighter": "^1.0.0",
"php-parallel-lint/php-parallel-lint": "^1.3.2",
"phpcompatibility/php-compatibility": "^9.3.5",
"roave/security-advisories": "dev-latest",
"squizlabs/php_codesniffer": "^3.7.1",
"squizlabs/php_codesniffer": "^3.7.2",
"yoast/phpunit-polyfills": "^1.0.4"
},
"suggest": {

247
src/DSNConfigurator.php Normal file
View File

@ -0,0 +1,247 @@
<?php
/**
* PHPMailer - PHP email creation and transport class.
* PHP Version 5.5.
*
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
*
* @author Marcus Bointon (Synchro/coolbru) <phpmailer@synchromedia.co.uk>
* @author Jim Jagielski (jimjag) <jimjag@gmail.com>
* @author Andy Prevost (codeworxtech) <codeworxtech@users.sourceforge.net>
* @author Brent R. Matzelle (original founder)
* @copyright 2012 - 2023 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
* @note This program is distributed in the hope that it will be useful - WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE.
*/
namespace PHPMailer\PHPMailer;
/**
* Configure PHPMailer with DSN string.
*
* @see https://en.wikipedia.org/wiki/Data_source_name
*
* @author Oleg Voronkovich <oleg-voronkovich@yandex.ru>
*/
class DSNConfigurator
{
/**
* Create new PHPMailer instance configured by DSN.
*
* @param string $dsn DSN
* @param bool $exceptions Should we throw external exceptions?
*
* @return PHPMailer
*/
public static function mailer($dsn, $exceptions = null)
{
static $configurator = null;
if (null === $configurator) {
$configurator = new DSNConfigurator();
}
return $configurator->configure(new PHPMailer($exceptions), $dsn);
}
/**
* Configure PHPMailer instance with DSN string.
*
* @param PHPMailer $mailer PHPMailer instance
* @param string $dsn DSN
*
* @return PHPMailer
*/
public function configure(PHPMailer $mailer, $dsn)
{
$config = $this->parseDSN($dsn);
$this->applyConfig($mailer, $config);
return $mailer;
}
/**
* Parse DSN string.
*
* @param string $dsn DSN
*
* @throws Exception If DSN is malformed
*
* @return array Configuration
*/
private function parseDSN($dsn)
{
$config = $this->parseUrl($dsn);
if (false === $config || !isset($config['scheme']) || !isset($config['host'])) {
throw new Exception(
sprintf('Malformed DSN: "%s".', $dsn)
);
}
if (isset($config['query'])) {
parse_str($config['query'], $config['query']);
}
return $config;
}
/**
* Apply configuration to mailer.
*
* @param PHPMailer $mailer PHPMailer instance
* @param array $config Configuration
*
* @throws Exception If scheme is invalid
*/
private function applyConfig(PHPMailer $mailer, $config)
{
switch ($config['scheme']) {
case 'mail':
$mailer->isMail();
break;
case 'sendmail':
$mailer->isSendmail();
break;
case 'qmail':
$mailer->isQmail();
break;
case 'smtp':
case 'smtps':
$mailer->isSMTP();
$this->configureSMTP($mailer, $config);
break;
default:
throw new Exception(
sprintf(
'Invalid scheme: "%s". Allowed values: "mail", "sendmail", "qmail", "smtp", "smtps".',
$config['scheme']
)
);
}
if (isset($config['query'])) {
$this->configureOptions($mailer, $config['query']);
}
}
/**
* Configure SMTP.
*
* @param PHPMailer $mailer PHPMailer instance
* @param array $config Configuration
*/
private function configureSMTP($mailer, $config)
{
$isSMTPS = 'smtps' === $config['scheme'];
if ($isSMTPS) {
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
}
$mailer->Host = $config['host'];
if (isset($config['port'])) {
$mailer->Port = $config['port'];
} elseif ($isSMTPS) {
$mailer->Port = SMTP::DEFAULT_SECURE_PORT;
}
$mailer->SMTPAuth = isset($config['user']) || isset($config['pass']);
if (isset($config['user'])) {
$mailer->Username = $config['user'];
}
if (isset($config['pass'])) {
$mailer->Password = $config['pass'];
}
}
/**
* Configure options.
*
* @param PHPMailer $mailer PHPMailer instance
* @param array $options Options
*
* @throws Exception If option is unknown
*/
private function configureOptions(PHPMailer $mailer, $options)
{
$allowedOptions = get_object_vars($mailer);
unset($allowedOptions['Mailer']);
unset($allowedOptions['SMTPAuth']);
unset($allowedOptions['Username']);
unset($allowedOptions['Password']);
unset($allowedOptions['Hostname']);
unset($allowedOptions['Port']);
unset($allowedOptions['ErrorInfo']);
$allowedOptions = \array_keys($allowedOptions);
foreach ($options as $key => $value) {
if (!in_array($key, $allowedOptions)) {
throw new Exception(
sprintf(
'Unknown option: "%s". Allowed values: "%s"',
$key,
implode('", "', $allowedOptions)
)
);
}
switch ($key) {
case 'AllowEmpty':
case 'SMTPAutoTLS':
case 'SMTPKeepAlive':
case 'SingleTo':
case 'UseSendmailOptions':
case 'do_verp':
case 'DKIM_copyHeaderFields':
$mailer->$key = (bool) $value;
break;
case 'Priority':
case 'SMTPDebug':
case 'WordWrap':
$mailer->$key = (int) $value;
break;
default:
$mailer->$key = $value;
break;
}
}
}
/**
* Parse a URL.
* Wrapper for the built-in parse_url function to work around a bug in PHP 5.5.
*
* @param string $url URL
*
* @return array|false
*/
protected function parseUrl($url)
{
if (\PHP_VERSION_ID >= 50600 || false === strpos($url, '?')) {
return parse_url($url);
}
$chunks = explode('?', $url);
if (is_array($chunks)) {
$result = parse_url($chunks[0]);
if (is_array($result)) {
$result['query'] = $chunks[1];
}
return $result;
}
return false;
}
}

View File

@ -767,7 +767,7 @@ class PHPMailer
*
* @var string
*/
const VERSION = '6.7.1';
const VERSION = '6.8.0';
/**
* Error severity: message only, continue processing.

View File

@ -46,7 +46,7 @@ class POP3
*
* @var string
*/
const VERSION = '6.7.1';
const VERSION = '6.8.0';
/**
* Default POP3 port number.

View File

@ -35,7 +35,7 @@ class SMTP
*
* @var string
*/
const VERSION = '6.7.1';
const VERSION = '6.8.0';
/**
* SMTP line break constant.
@ -51,6 +51,13 @@ class SMTP
*/
const DEFAULT_PORT = 25;
/**
* The SMTPs port to use if one is not specified.
*
* @var int
*/
const DEFAULT_SECURE_PORT = 465;
/**
* The maximum line length allowed by RFC 5321 section 4.5.3.1.6,
* *excluding* a trailing CRLF break.

View File

@ -0,0 +1,221 @@
<?php
/**
* PHPMailer - PHP email transport unit tests.
* PHP version 5.5.
*
* @author Marcus Bointon <phpmailer@synchromedia.co.uk>
* @author Andy Prevost
* @copyright 2012 - 2020 Marcus Bointon
* @copyright 2004 - 2009 Andy Prevost
* @license http://www.gnu.org/copyleft/lesser.html GNU Lesser General Public License
*/
namespace PHPMailer\Test\PHPMailer;
use PHPMailer\PHPMailer\DSNConfigurator;
use PHPMailer\PHPMailer\Exception;
use PHPMailer\PHPMailer\PHPMailer;
use PHPMailer\PHPMailer\SMTP;
use PHPMailer\Test\TestCase;
/**
* Test configuring with DSN.
*
* @covers \PHPMailer\PHPMailer\DSNConfigurator
*/
final class DSNConfiguratorTest extends TestCase
{
/**
* Test throwing exception if DSN is invalid.
*/
public function testInvalidDSN()
{
$configurator = new DSNConfigurator();
$this->expectException(Exception::class);
$this->expectExceptionMessage('Malformed DSN: "localhost".');
$configurator->configure($this->Mail, 'localhost');
}
/**
* Test throwing exception if DSN scheme is invalid.
*/
public function testInvalidScheme()
{
$configurator = new DSNConfigurator();
$this->expectException(Exception::class);
$this->expectExceptionMessage('Invalid scheme: "ftp".');
$configurator->configure($this->Mail, 'ftp://localhost');
}
/**
* Test cofiguring mail.
*/
public function testConfigureMail()
{
$configurator = new DSNConfigurator();
$configurator->configure($this->Mail, 'mail://localhost');
self::assertEquals($this->Mail->Mailer, 'mail');
}
/**
* Test cofiguring sendmail.
*/
public function testConfigureSendmail()
{
$configurator = new DSNConfigurator();
$configurator->configure($this->Mail, 'sendmail://localhost');
self::assertEquals($this->Mail->Mailer, 'sendmail');
}
/**
* Test cofiguring qmail.
*/
public function testConfigureQmail()
{
$configurator = new DSNConfigurator();
$configurator->configure($this->Mail, 'qmail://localhost');
self::assertEquals($this->Mail->Mailer, 'qmail');
}
/**
* Test cofiguring SMTP without authentication.
*/
public function testConfigureSmtpWithoutAuthentication()
{
$configurator = new DSNConfigurator();
$configurator->configure($this->Mail, 'smtp://localhost');
self::assertEquals($this->Mail->Mailer, 'smtp');
self::assertEquals($this->Mail->Host, 'localhost');
self::assertFalse($this->Mail->SMTPAuth);
}
/**
* Test cofiguring SMTP with authentication.
*/
public function testConfigureSmtpWithAuthentication()
{
$configurator = new DSNConfigurator();
$configurator->configure($this->Mail, 'smtp://user:pass@remotehost');
self::assertEquals($this->Mail->Mailer, 'smtp');
self::assertEquals($this->Mail->Host, 'remotehost');
self::assertTrue($this->Mail->SMTPAuth);
self::assertEquals($this->Mail->Username, 'user');
self::assertEquals($this->Mail->Password, 'pass');
}
/**
* Test cofiguring SMTP without port.
*/
public function testConfigureSmtpWithoutPort()
{
$configurator = new DSNConfigurator();
$configurator->configure($this->Mail, 'smtp://localhost');
self::assertEquals($this->Mail->Mailer, 'smtp');
self::assertEquals($this->Mail->Host, 'localhost');
self::assertEquals($this->Mail->Port, SMTP::DEFAULT_PORT);
}
/**
* Test cofiguring SMTP with port.
*/
public function testConfigureSmtpWitPort()
{
$configurator = new DSNConfigurator();
$configurator->configure($this->Mail, 'smtp://localhost:2525');
self::assertEquals($this->Mail->Mailer, 'smtp');
self::assertEquals($this->Mail->Host, 'localhost');
self::assertEquals($this->Mail->Port, 2525);
}
/**
* Test cofiguring SMTPs without port.
*/
public function testConfigureSmtpsWithoutPort()
{
$configurator = new DSNConfigurator();
$configurator->configure($this->Mail, 'smtps://user:pass@remotehost');
self::assertEquals($this->Mail->Mailer, 'smtp');
self::assertEquals($this->Mail->SMTPSecure, PHPMailer::ENCRYPTION_STARTTLS);
self::assertEquals($this->Mail->Host, 'remotehost');
self::assertEquals($this->Mail->Port, SMTP::DEFAULT_SECURE_PORT);
self::assertTrue($this->Mail->SMTPAuth);
self::assertEquals($this->Mail->Username, 'user');
self::assertEquals($this->Mail->Password, 'pass');
}
/**
* Test cofiguring SMTPs with port.
*/
public function testConfigureWithUnknownOption()
{
$configurator = new DSNConfigurator();
$this->expectException(Exception::class);
$this->expectExceptionMessage('Unknown option: "UnknownOption".');
$configurator->configure($this->Mail, 'mail://locahost?UnknownOption=Value');
}
/**
* Test cofiguring options with query sting.
*/
public function testConfigureWithOptions()
{
$configurator = new DSNConfigurator();
$configurator->configure(
$this->Mail,
'sendmail://localhost?Sendmail=/usr/local/bin/sendmail&AllowEmpty=1&WordWrap=78'
);
self::assertEquals($this->Mail->Mailer, 'sendmail');
self::assertEquals($this->Mail->Sendmail, '/usr/local/bin/sendmail');
self::assertEquals($this->Mail->AllowEmpty, true);
self::assertEquals($this->Mail->WordWrap, 78);
}
/**
* Test shortcut.
*/
public function testShortcut()
{
$mailer = DSNConfigurator::mailer('smtps://user@gmail.com:secret@smtp.gmail.com?SMTPDebug=3&Timeout=1000');
self::assertEquals($mailer->Mailer, 'smtp');
self::assertEquals($mailer->SMTPSecure, PHPMailer::ENCRYPTION_STARTTLS);
self::assertEquals($mailer->Host, 'smtp.gmail.com');
self::assertEquals($mailer->Port, SMTP::DEFAULT_SECURE_PORT);
self::assertTrue($mailer->SMTPAuth);
self::assertEquals($mailer->Username, 'user@gmail.com');
self::assertEquals($mailer->Password, 'secret');
self::assertEquals($mailer->SMTPDebug, 3);
self::assertEquals($mailer->Timeout, 1000);
}
}