0
0
mirror of https://github.com/PHPMailer/PHPMailer.git synced 2024-09-20 01:52:15 +02:00

Feature improve host check (#1909)

* Let isValidHost() determine validness of host

- PHP way of doing so (https://github.com/php/php-src/pull/826)
- Improved and shortened regexp a bit

* Give more specific debug message in case host(entry) is invalid

* Rewrite filter_var checks

* Host [[<ipv6>]] is not valid
This commit is contained in:
Patrick Kuijvenhoven 2019-12-10 11:48:50 +01:00 committed by Marcus Bointon
parent 05853dbd44
commit 7eff728136
3 changed files with 23 additions and 18 deletions

View File

@ -16,6 +16,8 @@ $PHPMAILER_LANG['file_open'] = 'Bestandsfout: kon bestand niet openen
$PHPMAILER_LANG['from_failed'] = 'Het volgende afzendersadres is mislukt: ';
$PHPMAILER_LANG['instantiate'] = 'Kon mailfunctie niet initialiseren.';
$PHPMAILER_LANG['invalid_address'] = 'Ongeldig adres: ';
$PHPMAILER_LANG['invalid_hostentry'] = 'Ongeldige hostentry: ';
$PHPMAILER_LANG['invalid_host'] = 'Ongeldige host: ';
$PHPMAILER_LANG['mailer_not_supported'] = ' mailer wordt niet ondersteund.';
$PHPMAILER_LANG['provide_address'] = 'Er moet minstens één ontvanger worden opgegeven.';
$PHPMAILER_LANG['recipients_failed'] = 'SMTP-fout: de volgende ontvangers zijn mislukt: ';

View File

@ -1346,7 +1346,7 @@ class PHPMailer
);
case 'php':
default:
return (bool) filter_var($address, FILTER_VALIDATE_EMAIL);
return filter_var($address, FILTER_VALIDATE_EMAIL) !== false;
}
}
@ -1948,33 +1948,33 @@ class PHPMailer
foreach ($hosts as $hostentry) {
$hostinfo = [];
if (!preg_match(
'/^((ssl|tls):\/\/)*([a-zA-Z\d.-]*|\[[a-fA-F\d:]+]):?(\d*)$/',
'/^(?:(ssl|tls):\/\/)?(.+?)(?::(\d+))?$/',
trim($hostentry),
$hostinfo
)) {
$this->edebug($this->lang('connect_host') . ' ' . $hostentry);
$this->edebug($this->lang('invalid_hostentry') . ' ' . trim($hostentry));
// Not a valid host entry
continue;
}
// $hostinfo[2]: optional ssl or tls prefix
// $hostinfo[3]: the hostname
// $hostinfo[4]: optional port number
// $hostinfo[1]: optional ssl or tls prefix
// $hostinfo[2]: the hostname
// $hostinfo[3]: optional port number
// The host string prefix can temporarily override the current setting for SMTPSecure
// If it's not specified, the default value is used
//Check the host name is a valid name or IP address before trying to use it
if (!static::isValidHost($hostinfo[3])) {
$this->edebug($this->lang('connect_host') . ' ' . $hostentry);
if (!static::isValidHost($hostinfo[2])) {
$this->edebug($this->lang('invalid_host') . ' ' . $hostinfo[2]);
continue;
}
$prefix = '';
$secure = $this->SMTPSecure;
$tls = (static::ENCRYPTION_STARTTLS === $this->SMTPSecure);
if ('ssl' === $hostinfo[2] || ('' === $hostinfo[2] && static::ENCRYPTION_SMTPS === $this->SMTPSecure)) {
if ('ssl' === $hostinfo[1] || ('' === $hostinfo[1] && static::ENCRYPTION_SMTPS === $this->SMTPSecure)) {
$prefix = 'ssl://';
$tls = false; // Can't have SSL and TLS at the same time
$secure = static::ENCRYPTION_SMTPS;
} elseif ('tls' === $hostinfo[2]) {
} elseif ('tls' === $hostinfo[1]) {
$tls = true;
// tls doesn't use a prefix
$secure = static::ENCRYPTION_STARTTLS;
@ -1987,11 +1987,10 @@ class PHPMailer
throw new Exception($this->lang('extension_missing') . 'openssl', self::STOP_CRITICAL);
}
}
$host = $hostinfo[3];
$host = $hostinfo[2];
$port = $this->Port;
$tport = (int) $hostinfo[4];
if ($tport > 0 && $tport < 65536) {
$port = $tport;
if (array_key_exists(3, $hostinfo) && is_numeric($hostinfo[3]) && $hostinfo[3] > 0 && $hostinfo[3] < 65536) {
$port = (int) $hostinfo[3];
}
if ($this->smtp->connect($prefix . $host, $port, $this->Timeout, $options)) {
try {
@ -2095,6 +2094,8 @@ class PHPMailer
'from_failed' => 'The following From address failed: ',
'instantiate' => 'Could not instantiate mail function.',
'invalid_address' => 'Invalid address: ',
'invalid_hostentry' => 'Invalid hostentry: ',
'invalid_host' => 'Invalid host: ',
'mailer_not_supported' => ' mailer is not supported.',
'provide_address' => 'You must provide at least one recipient email address.',
'recipients_failed' => 'SMTP Error: The following recipients failed: ',
@ -3867,20 +3868,21 @@ class PHPMailer
if (empty($host)
|| !is_string($host)
|| strlen($host) > 256
|| !preg_match('/^([a-zA-Z\d.-]*|\[[a-fA-F\d:]+])$/', $host)
) {
return false;
}
//Looks like a bracketed IPv6 address
if (trim($host, '[]') !== $host) {
return (bool) filter_var(trim($host, '[]'), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6);
if (strlen($host) > 2 && substr($host, 0, 1) === '[' && substr($host, -1, 1) === ']') {
return filter_var(substr($host, 1, -1), FILTER_VALIDATE_IP, FILTER_FLAG_IPV6) !== false;
}
//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 filter_var($host, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4) !== false;
}
if (filter_var('http://' . $host, FILTER_VALIDATE_URL)) {
if (filter_var('http://' . $host, FILTER_VALIDATE_URL) !== false) {
//Is it a syntactically valid hostname?
return true;
}

View File

@ -2414,6 +2414,7 @@ EOT;
trim(str_repeat('a0123456789.', 22), '.'),
'0:1234:dc0:41:216:3eff:fe67:3e01',
'[012q:1234:dc0:41:216:3eff:fe67:3e01]',
'[[::1]]',
];
foreach ($good as $h) {
$this->assertTrue(PHPMailer::isValidHost($h), 'Good hostname denied: ' . $h);