Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
Q
question2answer
Overview
Overview
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
outils
question2answer
Commits
e3732603
Commit
e3732603
authored
Apr 04, 2017
by
Scott
Committed by
GitHub
Apr 04, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #513 from ProThoughts/1.8
Updated PHPMailer to v5.2.23 (from v5.2.14)
parents
c93f249a
81a6e450
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
318 additions
and
92 deletions
+318
-92
class.phpmailer.php
qa-include/vendor/PHPMailer/class.phpmailer.php
+223
-67
class.smtp.php
qa-include/vendor/PHPMailer/class.smtp.php
+95
-25
No files found.
qa-include/vendor/PHPMailer/class.phpmailer.php
View file @
e3732603
...
@@ -31,7 +31,7 @@ class PHPMailer
...
@@ -31,7 +31,7 @@ class PHPMailer
* The PHPMailer Version number.
* The PHPMailer Version number.
* @var string
* @var string
*/
*/
public
$Version
=
'5.2.
14
'
;
public
$Version
=
'5.2.
23
'
;
/**
/**
* Email priority.
* Email priority.
...
@@ -201,6 +201,9 @@ class PHPMailer
...
@@ -201,6 +201,9 @@ class PHPMailer
/**
/**
* An ID to be used in the Message-ID header.
* An ID to be used in the Message-ID header.
* If empty, a unique id will be generated.
* If empty, a unique id will be generated.
* You can set your own, but it must be in the format "<id@domain>",
* 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
* @var string
*/
*/
public
$MessageID
=
''
;
public
$MessageID
=
''
;
...
@@ -285,7 +288,7 @@ class PHPMailer
...
@@ -285,7 +288,7 @@ class PHPMailer
/**
/**
* SMTP auth type.
* SMTP auth type.
* Options are
LOGIN (default), PLAIN, NTLM, CRAM-MD5
* Options are
CRAM-MD5, LOGIN, PLAIN, NTLM, XOAUTH2, attempted in that order if not specified
* @var string
* @var string
*/
*/
public
$AuthType
=
''
;
public
$AuthType
=
''
;
...
@@ -352,6 +355,7 @@ class PHPMailer
...
@@ -352,6 +355,7 @@ class PHPMailer
/**
/**
* Whether to split multiple to addresses into multiple messages
* Whether to split multiple to addresses into multiple messages
* or send them all in one message.
* or send them all in one message.
* Only supported in `mail` and `sendmail` transports, not in SMTP.
* @var boolean
* @var boolean
*/
*/
public
$SingleTo
=
false
;
public
$SingleTo
=
false
;
...
@@ -394,7 +398,7 @@ class PHPMailer
...
@@ -394,7 +398,7 @@ class PHPMailer
/**
/**
* DKIM Identity.
* DKIM Identity.
* Usually the email address used as the source of the email
* Usually the email address used as the source of the email
.
* @var string
* @var string
*/
*/
public
$DKIM_identity
=
''
;
public
$DKIM_identity
=
''
;
...
@@ -420,6 +424,13 @@ class PHPMailer
...
@@ -420,6 +424,13 @@ class PHPMailer
public
$DKIM_private
=
''
;
public
$DKIM_private
=
''
;
/**
/**
* DKIM private key string.
* If set, takes precedence over `$DKIM_private`.
* @var string
*/
public
$DKIM_private_string
=
''
;
/**
* Callback Action function name.
* Callback Action function name.
*
*
* The function that handles the result of the send email action.
* The function that handles the result of the send email action.
...
@@ -447,6 +458,15 @@ class PHPMailer
...
@@ -447,6 +458,15 @@ class PHPMailer
public
$XMailer
=
''
;
public
$XMailer
=
''
;
/**
/**
* Which validator to use by default when validating email addresses.
* May be a callable to inject your own validator, but there are several built-in validators.
* @see PHPMailer::validateAddress()
* @var string|callable
* @static
*/
public
static
$validator
=
'auto'
;
/**
* An instance of the SMTP sender class.
* An instance of the SMTP sender class.
* @var SMTP
* @var SMTP
* @access protected
* @access protected
...
@@ -634,10 +654,12 @@ class PHPMailer
...
@@ -634,10 +654,12 @@ class PHPMailer
* Constructor.
* Constructor.
* @param boolean $exceptions Should we throw external exceptions?
* @param boolean $exceptions Should we throw external exceptions?
*/
*/
public
function
__construct
(
$exceptions
=
false
)
public
function
__construct
(
$exceptions
=
null
)
{
{
if
(
$exceptions
!==
null
)
{
$this
->
exceptions
=
(
boolean
)
$exceptions
;
$this
->
exceptions
=
(
boolean
)
$exceptions
;
}
}
}
/**
/**
* Destructor.
* Destructor.
...
@@ -645,10 +667,8 @@ class PHPMailer
...
@@ -645,10 +667,8 @@ class PHPMailer
public
function
__destruct
()
public
function
__destruct
()
{
{
//Close any open SMTP connection nicely
//Close any open SMTP connection nicely
if
(
$this
->
Mailer
==
'smtp'
)
{
$this
->
smtpClose
();
$this
->
smtpClose
();
}
}
}
/**
/**
* Call mail() in a safe_mode-aware fashion.
* Call mail() in a safe_mode-aware fashion.
...
@@ -671,14 +691,16 @@ class PHPMailer
...
@@ -671,14 +691,16 @@ class PHPMailer
}
else
{
}
else
{
$subject
=
$this
->
encodeHeader
(
$this
->
secureHeader
(
$subject
));
$subject
=
$this
->
encodeHeader
(
$this
->
secureHeader
(
$subject
));
}
}
if
(
ini_get
(
'safe_mode'
)
||
!
(
$this
->
UseSendmailOptions
))
{
//Can't use additional_parameters in safe_mode, calling mail() with null params breaks
//@link http://php.net/manual/en/function.mail.php
if
(
ini_get
(
'safe_mode'
)
or
!
$this
->
UseSendmailOptions
or
is_null
(
$params
))
{
$result
=
@
mail
(
$to
,
$subject
,
$body
,
$header
);
$result
=
@
mail
(
$to
,
$subject
,
$body
,
$header
);
}
else
{
}
else
{
$result
=
@
mail
(
$to
,
$subject
,
$body
,
$header
,
$params
);
$result
=
@
mail
(
$to
,
$subject
,
$body
,
$header
,
$params
);
}
}
return
$result
;
return
$result
;
}
}
/**
/**
* Output debugging info via user-defined method.
* Output debugging info via user-defined method.
* Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug).
* Only generates output if SMTP debug output is enabled (@see SMTP::$do_debug).
...
@@ -713,7 +735,7 @@ class PHPMailer
...
@@ -713,7 +735,7 @@ class PHPMailer
case
'echo'
:
case
'echo'
:
default
:
default
:
//Normalize line breaks
//Normalize line breaks
$str
=
preg_replace
(
'/
(\r\n|\r|\n)
/ms'
,
"
\n
"
,
$str
);
$str
=
preg_replace
(
'/
\r\n?
/ms'
,
"
\n
"
,
$str
);
echo
gmdate
(
'Y-m-d H:i:s'
)
.
"
\t
"
.
str_replace
(
echo
gmdate
(
'Y-m-d H:i:s'
)
.
"
\t
"
.
str_replace
(
"
\n
"
,
"
\n
"
,
"
\n
\t
"
,
"
\n
\t
"
,
...
@@ -850,7 +872,7 @@ class PHPMailer
...
@@ -850,7 +872,7 @@ class PHPMailer
$name
=
trim
(
preg_replace
(
'/[\r\n]+/'
,
''
,
$name
));
//Strip breaks and trim
$name
=
trim
(
preg_replace
(
'/[\r\n]+/'
,
''
,
$name
));
//Strip breaks and trim
if
((
$pos
=
strrpos
(
$address
,
'@'
))
===
false
)
{
if
((
$pos
=
strrpos
(
$address
,
'@'
))
===
false
)
{
// At-sign is misssing.
// At-sign is misssing.
$error_message
=
$this
->
lang
(
'invalid_address'
)
.
$address
;
$error_message
=
$this
->
lang
(
'invalid_address'
)
.
" (addAnAddress
$kind
):
$address
"
;
$this
->
setError
(
$error_message
);
$this
->
setError
(
$error_message
);
$this
->
edebug
(
$error_message
);
$this
->
edebug
(
$error_message
);
if
(
$this
->
exceptions
)
{
if
(
$this
->
exceptions
)
{
...
@@ -900,7 +922,7 @@ class PHPMailer
...
@@ -900,7 +922,7 @@ class PHPMailer
return
false
;
return
false
;
}
}
if
(
!
$this
->
validateAddress
(
$address
))
{
if
(
!
$this
->
validateAddress
(
$address
))
{
$error_message
=
$this
->
lang
(
'invalid_address'
)
.
$address
;
$error_message
=
$this
->
lang
(
'invalid_address'
)
.
" (addAnAddress
$kind
):
$address
"
;
$this
->
setError
(
$error_message
);
$this
->
setError
(
$error_message
);
$this
->
edebug
(
$error_message
);
$this
->
edebug
(
$error_message
);
if
(
$this
->
exceptions
)
{
if
(
$this
->
exceptions
)
{
...
@@ -994,7 +1016,7 @@ class PHPMailer
...
@@ -994,7 +1016,7 @@ class PHPMailer
if
((
$pos
=
strrpos
(
$address
,
'@'
))
===
false
or
if
((
$pos
=
strrpos
(
$address
,
'@'
))
===
false
or
(
!
$this
->
has8bitChars
(
substr
(
$address
,
++
$pos
))
or
!
$this
->
idnSupported
())
and
(
!
$this
->
has8bitChars
(
substr
(
$address
,
++
$pos
))
or
!
$this
->
idnSupported
())
and
!
$this
->
validateAddress
(
$address
))
{
!
$this
->
validateAddress
(
$address
))
{
$error_message
=
$this
->
lang
(
'invalid_address'
)
.
$address
;
$error_message
=
$this
->
lang
(
'invalid_address'
)
.
" (setFrom)
$address
"
;
$this
->
setError
(
$error_message
);
$this
->
setError
(
$error_message
);
$this
->
edebug
(
$error_message
);
$this
->
edebug
(
$error_message
);
if
(
$this
->
exceptions
)
{
if
(
$this
->
exceptions
)
{
...
@@ -1027,19 +1049,30 @@ class PHPMailer
...
@@ -1027,19 +1049,30 @@ class PHPMailer
/**
/**
* Check that a string looks like an email address.
* Check that a string looks like an email address.
* @param string $address The email address to check
* @param string $address The email address to check
* @param string $patternselect A selector for the validation pattern to use :
* @param string
|callable
$patternselect A selector for the validation pattern to use :
* * `auto` Pick best pattern automatically;
* * `auto` Pick best pattern automatically;
* * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
* * `pcre8` Use the squiloople.com pattern, requires PCRE > 8.0, PHP >= 5.3.2, 5.2.14;
* * `pcre` Use old PCRE implementation;
* * `pcre` Use old PCRE implementation;
* * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
* * `php` Use PHP built-in FILTER_VALIDATE_EMAIL;
* * `html5` Use the pattern given by the HTML5 spec for 'email' type form input elements.
* * `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.
* * `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.
* @return boolean
* @return boolean
* @static
* @static
* @access public
* @access public
*/
*/
public
static
function
validateAddress
(
$address
,
$patternselect
=
'auto'
)
public
static
function
validateAddress
(
$address
,
$patternselect
=
null
)
{
{
if
(
is_null
(
$patternselect
))
{
$patternselect
=
self
::
$validator
;
}
if
(
is_callable
(
$patternselect
))
{
return
call_user_func
(
$patternselect
,
$address
);
}
//Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
//Reject line breaks in addresses; it's valid RFC5322, but not RFC5321
if
(
strpos
(
$address
,
"
\n
"
)
!==
false
or
strpos
(
$address
,
"
\r
"
)
!==
false
)
{
if
(
strpos
(
$address
,
"
\n
"
)
!==
false
or
strpos
(
$address
,
"
\r
"
)
!==
false
)
{
return
false
;
return
false
;
...
@@ -1216,7 +1249,7 @@ class PHPMailer
...
@@ -1216,7 +1249,7 @@ class PHPMailer
}
}
$this
->
$address_kind
=
$this
->
punyencodeAddress
(
$this
->
$address_kind
);
$this
->
$address_kind
=
$this
->
punyencodeAddress
(
$this
->
$address_kind
);
if
(
!
$this
->
validateAddress
(
$this
->
$address_kind
))
{
if
(
!
$this
->
validateAddress
(
$this
->
$address_kind
))
{
$error_message
=
$this
->
lang
(
'invalid_address'
)
.
$this
->
$address_kind
;
$error_message
=
$this
->
lang
(
'invalid_address'
)
.
' (punyEncode) '
.
$this
->
$address_kind
;
$this
->
setError
(
$error_message
);
$this
->
setError
(
$error_message
);
$this
->
edebug
(
$error_message
);
$this
->
edebug
(
$error_message
);
if
(
$this
->
exceptions
)
{
if
(
$this
->
exceptions
)
{
...
@@ -1227,7 +1260,7 @@ class PHPMailer
...
@@ -1227,7 +1260,7 @@ class PHPMailer
}
}
// Set whether the message is multipart/alternative
// Set whether the message is multipart/alternative
if
(
!
empty
(
$this
->
AltBody
))
{
if
(
$this
->
alternativeExists
(
))
{
$this
->
ContentType
=
'multipart/alternative'
;
$this
->
ContentType
=
'multipart/alternative'
;
}
}
...
@@ -1261,9 +1294,11 @@ class PHPMailer
...
@@ -1261,9 +1294,11 @@ class PHPMailer
// Sign with DKIM if enabled
// Sign with DKIM if enabled
if
(
!
empty
(
$this
->
DKIM_domain
)
if
(
!
empty
(
$this
->
DKIM_domain
)
&&
!
empty
(
$this
->
DKIM_private
)
&&
!
empty
(
$this
->
DKIM_selector
)
&&
!
empty
(
$this
->
DKIM_selector
)
&&
file_exists
(
$this
->
DKIM_private
))
{
&&
(
!
empty
(
$this
->
DKIM_private_string
)
||
(
!
empty
(
$this
->
DKIM_private
)
&&
file_exists
(
$this
->
DKIM_private
))
)
)
{
$header_dkim
=
$this
->
DKIM_Add
(
$header_dkim
=
$this
->
DKIM_Add
(
$this
->
MIMEHeader
.
$this
->
mailHeader
,
$this
->
MIMEHeader
.
$this
->
mailHeader
,
$this
->
encodeHeader
(
$this
->
secureHeader
(
$this
->
Subject
)),
$this
->
encodeHeader
(
$this
->
secureHeader
(
$this
->
Subject
)),
...
@@ -1329,19 +1364,24 @@ class PHPMailer
...
@@ -1329,19 +1364,24 @@ class PHPMailer
*/
*/
protected
function
sendmailSend
(
$header
,
$body
)
protected
function
sendmailSend
(
$header
,
$body
)
{
{
if
(
$this
->
Sender
!=
''
)
{
// CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
if
(
!
empty
(
$this
->
Sender
)
and
self
::
isShellSafe
(
$this
->
Sender
))
{
if
(
$this
->
Mailer
==
'qmail'
)
{
if
(
$this
->
Mailer
==
'qmail'
)
{
$sendmail
=
sprintf
(
'%s -f%s'
,
escapeshellcmd
(
$this
->
Sendmail
),
escapeshellarg
(
$this
->
Sender
))
;
$sendmail
Fmt
=
'%s -f%s'
;
}
else
{
}
else
{
$sendmail
=
sprintf
(
'%s -oi -f%s -t'
,
escapeshellcmd
(
$this
->
Sendmail
),
escapeshellarg
(
$this
->
Sender
))
;
$sendmail
Fmt
=
'%s -oi -f%s -t'
;
}
}
}
else
{
}
else
{
if
(
$this
->
Mailer
==
'qmail'
)
{
if
(
$this
->
Mailer
==
'qmail'
)
{
$sendmail
=
sprintf
(
'%s'
,
escapeshellcmd
(
$this
->
Sendmail
))
;
$sendmail
Fmt
=
'%s'
;
}
else
{
}
else
{
$sendmail
=
sprintf
(
'%s -oi -t'
,
escapeshellcmd
(
$this
->
Sendmail
))
;
$sendmail
Fmt
=
'%s -oi -t'
;
}
}
}
}
// TODO: If possible, this should be changed to escapeshellarg. Needs thorough testing.
$sendmail
=
sprintf
(
$sendmailFmt
,
escapeshellcmd
(
$this
->
Sendmail
),
$this
->
Sender
);
if
(
$this
->
SingleTo
)
{
if
(
$this
->
SingleTo
)
{
foreach
(
$this
->
SingleToArray
as
$toAddr
)
{
foreach
(
$this
->
SingleToArray
as
$toAddr
)
{
if
(
!@
$mail
=
popen
(
$sendmail
,
'w'
))
{
if
(
!@
$mail
=
popen
(
$sendmail
,
'w'
))
{
...
@@ -1388,6 +1428,40 @@ class PHPMailer
...
@@ -1388,6 +1428,40 @@ class PHPMailer
}
}
/**
/**
* 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
* @return boolean
*/
protected
static
function
isShellSafe
(
$string
)
{
// Future-proof
if
(
escapeshellcmd
(
$string
)
!==
$string
or
!
in_array
(
escapeshellarg
(
$string
),
array
(
"'
$string
'"
,
"
\"
$string
\"
"
))
)
{
return
false
;
}
$length
=
strlen
(
$string
);
for
(
$i
=
0
;
$i
<
$length
;
$i
++
)
{
$c
=
$string
[
$i
];
// All other characters have a special meaning in at least one common shell, including = and +.
// Full stop (.) has a special meaning in cmd.exe, but its impact should be negligible here.
// Note that this does permit non-Latin alphanumeric characters based on the current locale.
if
(
!
ctype_alnum
(
$c
)
&&
strpos
(
'@_-.'
,
$c
)
===
false
)
{
return
false
;
}
}
return
true
;
}
/**
* Send mail using the PHP mail() function.
* Send mail using the PHP mail() function.
* @param string $header The message headers
* @param string $header The message headers
* @param string $body The message body
* @param string $body The message body
...
@@ -1404,17 +1478,20 @@ class PHPMailer
...
@@ -1404,17 +1478,20 @@ class PHPMailer
}
}
$to
=
implode
(
', '
,
$toArr
);
$to
=
implode
(
', '
,
$toArr
);
if
(
empty
(
$this
->
Sender
))
{
$params
=
null
;
$params
=
' '
;
//This sets the SMTP envelope sender which gets turned into a return-path header by the receiver
}
else
{
if
(
!
empty
(
$this
->
Sender
)
and
$this
->
validateAddress
(
$this
->
Sender
))
{
// CVE-2016-10033, CVE-2016-10045: Don't pass -f if characters will be escaped.
if
(
self
::
isShellSafe
(
$this
->
Sender
))
{
$params
=
sprintf
(
'-f%s'
,
$this
->
Sender
);
$params
=
sprintf
(
'-f%s'
,
$this
->
Sender
);
}
}
if
(
$this
->
Sender
!=
''
and
!
ini_get
(
'safe_mode'
))
{
}
if
(
!
empty
(
$this
->
Sender
)
and
!
ini_get
(
'safe_mode'
)
and
$this
->
validateAddress
(
$this
->
Sender
))
{
$old_from
=
ini_get
(
'sendmail_from'
);
$old_from
=
ini_get
(
'sendmail_from'
);
ini_set
(
'sendmail_from'
,
$this
->
Sender
);
ini_set
(
'sendmail_from'
,
$this
->
Sender
);
}
}
$result
=
false
;
$result
=
false
;
if
(
$this
->
SingleTo
&&
count
(
$toArr
)
>
1
)
{
if
(
$this
->
SingleTo
and
count
(
$toArr
)
>
1
)
{
foreach
(
$toArr
as
$toAddr
)
{
foreach
(
$toArr
as
$toAddr
)
{
$result
=
$this
->
mailPassthru
(
$toAddr
,
$this
->
Subject
,
$body
,
$header
,
$params
);
$result
=
$this
->
mailPassthru
(
$toAddr
,
$this
->
Subject
,
$body
,
$header
,
$params
);
$this
->
doCallback
(
$result
,
array
(
$toAddr
),
$this
->
cc
,
$this
->
bcc
,
$this
->
Subject
,
$body
,
$this
->
From
);
$this
->
doCallback
(
$result
,
array
(
$toAddr
),
$this
->
cc
,
$this
->
bcc
,
$this
->
Subject
,
$body
,
$this
->
From
);
...
@@ -1463,10 +1540,10 @@ class PHPMailer
...
@@ -1463,10 +1540,10 @@ class PHPMailer
if
(
!
$this
->
smtpConnect
(
$this
->
SMTPOptions
))
{
if
(
!
$this
->
smtpConnect
(
$this
->
SMTPOptions
))
{
throw
new
phpmailerException
(
$this
->
lang
(
'smtp_connect_failed'
),
self
::
STOP_CRITICAL
);
throw
new
phpmailerException
(
$this
->
lang
(
'smtp_connect_failed'
),
self
::
STOP_CRITICAL
);
}
}
if
(
''
==
$this
->
Sender
)
{
if
(
!
empty
(
$this
->
Sender
)
and
$this
->
validateAddress
(
$this
->
Sender
))
{
$smtp_from
=
$this
->
From
;
}
else
{
$smtp_from
=
$this
->
Sender
;
$smtp_from
=
$this
->
Sender
;
}
else
{
$smtp_from
=
$this
->
From
;
}
}
if
(
!
$this
->
smtp
->
mail
(
$smtp_from
))
{
if
(
!
$this
->
smtp
->
mail
(
$smtp_from
))
{
$this
->
setError
(
$this
->
lang
(
'from_failed'
)
.
$smtp_from
.
' : '
.
implode
(
','
,
$this
->
smtp
->
getError
()));
$this
->
setError
(
$this
->
lang
(
'from_failed'
)
.
$smtp_from
.
' : '
.
implode
(
','
,
$this
->
smtp
->
getError
()));
...
@@ -1520,12 +1597,17 @@ class PHPMailer
...
@@ -1520,12 +1597,17 @@ class PHPMailer
* @throws phpmailerException
* @throws phpmailerException
* @return boolean
* @return boolean
*/
*/
public
function
smtpConnect
(
$options
=
array
()
)
public
function
smtpConnect
(
$options
=
null
)
{
{
if
(
is_null
(
$this
->
smtp
))
{
if
(
is_null
(
$this
->
smtp
))
{
$this
->
smtp
=
$this
->
getSMTPInstance
();
$this
->
smtp
=
$this
->
getSMTPInstance
();
}
}
//If no options are provided, use whatever is set in the instance
if
(
is_null
(
$options
))
{
$options
=
$this
->
SMTPOptions
;
}
// Already connected?
// Already connected?
if
(
$this
->
smtp
->
connected
())
{
if
(
$this
->
smtp
->
connected
())
{
return
true
;
return
true
;
...
@@ -1595,7 +1677,7 @@ class PHPMailer
...
@@ -1595,7 +1677,7 @@ class PHPMailer
if
(
!
$this
->
smtp
->
startTLS
())
{
if
(
!
$this
->
smtp
->
startTLS
())
{
throw
new
phpmailerException
(
$this
->
lang
(
'connect_host'
));
throw
new
phpmailerException
(
$this
->
lang
(
'connect_host'
));
}
}
// We must resend
HELO after tls
negotiation
// We must resend
EHLO after TLS
negotiation
$this
->
smtp
->
hello
(
$hello
);
$this
->
smtp
->
hello
(
$hello
);
}
}
if
(
$this
->
SMTPAuth
)
{
if
(
$this
->
SMTPAuth
)
{
...
@@ -1634,7 +1716,7 @@ class PHPMailer
...
@@ -1634,7 +1716,7 @@ class PHPMailer
*/
*/
public
function
smtpClose
()
public
function
smtpClose
()
{
{
if
(
$this
->
smtp
!==
null
)
{
if
(
is_a
(
$this
->
smtp
,
'SMTP'
)
)
{
if
(
$this
->
smtp
->
connected
())
{
if
(
$this
->
smtp
->
connected
())
{
$this
->
smtp
->
quit
();
$this
->
smtp
->
quit
();
$this
->
smtp
->
close
();
$this
->
smtp
->
close
();
...
@@ -1653,6 +1735,19 @@ class PHPMailer
...
@@ -1653,6 +1735,19 @@ class PHPMailer
*/
*/
public
function
setLanguage
(
$langcode
=
'en'
,
$lang_path
=
''
)
public
function
setLanguage
(
$langcode
=
'en'
,
$lang_path
=
''
)
{
{
// Backwards compatibility for renamed language codes
$renamed_langcodes
=
array
(
'br'
=>
'pt_br'
,
'cz'
=>
'cs'
,
'dk'
=>
'da'
,
'no'
=>
'nb'
,
'se'
=>
'sv'
,
);
if
(
isset
(
$renamed_langcodes
[
$langcode
]))
{
$langcode
=
$renamed_langcodes
[
$langcode
];
}
// Define full set of translatable strings in English
// Define full set of translatable strings in English
$PHPMAILER_LANG
=
array
(
$PHPMAILER_LANG
=
array
(
'authenticate'
=>
'SMTP Error: Could not authenticate.'
,
'authenticate'
=>
'SMTP Error: Could not authenticate.'
,
...
@@ -1679,6 +1774,10 @@ class PHPMailer
...
@@ -1679,6 +1774,10 @@ class PHPMailer
// Calculate an absolute path so it can work if CWD is not here
// Calculate an absolute path so it can work if CWD is not here
$lang_path
=
dirname
(
__FILE__
)
.
DIRECTORY_SEPARATOR
.
'language'
.
DIRECTORY_SEPARATOR
;
$lang_path
=
dirname
(
__FILE__
)
.
DIRECTORY_SEPARATOR
.
'language'
.
DIRECTORY_SEPARATOR
;
}
}
//Validate $langcode
if
(
!
preg_match
(
'/^[a-z]{2}(?:_[a-zA-Z]{2})?$/'
,
$langcode
))
{
$langcode
=
'en'
;
}
$foundlang
=
true
;
$foundlang
=
true
;
$lang_file
=
$lang_path
.
'phpmailer.lang-'
.
$langcode
.
'.php'
;
$lang_file
=
$lang_path
.
'phpmailer.lang-'
.
$langcode
.
'.php'
;
// There is no English translation file
// There is no English translation file
...
@@ -1972,7 +2071,9 @@ class PHPMailer
...
@@ -1972,7 +2071,9 @@ class PHPMailer
$result
.=
$this
->
headerLine
(
'Subject'
,
$this
->
encodeHeader
(
$this
->
secureHeader
(
$this
->
Subject
)));
$result
.=
$this
->
headerLine
(
'Subject'
,
$this
->
encodeHeader
(
$this
->
secureHeader
(
$this
->
Subject
)));
}
}
if
(
$this
->
MessageID
!=
''
)
{
// Only allow a custom message ID if it conforms to RFC 5322 section 3.6.4
// https://tools.ietf.org/html/rfc5322#section-3.6.4
if
(
''
!=
$this
->
MessageID
and
preg_match
(
'/^<.*@.*>$/'
,
$this
->
MessageID
))
{
$this
->
lastMessageID
=
$this
->
MessageID
;
$this
->
lastMessageID
=
$this
->
MessageID
;
}
else
{
}
else
{
$this
->
lastMessageID
=
sprintf
(
'<%s@%s>'
,
$this
->
uniqueid
,
$this
->
serverHostname
());
$this
->
lastMessageID
=
sprintf
(
'<%s@%s>'
,
$this
->
uniqueid
,
$this
->
serverHostname
());
...
@@ -2074,7 +2175,15 @@ class PHPMailer
...
@@ -2074,7 +2175,15 @@ class PHPMailer
*/
*/
public
function
getSentMIMEMessage
()
public
function
getSentMIMEMessage
()
{
{
return
$this
->
MIMEHeader
.
$this
->
mailHeader
.
self
::
CRLF
.
$this
->
MIMEBody
;
return
rtrim
(
$this
->
MIMEHeader
.
$this
->
mailHeader
,
"
\n\r
"
)
.
self
::
CRLF
.
self
::
CRLF
.
$this
->
MIMEBody
;
}
/**
* Create unique ID
* @return string
*/
protected
function
generateId
()
{
return
md5
(
uniqid
(
time
()));
}
}
/**
/**
...
@@ -2088,7 +2197,7 @@ class PHPMailer
...
@@ -2088,7 +2197,7 @@ class PHPMailer
{
{
$body
=
''
;
$body
=
''
;
//Create unique IDs and preset boundaries
//Create unique IDs and preset boundaries
$this
->
uniqueid
=
md5
(
uniqid
(
time
())
);
$this
->
uniqueid
=
$this
->
generateId
(
);
$this
->
boundary
[
1
]
=
'b1_'
.
$this
->
uniqueid
;
$this
->
boundary
[
1
]
=
'b1_'
.
$this
->
uniqueid
;
$this
->
boundary
[
2
]
=
'b2_'
.
$this
->
uniqueid
;
$this
->
boundary
[
2
]
=
'b2_'
.
$this
->
uniqueid
;
$this
->
boundary
[
3
]
=
'b3_'
.
$this
->
uniqueid
;
$this
->
boundary
[
3
]
=
'b3_'
.
$this
->
uniqueid
;
...
@@ -2104,12 +2213,12 @@ class PHPMailer
...
@@ -2104,12 +2213,12 @@ class PHPMailer
//Can we do a 7-bit downgrade?
//Can we do a 7-bit downgrade?
if
(
$bodyEncoding
==
'8bit'
and
!
$this
->
has8bitChars
(
$this
->
Body
))
{
if
(
$bodyEncoding
==
'8bit'
and
!
$this
->
has8bitChars
(
$this
->
Body
))
{
$bodyEncoding
=
'7bit'
;
$bodyEncoding
=
'7bit'
;
//All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
$bodyCharSet
=
'us-ascii'
;
$bodyCharSet
=
'us-ascii'
;
}
}
//If lines are too long, and we're not already using an encoding that will shorten them,
//If lines are too long, and we're not already using an encoding that will shorten them,
//change to quoted-printable transfer encoding
//change to quoted-printable transfer encoding
for the body part only
if
(
'base64'
!=
$this
->
Encoding
and
self
::
hasLineLongerThanMax
(
$this
->
Body
))
{
if
(
'base64'
!=
$this
->
Encoding
and
self
::
hasLineLongerThanMax
(
$this
->
Body
))
{
$this
->
Encoding
=
'quoted-printable'
;
$bodyEncoding
=
'quoted-printable'
;
$bodyEncoding
=
'quoted-printable'
;
}
}
...
@@ -2118,10 +2227,12 @@ class PHPMailer
...
@@ -2118,10 +2227,12 @@ class PHPMailer
//Can we do a 7-bit downgrade?
//Can we do a 7-bit downgrade?
if
(
$altBodyEncoding
==
'8bit'
and
!
$this
->
has8bitChars
(
$this
->
AltBody
))
{
if
(
$altBodyEncoding
==
'8bit'
and
!
$this
->
has8bitChars
(
$this
->
AltBody
))
{
$altBodyEncoding
=
'7bit'
;
$altBodyEncoding
=
'7bit'
;
//All ISO 8859, Windows codepage and UTF-8 charsets are ascii compatible up to 7-bit
$altBodyCharSet
=
'us-ascii'
;
$altBodyCharSet
=
'us-ascii'
;
}
}
//If lines are too long, change to quoted-printable transfer encoding
//If lines are too long, and we're not already using an encoding that will shorten them,
if
(
self
::
hasLineLongerThanMax
(
$this
->
AltBody
))
{
//change to quoted-printable transfer encoding for the alt body part only
if
(
'base64'
!=
$altBodyEncoding
and
self
::
hasLineLongerThanMax
(
$this
->
AltBody
))
{
$altBodyEncoding
=
'quoted-printable'
;
$altBodyEncoding
=
'quoted-printable'
;
}
}
//Use this as a preamble in all multipart message types
//Use this as a preamble in all multipart message types
...
@@ -2224,8 +2335,10 @@ class PHPMailer
...
@@ -2224,8 +2335,10 @@ class PHPMailer
$body
.=
$this
->
attachAll
(
'attachment'
,
$this
->
boundary
[
1
]);
$body
.=
$this
->
attachAll
(
'attachment'
,
$this
->
boundary
[
1
]);
break
;
break
;
default
:
default
:
// catch case 'plain' and case ''
// Catch case 'plain' and case '', applies to simple `text/plain` and `text/html` body content types
$body
.=
$this
->
encodeString
(
$this
->
Body
,
$bodyEncoding
);
//Reset the `Encoding` property in case we changed it for line length reasons
$this
->
Encoding
=
$bodyEncoding
;
$body
.=
$this
->
encodeString
(
$this
->
Body
,
$this
->
Encoding
);
break
;
break
;
}
}
...
@@ -2331,8 +2444,7 @@ class PHPMailer
...
@@ -2331,8 +2444,7 @@ class PHPMailer
/**
/**
* Set the message type.
* Set the message type.
* PHPMailer only supports some preset message types,
* PHPMailer only supports some preset message types, not arbitrary MIME structures.
* not arbitrary MIME structures.
* @access protected
* @access protected
* @return void
* @return void
*/
*/
...
@@ -2350,6 +2462,7 @@ class PHPMailer
...
@@ -2350,6 +2462,7 @@ class PHPMailer
}
}
$this
->
message_type
=
implode
(
'_'
,
$type
);
$this
->
message_type
=
implode
(
'_'
,
$type
);
if
(
$this
->
message_type
==
''
)
{
if
(
$this
->
message_type
==
''
)
{
//The 'plain' message_type refers to the message having a single body element, not that it is plain-text
$this
->
message_type
=
'plain'
;
$this
->
message_type
=
'plain'
;
}
}
}
}
...
@@ -2379,6 +2492,7 @@ class PHPMailer
...
@@ -2379,6 +2492,7 @@ class PHPMailer
/**
/**
* Add an attachment from a path on the filesystem.
* Add an attachment from a path on the filesystem.
* Never use a user-supplied path to a file!
* Returns false if the file could not be found or read.
* Returns false if the file could not be found or read.
* @param string $path Path to the attachment.
* @param string $path Path to the attachment.
* @param string $name Overrides the attachment name.
* @param string $name Overrides the attachment name.
...
@@ -2904,6 +3018,7 @@ class PHPMailer
...
@@ -2904,6 +3018,7 @@ class PHPMailer
* displayed inline with the message, not just attached for download.
* displayed inline with the message, not just attached for download.
* This is used in HTML messages that embed the images
* This is used in HTML messages that embed the images
* the HTML refers to using the $cid value.
* 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 $path Path to the attachment.
* @param string $cid Content ID of the attachment; Use this to reference
* @param string $cid Content ID of the attachment; Use this to reference
* the content when using an embedded image in HTML.
* the content when using an embedded image in HTML.
...
@@ -3264,21 +3379,29 @@ class PHPMailer
...
@@ -3264,21 +3379,29 @@ class PHPMailer
}
}
/**
/**
* Create a message from an HTML string.
* Create a message body from an HTML string.
* Automatically makes modifications for inline images and backgrounds
* Automatically inlines images and creates a plain-text version by converting the HTML,
* and creates a plain-text version by converting the HTML.
* overwriting any existing values in Body and AltBody.
* Overwrites any existing values in $this->Body and $this->AltBody
* Do not source $message content from user input!
* $basedir is prepended when handling relative URLs, e.g. <img src="/images/a.png"> and must not be empty
* will look for an image file in $basedir/images/a.png and convert it to inline.
* If you don't provide a $basedir, relative paths will be left untouched (and thus probably break in email)
* If you don't want to apply these transformations to your HTML, just set Body and AltBody directly.
* @access public
* @access public
* @param string $message HTML message string
* @param string $message HTML message string
* @param string $basedir
baseline directory for path
* @param string $basedir
Absolute path to a base directory to prepend to relative paths to images
* @param boolean|callable $advanced Whether to use the internal HTML to text converter
* @param boolean|callable $advanced Whether to use the internal HTML to text converter
* or your own custom converter @see PHPMailer::html2text()
* 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
)
public
function
msgHTML
(
$message
,
$basedir
=
''
,
$advanced
=
false
)
{
{
preg_match_all
(
'/(src|background)=["\'](.*)["\']/Ui'
,
$message
,
$images
);
preg_match_all
(
'/(src|background)=["\'](.*)["\']/Ui'
,
$message
,
$images
);
if
(
array_key_exists
(
2
,
$images
))
{
if
(
array_key_exists
(
2
,
$images
))
{
if
(
strlen
(
$basedir
)
>
1
&&
substr
(
$basedir
,
-
1
)
!=
'/'
)
{
// Ensure $basedir has a trailing /
$basedir
.=
'/'
;
}
foreach
(
$images
[
2
]
as
$imgindex
=>
$url
)
{
foreach
(
$images
[
2
]
as
$imgindex
=>
$url
)
{
// Convert data URIs into embedded images
// Convert data URIs into embedded images
if
(
preg_match
(
'#^data:(image[^;,]*)(;base64)?,#'
,
$url
,
$match
))
{
if
(
preg_match
(
'#^data:(image[^;,]*)(;base64)?,#'
,
$url
,
$match
))
{
...
@@ -3296,18 +3419,24 @@ class PHPMailer
...
@@ -3296,18 +3419,24 @@ class PHPMailer
$message
$message
);
);
}
}
}
elseif
(
substr
(
$url
,
0
,
4
)
!==
'cid:'
&&
!
preg_match
(
'#^[A-z]+://#'
,
$url
))
{
continue
;
// Do not change urls for absolute images (thanks to corvuscorax)
}
if
(
// Only process relative URLs if a basedir is provided (i.e. no absolute local paths)
!
empty
(
$basedir
)
// Ignore URLs containing parent dir traversal (..)
&&
(
strpos
(
$url
,
'..'
)
===
false
)
// Do not change urls that are already inline images
// Do not change urls that are already inline images
&&
substr
(
$url
,
0
,
4
)
!==
'cid:'
// Do not change absolute URLs, including anonymous protocol
&&
!
preg_match
(
'#^[a-z][a-z0-9+.-]*:?//#i'
,
$url
)
)
{
$filename
=
basename
(
$url
);
$filename
=
basename
(
$url
);
$directory
=
dirname
(
$url
);
$directory
=
dirname
(
$url
);
if
(
$directory
==
'.'
)
{
if
(
$directory
==
'.'
)
{
$directory
=
''
;
$directory
=
''
;
}
}
$cid
=
md5
(
$url
)
.
'@phpmailer.0'
;
// RFC2392 S 2
$cid
=
md5
(
$url
)
.
'@phpmailer.0'
;
// RFC2392 S 2
if
(
strlen
(
$basedir
)
>
1
&&
substr
(
$basedir
,
-
1
)
!=
'/'
)
{
$basedir
.=
'/'
;
}
if
(
strlen
(
$directory
)
>
1
&&
substr
(
$directory
,
-
1
)
!=
'/'
)
{
if
(
strlen
(
$directory
)
>
1
&&
substr
(
$directory
,
-
1
)
!=
'/'
)
{
$directory
.=
'/'
;
$directory
.=
'/'
;
}
}
...
@@ -3332,7 +3461,7 @@ class PHPMailer
...
@@ -3332,7 +3461,7 @@ class PHPMailer
// Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better
// Convert all message body line breaks to CRLF, makes quoted-printable encoding work much better
$this
->
Body
=
$this
->
normalizeBreaks
(
$message
);
$this
->
Body
=
$this
->
normalizeBreaks
(
$message
);
$this
->
AltBody
=
$this
->
normalizeBreaks
(
$this
->
html2text
(
$message
,
$advanced
));
$this
->
AltBody
=
$this
->
normalizeBreaks
(
$this
->
html2text
(
$message
,
$advanced
));
if
(
empty
(
$this
->
AltBody
))
{
if
(
!
$this
->
alternativeExists
(
))
{
$this
->
AltBody
=
'To view this email message, open it in a program that understands HTML!'
.
$this
->
AltBody
=
'To view this email message, open it in a program that understands HTML!'
.
self
::
CRLF
.
self
::
CRLF
;
self
::
CRLF
.
self
::
CRLF
;
}
}
...
@@ -3343,7 +3472,7 @@ class PHPMailer
...
@@ -3343,7 +3472,7 @@ class PHPMailer
* Convert an HTML string into plain text.
* Convert an HTML string into plain text.
* This is used by msgHTML().
* This is used by msgHTML().
* Note - older versions of this function used a bundled advanced converter
* Note - older versions of this function used a bundled advanced converter
* which was been removed for license reasons in #232
* which was been removed for license reasons in #232
.
* Example usage:
* Example usage:
* <code>
* <code>
* // Use default conversion
* // Use default conversion
...
@@ -3643,7 +3772,7 @@ class PHPMailer
...
@@ -3643,7 +3772,7 @@ class PHPMailer
* @access public
* @access public
* @param string $signHeader
* @param string $signHeader
* @throws phpmailerException
* @throws phpmailerException
* @return string
* @return string
The DKIM signature value
*/
*/
public
function
DKIM_Sign
(
$signHeader
)
public
function
DKIM_Sign
(
$signHeader
)
{
{
...
@@ -3653,15 +3782,35 @@ class PHPMailer
...
@@ -3653,15 +3782,35 @@ class PHPMailer
}
}
return
''
;
return
''
;
}
}
$privKeyStr
=
file_get_contents
(
$this
->
DKIM_private
);
$privKeyStr
=
!
empty
(
$this
->
DKIM_private_string
)
?
$this
->
DKIM_private_string
:
file_get_contents
(
$this
->
DKIM_private
);
if
(
$this
->
DKIM_passphrase
!=
''
)
{
if
(
''
!=
$this
->
DKIM_passphrase
)
{
$privKey
=
openssl_pkey_get_private
(
$privKeyStr
,
$this
->
DKIM_passphrase
);
$privKey
=
openssl_pkey_get_private
(
$privKeyStr
,
$this
->
DKIM_passphrase
);
}
else
{
}
else
{
$privKey
=
$privKeyStr
;
$privKey
=
openssl_pkey_get_private
(
$privKeyStr
);
}
//Workaround for missing digest algorithms in old PHP & OpenSSL versions
//@link http://stackoverflow.com/a/11117338/333340
if
(
version_compare
(
PHP_VERSION
,
'5.3.0'
)
>=
0
and
in_array
(
'sha256WithRSAEncryption'
,
openssl_get_md_methods
(
true
)))
{
if
(
openssl_sign
(
$signHeader
,
$signature
,
$privKey
,
'sha256WithRSAEncryption'
))
{
openssl_pkey_free
(
$privKey
);
return
base64_encode
(
$signature
);
}
}
if
(
openssl_sign
(
$signHeader
,
$signature
,
$privKey
))
{
}
else
{
$pinfo
=
openssl_pkey_get_details
(
$privKey
);
$hash
=
hash
(
'sha256'
,
$signHeader
);
//'Magic' constant for SHA256 from RFC3447
//@link https://tools.ietf.org/html/rfc3447#page-43
$t
=
'3031300d060960864801650304020105000420'
.
$hash
;
$pslen
=
$pinfo
[
'bits'
]
/
8
-
(
strlen
(
$t
)
/
2
+
3
);
$eb
=
pack
(
'H*'
,
'0001'
.
str_repeat
(
'FF'
,
$pslen
)
.
'00'
.
$t
);
if
(
openssl_private_encrypt
(
$eb
,
$signature
,
$privKey
,
OPENSSL_NO_PADDING
))
{
openssl_pkey_free
(
$privKey
);
return
base64_encode
(
$signature
);
return
base64_encode
(
$signature
);
}
}
}
openssl_pkey_free
(
$privKey
);
return
''
;
return
''
;
}
}
...
@@ -3678,7 +3827,7 @@ class PHPMailer
...
@@ -3678,7 +3827,7 @@ class PHPMailer
foreach
(
$lines
as
$key
=>
$line
)
{
foreach
(
$lines
as
$key
=>
$line
)
{
list
(
$heading
,
$value
)
=
explode
(
':'
,
$line
,
2
);
list
(
$heading
,
$value
)
=
explode
(
':'
,
$line
,
2
);
$heading
=
strtolower
(
$heading
);
$heading
=
strtolower
(
$heading
);
$value
=
preg_replace
(
'/\s
+
/'
,
' '
,
$value
);
// Compress useless spaces
$value
=
preg_replace
(
'/\s
{2,}
/'
,
' '
,
$value
);
// Compress useless spaces
$lines
[
$key
]
=
$heading
.
':'
.
trim
(
$value
);
// Don't forget to remove WSP around the value
$lines
[
$key
]
=
$heading
.
':'
.
trim
(
$value
);
// Don't forget to remove WSP around the value
}
}
$signHeader
=
implode
(
"
\r\n
"
,
$lines
);
$signHeader
=
implode
(
"
\r\n
"
,
$lines
);
...
@@ -3716,7 +3865,7 @@ class PHPMailer
...
@@ -3716,7 +3865,7 @@ class PHPMailer
*/
*/
public
function
DKIM_Add
(
$headers_line
,
$subject
,
$body
)
public
function
DKIM_Add
(
$headers_line
,
$subject
,
$body
)
{
{
$DKIMsignatureType
=
'rsa-sha
1
'
;
// Signature & hash algorithms
$DKIMsignatureType
=
'rsa-sha
256
'
;
// Signature & hash algorithms
$DKIMcanonicalization
=
'relaxed/simple'
;
// Canonicalization of header/body
$DKIMcanonicalization
=
'relaxed/simple'
;
// Canonicalization of header/body
$DKIMquery
=
'dns/txt'
;
// Query method
$DKIMquery
=
'dns/txt'
;
// Query method
$DKIMtime
=
time
();
// Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
$DKIMtime
=
time
();
// Signature Timestamp = seconds since 00:00:00 - Jan 1, 1970 (UTC time zone)
...
@@ -3724,6 +3873,7 @@ class PHPMailer
...
@@ -3724,6 +3873,7 @@ class PHPMailer
$headers
=
explode
(
$this
->
LE
,
$headers_line
);
$headers
=
explode
(
$this
->
LE
,
$headers_line
);
$from_header
=
''
;
$from_header
=
''
;
$to_header
=
''
;
$to_header
=
''
;
$date_header
=
''
;
$current
=
''
;
$current
=
''
;
foreach
(
$headers
as
$header
)
{
foreach
(
$headers
as
$header
)
{
if
(
strpos
(
$header
,
'From:'
)
===
0
)
{
if
(
strpos
(
$header
,
'From:'
)
===
0
)
{
...
@@ -3732,6 +3882,9 @@ class PHPMailer
...
@@ -3732,6 +3882,9 @@ class PHPMailer
}
elseif
(
strpos
(
$header
,
'To:'
)
===
0
)
{
}
elseif
(
strpos
(
$header
,
'To:'
)
===
0
)
{
$to_header
=
$header
;
$to_header
=
$header
;
$current
=
'to_header'
;
$current
=
'to_header'
;
}
elseif
(
strpos
(
$header
,
'Date:'
)
===
0
)
{
$date_header
=
$header
;
$current
=
'date_header'
;
}
else
{
}
else
{
if
(
!
empty
(
$$current
)
&&
strpos
(
$header
,
' =?'
)
===
0
)
{
if
(
!
empty
(
$$current
)
&&
strpos
(
$header
,
' =?'
)
===
0
)
{
$$current
.=
$header
;
$$current
.=
$header
;
...
@@ -3742,6 +3895,7 @@ class PHPMailer
...
@@ -3742,6 +3895,7 @@ class PHPMailer
}
}
$from
=
str_replace
(
'|'
,
'=7C'
,
$this
->
DKIM_QP
(
$from_header
));
$from
=
str_replace
(
'|'
,
'=7C'
,
$this
->
DKIM_QP
(
$from_header
));
$to
=
str_replace
(
'|'
,
'=7C'
,
$this
->
DKIM_QP
(
$to_header
));
$to
=
str_replace
(
'|'
,
'=7C'
,
$this
->
DKIM_QP
(
$to_header
));
$date
=
str_replace
(
'|'
,
'=7C'
,
$this
->
DKIM_QP
(
$date_header
));
$subject
=
str_replace
(
$subject
=
str_replace
(
'|'
,
'|'
,
'=7C'
,
'=7C'
,
...
@@ -3749,7 +3903,7 @@ class PHPMailer
...
@@ -3749,7 +3903,7 @@ class PHPMailer
);
// Copied header fields (dkim-quoted-printable)
);
// Copied header fields (dkim-quoted-printable)
$body
=
$this
->
DKIM_BodyC
(
$body
);
$body
=
$this
->
DKIM_BodyC
(
$body
);
$DKIMlen
=
strlen
(
$body
);
// Length of body
$DKIMlen
=
strlen
(
$body
);
// Length of body
$DKIMb64
=
base64_encode
(
pack
(
'H*'
,
sha1
(
$body
)));
// Base64 of packed binary SHA-1
hash of body
$DKIMb64
=
base64_encode
(
pack
(
'H*'
,
hash
(
'sha256'
,
$body
)));
// Base64 of packed binary SHA-256
hash of body
if
(
''
==
$this
->
DKIM_identity
)
{
if
(
''
==
$this
->
DKIM_identity
)
{
$ident
=
''
;
$ident
=
''
;
}
else
{
}
else
{
...
@@ -3762,16 +3916,18 @@ class PHPMailer
...
@@ -3762,16 +3916,18 @@ class PHPMailer
$this
->
DKIM_selector
.
$this
->
DKIM_selector
.
";
\r\n
"
.
";
\r\n
"
.
"
\t
t="
.
$DKIMtime
.
'; c='
.
$DKIMcanonicalization
.
";
\r\n
"
.
"
\t
t="
.
$DKIMtime
.
'; c='
.
$DKIMcanonicalization
.
";
\r\n
"
.
"
\t
h=From:To:Subject;
\r\n
"
.
"
\t
h=From:To:
Date:
Subject;
\r\n
"
.
"
\t
d="
.
$this
->
DKIM_domain
.
';'
.
$ident
.
"
\r\n
"
.
"
\t
d="
.
$this
->
DKIM_domain
.
';'
.
$ident
.
"
\r\n
"
.
"
\t
z=
$from
\r\n
"
.
"
\t
z=
$from
\r\n
"
.
"
\t
|
$to
\r\n
"
.
"
\t
|
$to
\r\n
"
.
"
\t
|
$date
\r\n
"
.
"
\t
|
$subject
;
\r\n
"
.
"
\t
|
$subject
;
\r\n
"
.
"
\t
bh="
.
$DKIMb64
.
";
\r\n
"
.
"
\t
bh="
.
$DKIMb64
.
";
\r\n
"
.
"
\t
b="
;
"
\t
b="
;
$toSign
=
$this
->
DKIM_HeaderC
(
$toSign
=
$this
->
DKIM_HeaderC
(
$from_header
.
"
\r\n
"
.
$from_header
.
"
\r\n
"
.
$to_header
.
"
\r\n
"
.
$to_header
.
"
\r\n
"
.
$date_header
.
"
\r\n
"
.
$subject_header
.
"
\r\n
"
.
$subject_header
.
"
\r\n
"
.
$dkimhdrs
$dkimhdrs
);
);
...
...
qa-include/vendor/PHPMailer/class.smtp.php
View file @
e3732603
...
@@ -30,7 +30,7 @@ class SMTP
...
@@ -30,7 +30,7 @@ class SMTP
* The PHPMailer SMTP version number.
* The PHPMailer SMTP version number.
* @var string
* @var string
*/
*/
const
VERSION
=
'5.2.
14
'
;
const
VERSION
=
'5.2.
23
'
;
/**
/**
* SMTP line break constant.
* SMTP line break constant.
...
@@ -81,7 +81,7 @@ class SMTP
...
@@ -81,7 +81,7 @@ class SMTP
* @deprecated Use the `VERSION` constant instead
* @deprecated Use the `VERSION` constant instead
* @see SMTP::VERSION
* @see SMTP::VERSION
*/
*/
public
$Version
=
'5.2.
14
'
;
public
$Version
=
'5.2.
23
'
;
/**
/**
* SMTP server port number.
* SMTP server port number.
...
@@ -151,6 +151,17 @@ class SMTP
...
@@ -151,6 +151,17 @@ class SMTP
public
$Timelimit
=
300
;
public
$Timelimit
=
300
;
/**
/**
* @var array patterns to extract smtp transaction id from smtp reply
* Only first capture group will be use, use non-capturing group to deal with it
* Extend this class to override this property to fulfil your needs.
*/
protected
$smtp_transaction_id_patterns
=
array
(
'exim'
=>
'/[0-9]{3} OK id=(.*)/'
,
'sendmail'
=>
'/[0-9]{3} 2.0.0 (.*) Message/'
,
'postfix'
=>
'/[0-9]{3} 2.0.0 Ok: queued as (.*)/'
);
/**
* The socket for the server connection.
* The socket for the server connection.
* @var resource
* @var resource
*/
*/
...
@@ -206,7 +217,7 @@ class SMTP
...
@@ -206,7 +217,7 @@ class SMTP
}
}
//Avoid clash with built-in function names
//Avoid clash with built-in function names
if
(
!
in_array
(
$this
->
Debugoutput
,
array
(
'error_log'
,
'html'
,
'echo'
))
and
is_callable
(
$this
->
Debugoutput
))
{
if
(
!
in_array
(
$this
->
Debugoutput
,
array
(
'error_log'
,
'html'
,
'echo'
))
and
is_callable
(
$this
->
Debugoutput
))
{
call_user_func
(
$this
->
Debugoutput
,
$str
,
$
this
->
do_debug
);
call_user_func
(
$this
->
Debugoutput
,
$str
,
$
level
);
return
;
return
;
}
}
switch
(
$this
->
Debugoutput
)
{
switch
(
$this
->
Debugoutput
)
{
...
@@ -220,8 +231,7 @@ class SMTP
...
@@ -220,8 +231,7 @@ class SMTP
preg_replace
(
'/[\r\n]+/'
,
''
,
$str
),
preg_replace
(
'/[\r\n]+/'
,
''
,
$str
),
ENT_QUOTES
,
ENT_QUOTES
,
'UTF-8'
'UTF-8'
)
)
.
"<br>
\n
"
;
.
"<br>
\n
"
;
break
;
break
;
case
'echo'
:
case
'echo'
:
default
:
default
:
...
@@ -231,7 +241,7 @@ class SMTP
...
@@ -231,7 +241,7 @@ class SMTP
"
\n
"
,
"
\n
"
,
"
\n
\t
"
,
"
\n
\t
"
,
trim
(
$str
)
trim
(
$str
)
)
.
"
\n
"
;
)
.
"
\n
"
;
}
}
}
}
...
@@ -265,15 +275,16 @@ class SMTP
...
@@ -265,15 +275,16 @@ class SMTP
}
}
// Connect to the SMTP server
// Connect to the SMTP server
$this
->
edebug
(
$this
->
edebug
(
"Connection: opening to
$host
:
$port
, timeout=
$timeout
, options="
.
var_export
(
$options
,
true
),
"Connection: opening to
$host
:
$port
, timeout=
$timeout
, options="
.
var_export
(
$options
,
true
),
self
::
DEBUG_CONNECTION
self
::
DEBUG_CONNECTION
);
);
$errno
=
0
;
$errno
=
0
;
$errstr
=
''
;
$errstr
=
''
;
if
(
$streamok
)
{
if
(
$streamok
)
{
$socket_context
=
stream_context_create
(
$options
);
$socket_context
=
stream_context_create
(
$options
);
//Suppress errors; connection failures are handled at a higher level
set_error_handler
(
array
(
$this
,
'errorHandler'
));
$this
->
smtp_conn
=
@
stream_socket_client
(
$this
->
smtp_conn
=
stream_socket_client
(
$host
.
":"
.
$port
,
$host
.
":"
.
$port
,
$errno
,
$errno
,
$errstr
,
$errstr
,
...
@@ -281,12 +292,14 @@ class SMTP
...
@@ -281,12 +292,14 @@ class SMTP
STREAM_CLIENT_CONNECT
,
STREAM_CLIENT_CONNECT
,
$socket_context
$socket_context
);
);
restore_error_handler
();
}
else
{
}
else
{
//Fall back to fsockopen which should work in more places, but is missing some features
//Fall back to fsockopen which should work in more places, but is missing some features
$this
->
edebug
(
$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
self
::
DEBUG_CONNECTION
);
);
set_error_handler
(
array
(
$this
,
'errorHandler'
));
$this
->
smtp_conn
=
fsockopen
(
$this
->
smtp_conn
=
fsockopen
(
$host
,
$host
,
$port
,
$port
,
...
@@ -294,6 +307,7 @@ class SMTP
...
@@ -294,6 +307,7 @@ class SMTP
$errstr
,
$errstr
,
$timeout
$timeout
);
);
restore_error_handler
();
}
}
// Verify we connected properly
// Verify we connected properly
if
(
!
is_resource
(
$this
->
smtp_conn
))
{
if
(
!
is_resource
(
$this
->
smtp_conn
))
{
...
@@ -336,15 +350,26 @@ class SMTP
...
@@ -336,15 +350,26 @@ class SMTP
if
(
!
$this
->
sendCommand
(
'STARTTLS'
,
'STARTTLS'
,
220
))
{
if
(
!
$this
->
sendCommand
(
'STARTTLS'
,
'STARTTLS'
,
220
))
{
return
false
;
return
false
;
}
}
//Allow the best TLS version(s) we can
$crypto_method
=
STREAM_CRYPTO_METHOD_TLS_CLIENT
;
//PHP 5.6.7 dropped inclusion of TLS 1.1 and 1.2 in STREAM_CRYPTO_METHOD_TLS_CLIENT
//so add them back in manually if we can
if
(
defined
(
'STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT'
))
{
$crypto_method
|=
STREAM_CRYPTO_METHOD_TLSv1_2_CLIENT
;
$crypto_method
|=
STREAM_CRYPTO_METHOD_TLSv1_1_CLIENT
;
}
// Begin encrypted connection
// Begin encrypted connection
if
(
!
stream_socket_enable_crypto
(
set_error_handler
(
array
(
$this
,
'errorHandler'
));
$crypto_ok
=
stream_socket_enable_crypto
(
$this
->
smtp_conn
,
$this
->
smtp_conn
,
true
,
true
,
STREAM_CRYPTO_METHOD_TLS_CLIENT
$crypto_method
))
{
);
return
false
;
restore_error_handler
();
}
return
$crypto_ok
;
return
true
;
}
}
/**
/**
...
@@ -373,8 +398,7 @@ class SMTP
...
@@ -373,8 +398,7 @@ class SMTP
}
}
if
(
array_key_exists
(
'EHLO'
,
$this
->
server_caps
))
{
if
(
array_key_exists
(
'EHLO'
,
$this
->
server_caps
))
{
// SMTP extensions are available. Let's try to find a proper authentication method
// SMTP extensions are available; try to find a proper authentication method
if
(
!
array_key_exists
(
'AUTH'
,
$this
->
server_caps
))
{
if
(
!
array_key_exists
(
'AUTH'
,
$this
->
server_caps
))
{
$this
->
setError
(
'Authentication is not allowed at this stage'
);
$this
->
setError
(
'Authentication is not allowed at this stage'
);
// 'at this stage' means that auth may be allowed after the stage changes
// 'at this stage' means that auth may be allowed after the stage changes
...
@@ -389,7 +413,7 @@ class SMTP
...
@@ -389,7 +413,7 @@ class SMTP
);
);
if
(
empty
(
$authtype
))
{
if
(
empty
(
$authtype
))
{
foreach
(
array
(
'
LOGIN'
,
'CRAM-MD5'
,
'NTLM'
,
'PLAIN
'
,
'XOAUTH2'
)
as
$method
)
{
foreach
(
array
(
'
CRAM-MD5'
,
'LOGIN'
,
'PLAIN'
,
'NTLM
'
,
'XOAUTH2'
)
as
$method
)
{
if
(
in_array
(
$method
,
$this
->
server_caps
[
'AUTH'
]))
{
if
(
in_array
(
$method
,
$this
->
server_caps
[
'AUTH'
]))
{
$authtype
=
$method
;
$authtype
=
$method
;
break
;
break
;
...
@@ -399,7 +423,7 @@ class SMTP
...
@@ -399,7 +423,7 @@ class SMTP
$this
->
setError
(
'No supported authentication methods found'
);
$this
->
setError
(
'No supported authentication methods found'
);
return
false
;
return
false
;
}
}
self
::
edebug
(
'Auth method selected: '
.
$authtype
,
self
::
DEBUG_LOWLEVEL
);
self
::
edebug
(
'Auth method selected: '
.
$authtype
,
self
::
DEBUG_LOWLEVEL
);
}
}
if
(
!
in_array
(
$authtype
,
$this
->
server_caps
[
'AUTH'
]))
{
if
(
!
in_array
(
$authtype
,
$this
->
server_caps
[
'AUTH'
]))
{
...
@@ -463,7 +487,7 @@ class SMTP
...
@@ -463,7 +487,7 @@ class SMTP
$temp
=
new
stdClass
;
$temp
=
new
stdClass
;
$ntlm_client
=
new
ntlm_sasl_client_class
;
$ntlm_client
=
new
ntlm_sasl_client_class
;
//Check that functions are available
//Check that functions are available
if
(
!
$ntlm_client
->
I
nitialize
(
$temp
))
{
if
(
!
$ntlm_client
->
i
nitialize
(
$temp
))
{
$this
->
setError
(
$temp
->
error
);
$this
->
setError
(
$temp
->
error
);
$this
->
edebug
(
$this
->
edebug
(
'You need to enable some modules in your php.ini file: '
'You need to enable some modules in your php.ini file: '
...
@@ -473,7 +497,7 @@ class SMTP
...
@@ -473,7 +497,7 @@ class SMTP
return
false
;
return
false
;
}
}
//msg1
//msg1
$msg1
=
$ntlm_client
->
T
ypeMsg1
(
$realm
,
$workstation
);
//msg1
$msg1
=
$ntlm_client
->
t
ypeMsg1
(
$realm
,
$workstation
);
//msg1
if
(
!
$this
->
sendCommand
(
if
(
!
$this
->
sendCommand
(
'AUTH NTLM'
,
'AUTH NTLM'
,
...
@@ -492,7 +516,7 @@ class SMTP
...
@@ -492,7 +516,7 @@ class SMTP
$password
$password
);
);
//msg3
//msg3
$msg3
=
$ntlm_client
->
T
ypeMsg3
(
$msg3
=
$ntlm_client
->
t
ypeMsg3
(
$ntlm_res
,
$ntlm_res
,
$username
,
$username
,
$realm
,
$realm
,
...
@@ -736,7 +760,7 @@ class SMTP
...
@@ -736,7 +760,7 @@ class SMTP
protected
function
parseHelloFields
(
$type
)
protected
function
parseHelloFields
(
$type
)
{
{
$this
->
server_caps
=
array
();
$this
->
server_caps
=
array
();
$lines
=
explode
(
"
\n
"
,
$this
->
last_re
ply
);
$lines
=
explode
(
"
\n
"
,
$this
->
helo_r
ply
);
foreach
(
$lines
as
$n
=>
$s
)
{
foreach
(
$lines
as
$n
=>
$s
)
{
//First 4 chars contain response code followed by - or space
//First 4 chars contain response code followed by - or space
...
@@ -868,7 +892,8 @@ class SMTP
...
@@ -868,7 +892,8 @@ class SMTP
$code_ex
=
(
count
(
$matches
)
>
2
?
$matches
[
2
]
:
null
);
$code_ex
=
(
count
(
$matches
)
>
2
?
$matches
[
2
]
:
null
);
// Cut off error code from each response line
// Cut off error code from each response line
$detail
=
preg_replace
(
$detail
=
preg_replace
(
"/
{
$code
}
[ -]"
.
(
$code_ex
?
str_replace
(
'.'
,
'\\.'
,
$code_ex
)
.
' '
:
''
)
.
"/m"
,
"/
{
$code
}
[ -]"
.
(
$code_ex
?
str_replace
(
'.'
,
'\\.'
,
$code_ex
)
.
' '
:
''
)
.
"/m"
,
''
,
''
,
$this
->
last_reply
$this
->
last_reply
);
);
...
@@ -1080,7 +1105,7 @@ class SMTP
...
@@ -1080,7 +1105,7 @@ class SMTP
// Now check if reads took too long
// Now check if reads took too long
if
(
$endtime
and
time
()
>
$endtime
)
{
if
(
$endtime
and
time
()
>
$endtime
)
{
$this
->
edebug
(
$this
->
edebug
(
'SMTP -> get_lines(): timelimit reached ('
.
'SMTP -> get_lines(): timelimit reached ('
.
$this
->
Timelimit
.
' sec)'
,
$this
->
Timelimit
.
' sec)'
,
self
::
DEBUG_LOWLEVEL
self
::
DEBUG_LOWLEVEL
);
);
...
@@ -1178,4 +1203,49 @@ class SMTP
...
@@ -1178,4 +1203,49 @@ class SMTP
{
{
return
$this
->
Timeout
;
return
$this
->
Timeout
;
}
}
/**
* Reports an error number and string.
* @param integer $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 integer $errline The line number the error occurred on
*/
protected
function
errorHandler
(
$errno
,
$errmsg
,
$errfile
=
''
,
$errline
=
0
)
{
$notice
=
'Connection failed.'
;
$this
->
setError
(
$notice
,
$errno
,
$errmsg
);
$this
->
edebug
(
$notice
.
' Error #'
.
$errno
.
': '
.
$errmsg
.
" [
$errfile
line
$errline
]"
,
self
::
DEBUG_CONNECTION
);
}
/**
* Will return the ID of the last smtp transaction based on a list of patterns provided
* in SMTP::$smtp_transaction_id_patterns.
* If no reply has been received yet, it will return null.
* If no pattern has been matched, it will return false.
* @return bool|null|string
*/
public
function
getLastTransactionID
()
{
$reply
=
$this
->
getLastReply
();
if
(
empty
(
$reply
))
{
return
null
;
}
foreach
(
$this
->
smtp_transaction_id_patterns
as
$smtp_transaction_id_pattern
)
{
if
(
preg_match
(
$smtp_transaction_id_pattern
,
$reply
,
$matches
))
{
return
$matches
[
1
];
}
}
return
false
;
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment