Skip to content

Commit 49fb589

Browse files
External Libraries: Upgrade PHPMailer to version 6.10.0.
This is a feature and maintenance release introducing full support for [https://www.rfc-editor.org/rfc/rfc6531 RFC 6531 SMTPUTF8], meaning that plugin or theme developers are now free to use Unicode characters in email addresses, such as `JøeÜ[email protected]`, without any complicated encoding schemes. Using this feature requires sending through a mail server that advertises support for SMTPUTF8. For full details see [https://github.com/PHPMailer/PHPMailer/blob/master/SMTPUTF8.md SMTPUTF8.md]. This commit also includes the parts of PHPMailer not previously bundled with core, specifically the DSNConfigurator, OAuth, and POP3 classes, so that plugin developers could use those extended features without including their own versions of the library. Including the full library aims to make it easier (and faster) for core to update in case of security issues, and to provide more flexibility and security for plugins and (by extension) users of WordPress. References: * [https://github.com/PHPMailer/PHPMailer/releases/tag/v6.10.0 PHPMailer 6.10.0 release notes] * [PHPMailer/PHPMailer@v6.9.3...v6.10.0 Full list of changes in PHPMailer 6.10.0] Follow-up to [54937], [55557], [56484], [57137], [59246], [59481]. Props agulbra, Ipstenu, JeffMatson, lukecavanagh, dd32, Otto42, JeffMatson, MattyRob, desrosj, SirLouen, SergeyBiryukov. Fixes #39714, #63811. git-svn-id: https://develop.svn.wordpress.org/trunk@60623 602fd350-edb4-49c9-b593-d223f7449a82
1 parent dcf780a commit 49fb589

File tree

7 files changed

+1067
-17
lines changed

7 files changed

+1067
-17
lines changed
Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
<?php
2+
3+
/**
4+
* PHPMailer - PHP email creation and transport class.
5+
* PHP Version 5.5.
6+
*
7+
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
8+
*
9+
* @author Marcus Bointon (Synchro/coolbru) <[email protected]>
10+
* @author Jim Jagielski (jimjag) <[email protected]>
11+
* @author Andy Prevost (codeworxtech) <[email protected]>
12+
* @author Brent R. Matzelle (original founder)
13+
* @copyright 2012 - 2023 Marcus Bointon
14+
* @copyright 2010 - 2012 Jim Jagielski
15+
* @copyright 2004 - 2009 Andy Prevost
16+
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
17+
* @note This program is distributed in the hope that it will be useful - WITHOUT
18+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19+
* FITNESS FOR A PARTICULAR PURPOSE.
20+
*/
21+
22+
namespace PHPMailer\PHPMailer;
23+
24+
/**
25+
* Configure PHPMailer with DSN string.
26+
*
27+
* @see https://en.wikipedia.org/wiki/Data_source_name
28+
*
29+
* @author Oleg Voronkovich <[email protected]>
30+
*/
31+
class DSNConfigurator
32+
{
33+
/**
34+
* Create new PHPMailer instance configured by DSN.
35+
*
36+
* @param string $dsn DSN
37+
* @param bool $exceptions Should we throw external exceptions?
38+
*
39+
* @return PHPMailer
40+
*/
41+
public static function mailer($dsn, $exceptions = null)
42+
{
43+
static $configurator = null;
44+
45+
if (null === $configurator) {
46+
$configurator = new DSNConfigurator();
47+
}
48+
49+
return $configurator->configure(new PHPMailer($exceptions), $dsn);
50+
}
51+
52+
/**
53+
* Configure PHPMailer instance with DSN string.
54+
*
55+
* @param PHPMailer $mailer PHPMailer instance
56+
* @param string $dsn DSN
57+
*
58+
* @return PHPMailer
59+
*/
60+
public function configure(PHPMailer $mailer, $dsn)
61+
{
62+
$config = $this->parseDSN($dsn);
63+
64+
$this->applyConfig($mailer, $config);
65+
66+
return $mailer;
67+
}
68+
69+
/**
70+
* Parse DSN string.
71+
*
72+
* @param string $dsn DSN
73+
*
74+
* @throws Exception If DSN is malformed
75+
*
76+
* @return array Configuration
77+
*/
78+
private function parseDSN($dsn)
79+
{
80+
$config = $this->parseUrl($dsn);
81+
82+
if (false === $config || !isset($config['scheme']) || !isset($config['host'])) {
83+
throw new Exception('Malformed DSN');
84+
}
85+
86+
if (isset($config['query'])) {
87+
parse_str($config['query'], $config['query']);
88+
}
89+
90+
return $config;
91+
}
92+
93+
/**
94+
* Apply configuration to mailer.
95+
*
96+
* @param PHPMailer $mailer PHPMailer instance
97+
* @param array $config Configuration
98+
*
99+
* @throws Exception If scheme is invalid
100+
*/
101+
private function applyConfig(PHPMailer $mailer, $config)
102+
{
103+
switch ($config['scheme']) {
104+
case 'mail':
105+
$mailer->isMail();
106+
break;
107+
case 'sendmail':
108+
$mailer->isSendmail();
109+
break;
110+
case 'qmail':
111+
$mailer->isQmail();
112+
break;
113+
case 'smtp':
114+
case 'smtps':
115+
$mailer->isSMTP();
116+
$this->configureSMTP($mailer, $config);
117+
break;
118+
default:
119+
throw new Exception(
120+
sprintf(
121+
'Invalid scheme: "%s". Allowed values: "mail", "sendmail", "qmail", "smtp", "smtps".',
122+
$config['scheme']
123+
)
124+
);
125+
}
126+
127+
if (isset($config['query'])) {
128+
$this->configureOptions($mailer, $config['query']);
129+
}
130+
}
131+
132+
/**
133+
* Configure SMTP.
134+
*
135+
* @param PHPMailer $mailer PHPMailer instance
136+
* @param array $config Configuration
137+
*/
138+
private function configureSMTP($mailer, $config)
139+
{
140+
$isSMTPS = 'smtps' === $config['scheme'];
141+
142+
if ($isSMTPS) {
143+
$mailer->SMTPSecure = PHPMailer::ENCRYPTION_STARTTLS;
144+
}
145+
146+
$mailer->Host = $config['host'];
147+
148+
if (isset($config['port'])) {
149+
$mailer->Port = $config['port'];
150+
} elseif ($isSMTPS) {
151+
$mailer->Port = SMTP::DEFAULT_SECURE_PORT;
152+
}
153+
154+
$mailer->SMTPAuth = isset($config['user']) || isset($config['pass']);
155+
156+
if (isset($config['user'])) {
157+
$mailer->Username = $config['user'];
158+
}
159+
160+
if (isset($config['pass'])) {
161+
$mailer->Password = $config['pass'];
162+
}
163+
}
164+
165+
/**
166+
* Configure options.
167+
*
168+
* @param PHPMailer $mailer PHPMailer instance
169+
* @param array $options Options
170+
*
171+
* @throws Exception If option is unknown
172+
*/
173+
private function configureOptions(PHPMailer $mailer, $options)
174+
{
175+
$allowedOptions = get_object_vars($mailer);
176+
177+
unset($allowedOptions['Mailer']);
178+
unset($allowedOptions['SMTPAuth']);
179+
unset($allowedOptions['Username']);
180+
unset($allowedOptions['Password']);
181+
unset($allowedOptions['Hostname']);
182+
unset($allowedOptions['Port']);
183+
unset($allowedOptions['ErrorInfo']);
184+
185+
$allowedOptions = \array_keys($allowedOptions);
186+
187+
foreach ($options as $key => $value) {
188+
if (!in_array($key, $allowedOptions)) {
189+
throw new Exception(
190+
sprintf(
191+
'Unknown option: "%s". Allowed values: "%s"',
192+
$key,
193+
implode('", "', $allowedOptions)
194+
)
195+
);
196+
}
197+
198+
switch ($key) {
199+
case 'AllowEmpty':
200+
case 'SMTPAutoTLS':
201+
case 'SMTPKeepAlive':
202+
case 'SingleTo':
203+
case 'UseSendmailOptions':
204+
case 'do_verp':
205+
case 'DKIM_copyHeaderFields':
206+
$mailer->$key = (bool) $value;
207+
break;
208+
case 'Priority':
209+
case 'SMTPDebug':
210+
case 'WordWrap':
211+
$mailer->$key = (int) $value;
212+
break;
213+
default:
214+
$mailer->$key = $value;
215+
break;
216+
}
217+
}
218+
}
219+
220+
/**
221+
* Parse a URL.
222+
* Wrapper for the built-in parse_url function to work around a bug in PHP 5.5.
223+
*
224+
* @param string $url URL
225+
*
226+
* @return array|false
227+
*/
228+
protected function parseUrl($url)
229+
{
230+
if (\PHP_VERSION_ID >= 50600 || false === strpos($url, '?')) {
231+
return parse_url($url);
232+
}
233+
234+
$chunks = explode('?', $url);
235+
if (is_array($chunks)) {
236+
$result = parse_url($chunks[0]);
237+
if (is_array($result)) {
238+
$result['query'] = $chunks[1];
239+
}
240+
return $result;
241+
}
242+
243+
return false;
244+
}
245+
}

src/wp-includes/PHPMailer/OAuth.php

Lines changed: 139 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,139 @@
1+
<?php
2+
3+
/**
4+
* PHPMailer - PHP email creation and transport class.
5+
* PHP Version 5.5.
6+
*
7+
* @see https://github.com/PHPMailer/PHPMailer/ The PHPMailer GitHub project
8+
*
9+
* @author Marcus Bointon (Synchro/coolbru) <[email protected]>
10+
* @author Jim Jagielski (jimjag) <[email protected]>
11+
* @author Andy Prevost (codeworxtech) <[email protected]>
12+
* @author Brent R. Matzelle (original founder)
13+
* @copyright 2012 - 2020 Marcus Bointon
14+
* @copyright 2010 - 2012 Jim Jagielski
15+
* @copyright 2004 - 2009 Andy Prevost
16+
* @license https://www.gnu.org/licenses/old-licenses/lgpl-2.1.html GNU Lesser General Public License
17+
* @note This program is distributed in the hope that it will be useful - WITHOUT
18+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19+
* FITNESS FOR A PARTICULAR PURPOSE.
20+
*/
21+
22+
namespace PHPMailer\PHPMailer;
23+
24+
use League\OAuth2\Client\Grant\RefreshToken;
25+
use League\OAuth2\Client\Provider\AbstractProvider;
26+
use League\OAuth2\Client\Token\AccessToken;
27+
28+
/**
29+
* OAuth - OAuth2 authentication wrapper class.
30+
* Uses the oauth2-client package from the League of Extraordinary Packages.
31+
*
32+
* @see https://oauth2-client.thephpleague.com
33+
*
34+
* @author Marcus Bointon (Synchro/coolbru) <[email protected]>
35+
*/
36+
class OAuth implements OAuthTokenProvider
37+
{
38+
/**
39+
* An instance of the League OAuth Client Provider.
40+
*
41+
* @var AbstractProvider
42+
*/
43+
protected $provider;
44+
45+
/**
46+
* The current OAuth access token.
47+
*
48+
* @var AccessToken
49+
*/
50+
protected $oauthToken;
51+
52+
/**
53+
* The user's email address, usually used as the login ID
54+
* and also the from address when sending email.
55+
*
56+
* @var string
57+
*/
58+
protected $oauthUserEmail = '';
59+
60+
/**
61+
* The client secret, generated in the app definition of the service you're connecting to.
62+
*
63+
* @var string
64+
*/
65+
protected $oauthClientSecret = '';
66+
67+
/**
68+
* The client ID, generated in the app definition of the service you're connecting to.
69+
*
70+
* @var string
71+
*/
72+
protected $oauthClientId = '';
73+
74+
/**
75+
* The refresh token, used to obtain new AccessTokens.
76+
*
77+
* @var string
78+
*/
79+
protected $oauthRefreshToken = '';
80+
81+
/**
82+
* OAuth constructor.
83+
*
84+
* @param array $options Associative array containing
85+
* `provider`, `userName`, `clientSecret`, `clientId` and `refreshToken` elements
86+
*/
87+
public function __construct($options)
88+
{
89+
$this->provider = $options['provider'];
90+
$this->oauthUserEmail = $options['userName'];
91+
$this->oauthClientSecret = $options['clientSecret'];
92+
$this->oauthClientId = $options['clientId'];
93+
$this->oauthRefreshToken = $options['refreshToken'];
94+
}
95+
96+
/**
97+
* Get a new RefreshToken.
98+
*
99+
* @return RefreshToken
100+
*/
101+
protected function getGrant()
102+
{
103+
return new RefreshToken();
104+
}
105+
106+
/**
107+
* Get a new AccessToken.
108+
*
109+
* @return AccessToken
110+
*/
111+
protected function getToken()
112+
{
113+
return $this->provider->getAccessToken(
114+
$this->getGrant(),
115+
['refresh_token' => $this->oauthRefreshToken]
116+
);
117+
}
118+
119+
/**
120+
* Generate a base64-encoded OAuth token.
121+
*
122+
* @return string
123+
*/
124+
public function getOauth64()
125+
{
126+
//Get a new token if it's not available or has expired
127+
if (null === $this->oauthToken || $this->oauthToken->hasExpired()) {
128+
$this->oauthToken = $this->getToken();
129+
}
130+
131+
return base64_encode(
132+
'user=' .
133+
$this->oauthUserEmail .
134+
"\001auth=Bearer " .
135+
$this->oauthToken .
136+
"\001\001"
137+
);
138+
}
139+
}

0 commit comments

Comments
 (0)