Merge 6974f780c1 into 9952101e44
This commit is contained in:
commit
bdcdf72a64
|
|
@ -372,6 +372,17 @@ class PHPMailer
|
|||
*/
|
||||
public $Timeout = 300;
|
||||
|
||||
/**
|
||||
* DSN Sender Extensions
|
||||
* 'RET=FULL' shall return the complete message in case of any error
|
||||
* xor
|
||||
* 'RET=HDRS' shall return only the headers of the failed e-mail.
|
||||
* 'ENVID=xyz' shall include the ID xyz on the way back of this e-mail if any error.
|
||||
*
|
||||
* @see https://tools.ietf.org/html/rfc3461 See section 4.3 and 4.4 regarding RET and ENVID
|
||||
*/
|
||||
public $dsn_ret = '';
|
||||
|
||||
/**
|
||||
* Comma separated list of DSN notifications
|
||||
* 'NEVER' under no circumstances a DSN must be returned to the sender.
|
||||
|
|
@ -2029,7 +2040,7 @@ class PHPMailer
|
|||
} else {
|
||||
$smtp_from = $this->Sender;
|
||||
}
|
||||
if (!$this->smtp->mail($smtp_from)) {
|
||||
if (!$this->smtp->mail($smtp_from, $this->dsn_ret)) {
|
||||
$this->setError($this->lang('from_failed') . $smtp_from . ' : ' . implode(',', $this->smtp->getError()));
|
||||
throw new Exception($this->ErrorInfo, self::STOP_CRITICAL);
|
||||
}
|
||||
|
|
|
|||
96
src/SMTP.php
96
src/SMTP.php
|
|
@ -887,6 +887,87 @@ class SMTP
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforse the content of the DSN to be compliant with the RFC 3461, section 4.
|
||||
*
|
||||
* @param string $s eg. câfé
|
||||
*/
|
||||
protected static function xtext(string $s): string
|
||||
{
|
||||
$r = '';
|
||||
for ($i = 0, $len = strlen($s); $i < $len; ++$i) {
|
||||
$o = ord($s[$i]);
|
||||
if (($o >= 0x21) && ($o < 0x7e) && ($o !== ord('+')) && ($o !== ord('='))) {
|
||||
$r .= $s[$i];
|
||||
continue;
|
||||
}
|
||||
$r .= sprintf('+%02X', $o & 0xff);
|
||||
}
|
||||
|
||||
return $r;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforce the content of the DSN to be compliant with the RFC 3461, section 4.
|
||||
*
|
||||
* @param string $s eg. câfé
|
||||
*
|
||||
* @return false|string
|
||||
*/
|
||||
protected static function dsnize(string $str)
|
||||
{
|
||||
$r = [];
|
||||
$args = explode(' ', $str);
|
||||
switch (count($args)) {
|
||||
case 1: /* likely RET=HDRS|FULL */
|
||||
case 2: /* likely RET=HDRS|FULL ENVID=xtext */
|
||||
/* place holder if more arguments get required */
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
foreach ($args as $i => $arg) {
|
||||
$tokens = explode('=', $arg);
|
||||
|
||||
if ($i === 0) {
|
||||
if (count($tokens) !== 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strcasecmp($tokens[0], 'RET') !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((strcasecmp($tokens[1], 'FULL') !== 0) &&
|
||||
(strcasecmp($tokens[1], 'HDRS') !== 0)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$r[] = sprintf('RET=%s', strtoupper($tokens[1])); /* FULL or HDRS */
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($i == 1) {
|
||||
/* support any cases including ENVID=ab=de */
|
||||
if (count($tokens) <= 1) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strcasecmp($tokens[0], 'ENVID') !== 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
array_shift($tokens); // pop ENVID
|
||||
$id = implode('=', $tokens);
|
||||
$r[] = sprintf('ENVID=%s', self::xtext($id));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return implode(' ', $r);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send an SMTP MAIL command.
|
||||
* Starts a mail transaction from the email address specified in
|
||||
|
|
@ -896,16 +977,27 @@ class SMTP
|
|||
* Implements RFC 821: MAIL <SP> FROM:<reverse-path> <CRLF>.
|
||||
*
|
||||
* @param string $from Source address of this message
|
||||
* @param string $ret DSN argument
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function mail($from)
|
||||
public function mail($from, $ret = '')
|
||||
{
|
||||
$useVerp = ($this->do_verp ? ' XVERP' : '');
|
||||
|
||||
$useRet = '';
|
||||
if ($this->getServerExt('DSN') && !empty($ret)) {
|
||||
$useRet = self::dsnize($ret);
|
||||
if (!is_string($useRet)) {
|
||||
$useRet = ''; // bad one
|
||||
} else {
|
||||
$useRet = ' ' . $useRet;
|
||||
}
|
||||
}
|
||||
|
||||
return $this->sendCommand(
|
||||
'MAIL FROM',
|
||||
'MAIL FROM:<' . $from . '>' . $useVerp,
|
||||
'MAIL FROM:<' . $from . '>' . $useVerp . $useRet,
|
||||
250
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/*
|
||||
*
|
||||
* The syntax for "esmtp-value" in [4] does not allow SP, "=", control
|
||||
* characters, or characters outside the traditional ASCII range of 1- 127
|
||||
* decimal to be transmitted in an esmtp-value. Because the ENVID and ORCPT
|
||||
* parameters may need to convey values outside this range, the esmtp-values for
|
||||
* these parameters are encoded as "xtext". "xtext" is formally defined as
|
||||
* follows:
|
||||
*
|
||||
* xtext = *( xchar / hexchar )
|
||||
*
|
||||
* xchar = any ASCII CHAR between "!" (33) and "~" (126) inclusive, except for
|
||||
* "+" and "=".
|
||||
*
|
||||
* ; "hexchar"s are intended to encode octets that cannot appear
|
||||
* ; as ASCII characters within an esmtp-value.
|
||||
*
|
||||
* hexchar = ASCII "+" immediately followed by two upper case hexadecimal digits
|
||||
*
|
||||
* When encoding an octet sequence as xtext:
|
||||
*
|
||||
* + Any ASCII CHAR between "!" and "~" inclusive, except for "+" and "=",
|
||||
* MAY be encoded as itself. (A CHAR in this range MAY instead be encoded
|
||||
* as a "hexchar", at the implementor's discretion.)
|
||||
*
|
||||
* + ASCII CHARs that fall outside the range above must be encoded as "hexchar".
|
||||
*/
|
||||
|
||||
include '../src/SMTP.php';
|
||||
|
||||
class SMTPTestDsn extends PHPMailer\PHPMailer\SMTP
|
||||
{
|
||||
public function TestDsn()
|
||||
{
|
||||
$strs = [];
|
||||
$strs[] = 'RET=FULL ENVID=xyz';
|
||||
$strs[] = 'RET=FUll ENVID=xyz';
|
||||
$strs[] = 'ENVID=xyz';
|
||||
$strs[] = 'RET=ful ENVID=xyz';
|
||||
$strs[] = 'RET=Hdrs';
|
||||
$strs[] = 'RET=Hdrs ENVID=abcde+ée';
|
||||
$strs[] = 'RET=Hdrs ENVID=abc=de';
|
||||
$strs[] = 'RET=FULL ENVID=+Vincent+=+Jardin+=';
|
||||
|
||||
foreach ($strs as $str) {
|
||||
printf("%s -> %s\n", $str, \PHPMailer\PHPMailer\SMTP::dsnize($str));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SMTPTestDsn::TestDsn();
|
||||
Loading…
Reference in New Issue