-
Notifications
You must be signed in to change notification settings - Fork 54
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
* Email fallback. In Progress * Prepare version 2.1.1
- Loading branch information
1 parent
6b3fb1b
commit e0a5863
Showing
6 changed files
with
271 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -449,39 +449,272 @@ function wp_mail($to, $subject, $message, $headers = '', $attachments = []) | |
]; | ||
|
||
$endpoint = mg_api_get_region($region); | ||
$endpoint = ($endpoint) ? $endpoint : 'https://api.mailgun.net/v3/'; | ||
$endpoint = ($endpoint) ?: 'https://api.mailgun.net/v3/'; | ||
$url = $endpoint . "{$domain}/messages"; | ||
|
||
// TODO: Mailgun only supports 1000 recipients per request, since we are | ||
// overriding this function, let's add looping here to handle that | ||
$response = wp_remote_post($url, $data); | ||
if (is_wp_error($response)) { | ||
// Store WP error in last error. | ||
mg_api_last_error($response->get_error_message()); | ||
$isFallbackNeeded = false; | ||
try { | ||
$response = wp_remote_post($url, $data); | ||
if (is_wp_error($response)) { | ||
// Store WP error in last error. | ||
mg_api_last_error($response->get_error_message()); | ||
|
||
return false; | ||
} | ||
$isFallbackNeeded = true; | ||
} | ||
|
||
$response_code = wp_remote_retrieve_response_code($response); | ||
$response_body = json_decode(wp_remote_retrieve_body($response)); | ||
$response_code = wp_remote_retrieve_response_code($response); | ||
$response_body = json_decode(wp_remote_retrieve_body($response)); | ||
|
||
// Mailgun API should *always* return a `message` field, even when | ||
// $response_code != 200, so a lack of `message` indicates something | ||
// is broken. | ||
if ((int)$response_code != 200 || !isset($response_body->message)) { | ||
// Store response code and HTTP response message in last error. | ||
$response_message = wp_remote_retrieve_response_message($response); | ||
$errmsg = "$response_code - $response_message"; | ||
mg_api_last_error($errmsg); | ||
if ((int)$response_code !== 200 || !isset($response_body->message)) { | ||
// Store response code and HTTP response message in last error. | ||
$response_message = wp_remote_retrieve_response_message($response); | ||
$errmsg = "$response_code - $response_message"; | ||
mg_api_last_error($errmsg); | ||
|
||
return false; | ||
$isFallbackNeeded = true; | ||
} | ||
if ($response_body->message !== 'Queued. Thank you.') { | ||
mg_api_last_error($response_body->message); | ||
|
||
$isFallbackNeeded = true; | ||
} | ||
} catch (Throwable $throwable) { | ||
$isFallbackNeeded = true; | ||
} | ||
|
||
// Not sure there is any additional checking that needs to be done here, but why not? | ||
if ($response_body->message !== 'Queued. Thank you.') { | ||
mg_api_last_error($response_body->message); | ||
//Email Fallback | ||
|
||
return false; | ||
if ($isFallbackNeeded) { | ||
global $phpmailer; | ||
|
||
// (Re)create it, if it's gone missing. | ||
if (!($phpmailer instanceof PHPMailer\PHPMailer\PHPMailer)) { | ||
require_once ABSPATH . WPINC . '/PHPMailer/PHPMailer.php'; | ||
require_once ABSPATH . WPINC . '/PHPMailer/SMTP.php'; | ||
require_once ABSPATH . WPINC . '/PHPMailer/Exception.php'; | ||
$phpmailer = new PHPMailer\PHPMailer\PHPMailer(true); | ||
|
||
$phpmailer::$validator = static function ($email) { | ||
return (bool)is_email($email); | ||
}; | ||
} | ||
|
||
// Empty out the values that may be set. | ||
$phpmailer->clearAllRecipients(); | ||
$phpmailer->clearAttachments(); | ||
$phpmailer->clearCustomHeaders(); | ||
$phpmailer->clearReplyTos(); | ||
$phpmailer->Body = ''; | ||
$phpmailer->AltBody = ''; | ||
|
||
// Set "From" name and email. | ||
|
||
// If we don't have a name from the input headers. | ||
if (!isset($from_name)) { | ||
$from_name = 'WordPress'; | ||
} | ||
|
||
/* | ||
* If we don't have an email from the input headers, default to wordpress@$sitename | ||
* Some hosts will block outgoing mail from this address if it doesn't exist, | ||
* but there's no easy alternative. Defaulting to admin_email might appear to be | ||
* another option, but some hosts may refuse to relay mail from an unknown domain. | ||
* See https://core.trac.wordpress.org/ticket/5007. | ||
*/ | ||
if (!isset($from_email)) { | ||
// Get the site domain and get rid of www. | ||
$sitename = wp_parse_url(network_home_url(), PHP_URL_HOST); | ||
$from_email = 'wordpress@'; | ||
|
||
if (null !== $sitename) { | ||
if (str_starts_with($sitename, 'www.')) { | ||
$sitename = substr($sitename, 4); | ||
} | ||
|
||
$from_email .= $sitename; | ||
} | ||
} | ||
|
||
/** | ||
* Filters the email address to send from. | ||
* @param string $from_email Email address to send from. | ||
* @since 2.2.0 | ||
*/ | ||
$from_email = apply_filters('wp_mail_from', $from_email); | ||
|
||
/** | ||
* Filters the name to associate with the "from" email address. | ||
* @param string $from_name Name associated with the "from" email address. | ||
* @since 2.3.0 | ||
*/ | ||
$from_name = apply_filters('wp_mail_from_name', $from_name); | ||
|
||
try { | ||
$phpmailer->setFrom($from_email, $from_name, false); | ||
} catch (PHPMailer\PHPMailer\Exception $e) { | ||
$mail_error_data = compact('to', 'subject', 'message', 'headers', 'attachments'); | ||
$mail_error_data['phpmailer_exception_code'] = $e->getCode(); | ||
|
||
/** This filter is documented in wp-includes/pluggable.php */ | ||
do_action('wp_mail_failed', new WP_Error('wp_mail_failed', $e->getMessage(), $mail_error_data)); | ||
|
||
return false; | ||
} | ||
|
||
// Set mail's subject and body. | ||
$phpmailer->Subject = $subject; | ||
$phpmailer->Body = $message; | ||
|
||
// Set destination addresses, using appropriate methods for handling addresses. | ||
$address_headers = compact('to', 'cc', 'bcc', 'replyTo'); | ||
|
||
foreach ($address_headers as $address_header => $addresses) { | ||
if (empty($addresses)) { | ||
continue; | ||
} | ||
|
||
foreach ((array)$addresses as $address) { | ||
try { | ||
// Break $recipient into name and address parts if in the format "Foo <[email protected]>". | ||
$recipient_name = ''; | ||
|
||
if (preg_match('/(.*)<(.+)>/', $address, $matches)) { | ||
if (count($matches) === 3) { | ||
$recipient_name = $matches[1]; | ||
$address = $matches[2]; | ||
} | ||
} | ||
|
||
switch ($address_header) { | ||
case 'to': | ||
$phpmailer->addAddress($address, $recipient_name); | ||
break; | ||
case 'cc': | ||
$phpmailer->addCc($address, $recipient_name); | ||
break; | ||
case 'bcc': | ||
$phpmailer->addBcc($address, $recipient_name); | ||
break; | ||
case 'reply_to': | ||
$phpmailer->addReplyTo($address, $recipient_name); | ||
break; | ||
} | ||
} catch (PHPMailer\PHPMailer\Exception $e) { | ||
continue; | ||
} | ||
} | ||
} | ||
|
||
// Set to use PHP's mail(). | ||
$phpmailer->isMail(); | ||
|
||
// Set Content-Type and charset. | ||
|
||
// If we don't have a Content-Type from the input headers. | ||
if (!isset($content_type)) { | ||
$content_type = 'text/plain'; | ||
} | ||
|
||
/** | ||
* Filters the wp_mail() content type. | ||
* @param string $content_type Default wp_mail() content type. | ||
* @since 2.3.0 | ||
*/ | ||
$content_type = apply_filters('wp_mail_content_type', $content_type); | ||
|
||
$phpmailer->ContentType = $content_type; | ||
|
||
// Set whether it's plaintext, depending on $content_type. | ||
if ('text/html' === $content_type) { | ||
$phpmailer->isHTML(true); | ||
} | ||
|
||
// If we don't have a charset from the input headers. | ||
if (!isset($charset)) { | ||
$charset = get_bloginfo('charset'); | ||
} | ||
|
||
/** | ||
* Filters the default wp_mail() charset. | ||
* @param string $charset Default email charset. | ||
* @since 2.3.0 | ||
*/ | ||
$phpmailer->CharSet = apply_filters('wp_mail_charset', $charset); | ||
|
||
// Set custom headers. | ||
if (!empty($headers)) { | ||
foreach ((array)$headers as $name => $content) { | ||
// Only add custom headers not added automatically by PHPMailer. | ||
if (!in_array($name, ['MIME-Version', 'X-Mailer'], true)) { | ||
try { | ||
$phpmailer->addCustomHeader(sprintf('%1$s: %2$s', $name, $content)); | ||
} catch (PHPMailer\PHPMailer\Exception $e) { | ||
continue; | ||
} | ||
} | ||
} | ||
|
||
if (false !== stripos($content_type, 'multipart') && !empty($boundary)) { | ||
$phpmailer->addCustomHeader(sprintf('Content-Type: %s; boundary="%s"', $content_type, $boundary)); | ||
} | ||
} | ||
|
||
if (!empty($attachments)) { | ||
foreach ($attachments as $filename => $attachment) { | ||
$filename = is_string($filename) ? $filename : ''; | ||
|
||
try { | ||
$phpmailer->addAttachment($attachment, $filename); | ||
} catch (PHPMailer\PHPMailer\Exception $e) { | ||
continue; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Fires after PHPMailer is initialized. | ||
* @param PHPMailer $phpmailer The PHPMailer instance (passed by reference). | ||
* @since 2.2.0 | ||
*/ | ||
do_action_ref_array('phpmailer_init', [&$phpmailer]); | ||
|
||
$mail_data = compact('to', 'subject', 'message', 'headers', 'attachments'); | ||
|
||
// Send! | ||
try { | ||
$send = $phpmailer->send(); | ||
|
||
/** | ||
* Fires after PHPMailer has successfully sent an email. | ||
* The firing of this action does not necessarily mean that the recipient(s) received the | ||
* email successfully. It only means that the `send` method above was able to | ||
* process the request without any errors. | ||
* @param array $mail_data { | ||
* An array containing the email recipient(s), subject, message, headers, and attachments. | ||
* @type string[] $to Email addresses to send message. | ||
* @type string $subject Email subject. | ||
* @type string $message Message contents. | ||
* @type string[] $headers Additional headers. | ||
* @type string[] $attachments Paths to files to attach. | ||
* } | ||
* @since 5.9.0 | ||
*/ | ||
do_action('wp_mail_succeeded', $mail_data); | ||
|
||
return $send; | ||
} catch (PHPMailer\PHPMailer\Exception $e) { | ||
$mail_data['phpmailer_exception_code'] = $e->getCode(); | ||
|
||
/** | ||
* Fires after a PHPMailer\PHPMailer\Exception is caught. | ||
* @param WP_Error $error A WP_Error object with the PHPMailer\PHPMailer\Exception message, and an array | ||
* containing the mail recipient, subject, message, headers, and attachments. | ||
* @since 4.4.0 | ||
*/ | ||
do_action('wp_mail_failed', new WP_Error('wp_mail_failed', $e->getMessage(), $mail_data)); | ||
|
||
return false; | ||
} | ||
} | ||
|
||
return true; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters