updated plugin `WP Mail SMTP` version 2.1.1

This commit is contained in:
KawaiiPunk 2020-06-20 17:12:03 +00:00 committed by Gitium
parent 04443ddae8
commit 12dae937d6
193 changed files with 20688 additions and 1869 deletions

File diff suppressed because one or more lines are too long

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 871 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -0,0 +1 @@
<svg aria-hidden="true" data-prefix="fas" data-icon="check-circle" class="svg-inline--fa fa-check-circle fa-w-16" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#2ecc71" d="M504 256c0 136.967-111.033 248-248 248S8 392.967 8 256 119.033 8 256 8s248 111.033 248 248zM227.314 387.314l184-184c6.248-6.248 6.248-16.379 0-22.627l-22.627-22.627c-6.248-6.249-16.379-6.249-22.628 0L216 308.118l-70.059-70.059c-6.248-6.248-16.379-6.248-22.628 0l-22.627 22.627c-6.248 6.248-6.248 16.379 0 22.627l104 104c6.249 6.249 16.379 6.249 22.628.001z"/></svg>

After

Width:  |  Height:  |  Size: 560 B

View File

@ -0,0 +1 @@
<svg aria-hidden="true" data-prefix="far" data-icon="exclamation-circle" class="svg-inline--fa fa-exclamation-circle fa-w-16" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#e74c3c" d="M256 8C119.043 8 8 119.083 8 256c0 136.997 111.043 248 248 248s248-111.003 248-248C504 119.083 392.957 8 256 8zm0 448c-110.532 0-200-89.431-200-200 0-110.495 89.472-200 200-200 110.491 0 200 89.471 200 200 0 110.53-89.431 200-200 200zm42-104c0 23.159-18.841 42-42 42s-42-18.841-42-42 18.841-42 42-42 42 18.841 42 42zm-81.37-211.401l6.8 136c.319 6.387 5.591 11.401 11.985 11.401h41.17c6.394 0 11.666-5.014 11.985-11.401l6.8-136c.343-6.854-5.122-12.599-11.985-12.599h-54.77c-6.863 0-12.328 5.745-11.985 12.599z"/></svg>

After

Width:  |  Height:  |  Size: 724 B

View File

@ -0,0 +1 @@
<svg aria-hidden="true" data-prefix="fas" data-icon="exclamation-circle" class="svg-inline--fa fa-exclamation-circle fa-w-16" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="#f1c40f" d="M504 256c0 136.997-111.043 248-248 248S8 392.997 8 256C8 119.083 119.043 8 256 8s248 111.083 248 248zm-248 50c-25.405 0-46 20.595-46 46s20.595 46 46 46 46-20.595 46-46-20.595-46-46-46zm-43.673-165.346l7.418 136c.347 6.364 5.609 11.346 11.982 11.346h48.546c6.373 0 11.635-4.982 11.982-11.346l7.418-136c.375-6.874-5.098-12.654-11.982-12.654h-63.383c-6.884 0-12.356 5.78-11.981 12.654z"/></svg>

After

Width:  |  Height:  |  Size: 598 B

View File

@ -168,6 +168,7 @@ WPMailSMTP.Admin.Settings = WPMailSMTP.Admin.Settings || ( function( document, w
} ); } );
app.triggerExitNotice(); app.triggerExitNotice();
app.beforeSaveChecks();
}, },
education: { education: {
@ -178,6 +179,7 @@ WPMailSMTP.Admin.Settings = WPMailSMTP.Admin.Settings || ( function( document, w
escapeKey: true, escapeKey: true,
animationBounce: 1, animationBounce: 1,
theme: 'modern', theme: 'modern',
type: 'blue',
animateFromElement: false, animateFromElement: false,
draggable: false, draggable: false,
closeIcon: true, closeIcon: true,
@ -263,6 +265,54 @@ WPMailSMTP.Admin.Settings = WPMailSMTP.Admin.Settings || ( function( document, w
$( 'form', $settingPages ).on( 'submit', function() { $( 'form', $settingPages ).on( 'submit', function() {
app.pluginSettingsChanged = false; app.pluginSettingsChanged = false;
} ); } );
},
/**
* Perform any checks before the settings are saved.
*
* Checks:
* - warn users if they try to save the settings with the default (PHP) mailer selected.
*
* @since 2.1.0
*/
beforeSaveChecks: function() {
$( 'form', app.pageHolder ).on( 'submit', function() {
if ( $( '.wp-mail-smtp-mailer input:checked', app.pageHolder ).val() === 'mail' ) {
var $thisForm = $( this );
$.alert( {
backgroundDismiss: false,
escapeKey: false,
animationBounce: 1,
theme: 'modern',
type: 'orange',
animateFromElement: false,
draggable: false,
closeIcon: false,
useBootstrap: false,
icon: '"></i><img src="' + wp_mail_smtp.plugin_url + '/assets/images/font-awesome/exclamation-circle-solid-orange.svg" style="width: 40px; height: 40px;" alt="' + wp_mail_smtp.default_mailer_notice.icon_alt + '"><i class="',
title: wp_mail_smtp.default_mailer_notice.title,
content: wp_mail_smtp.default_mailer_notice.content,
boxWidth: '550px',
buttons: {
confirm: {
text: wp_mail_smtp.default_mailer_notice.save_button,
btnClass: 'btn-confirm',
keys: [ 'enter' ],
action: function() {
$thisForm.off( 'submit' ).submit();
}
},
cancel: {
text: wp_mail_smtp.default_mailer_notice.cancel_button,
},
}
} );
return false;
}
} );
} }
}; };

File diff suppressed because one or more lines are too long

View File

@ -3,7 +3,7 @@ Contributors: wpforms, jaredatch, smub, slaFFik
Tags: smtp, wp mail smtp, wordpress smtp, gmail smtp, sendgrid smtp, mailgun smtp, mail, mailer, phpmailer, wp_mail, email, mailgun, sengrid, gmail, pepipost, sendinblue, wp smtp Tags: smtp, wp mail smtp, wordpress smtp, gmail smtp, sendgrid smtp, mailgun smtp, mail, mailer, phpmailer, wp_mail, email, mailgun, sengrid, gmail, pepipost, sendinblue, wp smtp
Requires at least: 4.9 Requires at least: 4.9
Tested up to: 5.4 Tested up to: 5.4
Stable tag: 2.0.1 Stable tag: 2.1.1
Requires PHP: 5.5.0 Requires PHP: 5.5.0
The most popular WordPress SMTP and PHP Mailer plugin. Trusted by over 1 million sites. The most popular WordPress SMTP and PHP Mailer plugin. Trusted by over 1 million sites.
@ -62,7 +62,7 @@ SMTP.com is a recommended transactional email service.
With over 22 years of email delivery expertise, SMTP.com has been around for almost as long as email itself. They are known among internet providers as one of the most reliable senders on the internet. With over 22 years of email delivery expertise, SMTP.com has been around for almost as long as email itself. They are known among internet providers as one of the most reliable senders on the internet.
Their easy integration process lets you start sending emails in minutes and benefit from years of experience. SMTP.com provides users 10,000 free emails the first 30 days. Their easy integration process lets you start sending emails in minutes and benefit from years of experience. SMTP.com provides users 50,000 free emails the first 30 days.
Read our <a href="https://wpmailsmtp.com/docs/how-to-set-up-the-smtp-com-mailer-in-wp-mail-smtp" rel="friend">SMTP.com documentation</a> for more details. Read our <a href="https://wpmailsmtp.com/docs/how-to-set-up-the-smtp-com-mailer-in-wp-mail-smtp" rel="friend">SMTP.com documentation</a> for more details.
@ -229,6 +229,24 @@ By all means please contact us to discuss features or options you'd like to see
== Changelog == == Changelog ==
= 2.1.1 - 2020-06-08 =
* Changed: Remove current automatic default reply-to address and add WP filter `wp_mail_smtp_processor_set_default_reply_to` for setting default reply-to addresses.
* Changed: Improve description for several options with links to an article about how to properly use constants.
* Fixed: PHP parse error connected to Monolog library on PHP versions < 7.x.
= 2.1.0 - 2020-06-04 =
* Added: Async/scheduled tasks management support.
* Added: New warning notification for selecting the "Default (none)" mailer and saving the plugin settings.
* Changed: Set the original From Email as Reply-To address if it was overwritten by the Force From Email option.
* Changed: The Force From Email option is now enabled by default, for new plugin installs.
* Changed: Reply-To header is now set when not provided, equals to From Name/Email.
* Fixed: Display a non-empty PHPMailer error when some non-SMTP mailers generate errors.
* Fixed: Display a more accurate message, when the "channel - not found" error is triggered by SMTP.com API.
* Fixed: Save and display debug errors for the "Other SMTP" mailer.
* Fixed: Improve the debug details for the "Invalid address (setFrom)" error in the Email Test tab.
* Fixed: Improve the debug details for SMTP CA verification fail, Gmail Guzzle requirements, and Gmail invalid grant errors.
* Fixed: Improve the uninstall cleanup procedure.
= 2.0.1 - 2020-05-07 = = 2.0.1 - 2020-05-07 =
* Changed: Improved description of the "Do Not Send" plugin option. * Changed: Improved description of the "Do Not Send" plugin option.
* Fixed: Due to Pepipost API changes we now convert new lines so they are preserved in plain text emails. * Fixed: Due to Pepipost API changes we now convert new lines so they are preserved in plain text emails.

View File

@ -13,20 +13,26 @@ use WPMailSMTP\Options;
class Area { class Area {
/** /**
* Slug of the admin area page.
*
* @since 1.0.0 * @since 1.0.0
* *
* @var string Slug of the admin area page. * @var string
*/ */
const SLUG = 'wp-mail-smtp'; const SLUG = 'wp-mail-smtp';
/** /**
* Admin page unique hook.
*
* @since 1.0.0 * @since 1.0.0
* *
* @var string Admin page unique hook. * @var string
*/ */
public $hook; public $hook;
/** /**
* List of admin area pages.
*
* @since 1.0.0 * @since 1.0.0
* *
* @var PageAbstract[] * @var PageAbstract[]
@ -34,11 +40,13 @@ class Area {
private $pages; private $pages;
/** /**
* List of official registered pages.
*
* @since 1.5.0 * @since 1.5.0
* *
* @var array List of official registered pages. * @var array
*/ */
public static $pages_registered = array( 'general', 'logs', 'about' ); public static $pages_registered = [ 'general', 'logs', 'about' ];
/** /**
* Area constructor. * Area constructor.
@ -46,6 +54,7 @@ class Area {
* @since 1.0.0 * @since 1.0.0
*/ */
public function __construct() { public function __construct() {
$this->hooks(); $this->hooks();
} }
@ -57,34 +66,39 @@ class Area {
protected function hooks() { protected function hooks() {
// Add the Settings link to a plugin on Plugins page. // Add the Settings link to a plugin on Plugins page.
add_filter( 'plugin_action_links_' . plugin_basename( WPMS_PLUGIN_FILE ), array( $this, 'add_plugin_action_link' ), 10, 1 ); add_filter( 'plugin_action_links_' . plugin_basename( WPMS_PLUGIN_FILE ), [ $this, 'add_plugin_action_link' ], 10, 1 );
// Add the options page. // Add the options page.
add_action( 'admin_menu', array( $this, 'add_admin_options_page' ) ); add_action( 'admin_menu', [ $this, 'add_admin_options_page' ] );
// Register on load Email Log admin menu hook.
add_action( 'load-wp-mail-smtp_page_wp-mail-smtp-logs', [ $this, 'maybe_redirect_email_log_menu_to_email_log_settings_tab' ] );
// Admin footer text. // Admin footer text.
add_filter( 'admin_footer_text', array( $this, 'get_admin_footer' ), 1, 2 ); add_filter( 'admin_footer_text', [ $this, 'get_admin_footer' ], 1, 2 );
// Enqueue admin area scripts and styles. // Enqueue admin area scripts and styles.
add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_assets' ) ); add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
// Process the admin page forms actions. // Process the admin page forms actions.
add_action( 'admin_init', array( $this, 'process_actions' ) ); add_action( 'admin_init', [ $this, 'process_actions' ] );
// Display custom notices based on the error/success codes. // Display custom notices based on the error/success codes.
add_action( 'admin_init', array( $this, 'display_custom_auth_notices' ) ); add_action( 'admin_init', [ $this, 'display_custom_auth_notices' ] );
// Display notice instructing the user to complete plugin setup. // Display notice instructing the user to complete plugin setup.
add_action( 'admin_init', array( $this, 'display_setup_notice' ) ); add_action( 'admin_init', [ $this, 'display_setup_notice' ] );
// Outputs the plugin admin header. // Outputs the plugin admin header.
add_action( 'in_admin_header', array( $this, 'display_admin_header' ), 100 ); add_action( 'in_admin_header', [ $this, 'display_admin_header' ], 100 );
// Hide all unrelated to the plugin notices on the plugin admin pages. // Hide all unrelated to the plugin notices on the plugin admin pages.
add_action( 'admin_print_scripts', array( $this, 'hide_unrelated_notices' ) ); add_action( 'admin_print_scripts', [ $this, 'hide_unrelated_notices' ] );
// Process all AJAX requests. // Process all AJAX requests.
add_action( 'wp_ajax_wp_mail_smtp_ajax', array( $this, 'process_ajax' ) ); add_action( 'wp_ajax_wp_mail_smtp_ajax', [ $this, 'process_ajax' ] );
( new Review() )->hooks();
} }
/** /**
@ -107,8 +121,7 @@ class Area {
switch ( $error ) { switch ( $error ) {
case 'google_access_denied': case 'google_access_denied':
WP::add_admin_notice( WP::add_admin_notice( /* translators: %s - error code, returned by Google API. */
/* translators: %s - error code, returned by Google API. */
sprintf( esc_html__( 'There was an error while processing the authentication request: %s. Please try again.', 'wp-mail-smtp' ), '<code>' . $error . '</code>' ), sprintf( esc_html__( 'There was an error while processing the authentication request: %s. Please try again.', 'wp-mail-smtp' ), '<code>' . $error . '</code>' ),
WP::ADMIN_NOTICE_ERROR WP::ADMIN_NOTICE_ERROR
); );
@ -169,15 +182,14 @@ class Area {
// Display notice informing user further action is needed. // Display notice informing user further action is needed.
WP::add_admin_notice( WP::add_admin_notice(
sprintf( sprintf(
wp_kses( wp_kses( /* translators: %s - Mailer anchor link. */
/* translators: %s - Mailer anchor link. */
__( 'Thanks for using WP Mail SMTP! To complete the plugin setup and start sending emails, <strong>please select and configure your <a href="%s">Mailer</a></strong>.', 'wp-mail-smtp' ), __( 'Thanks for using WP Mail SMTP! To complete the plugin setup and start sending emails, <strong>please select and configure your <a href="%s">Mailer</a></strong>.', 'wp-mail-smtp' ),
array( [
'a' => array( 'a' => [
'href' => array(), 'href' => [],
), ],
'strong' => array(), 'strong' => [],
) ]
), ),
wp_mail_smtp()->get_admin()->get_admin_page_url( self::SLUG . '#wp-mail-smtp-setting-row-mailer' ) wp_mail_smtp()->get_admin()->get_admin_page_url( self::SLUG . '#wp-mail-smtp-setting-row-mailer' )
), ),
@ -232,6 +244,26 @@ class Area {
} }
} }
/**
* Redirect the "Email Log" WP menu link to the "Email Log" setting tab for lite version of the plugin.
*
* @since 2.1.0
*/
public function maybe_redirect_email_log_menu_to_email_log_settings_tab() {
/**
* The Email Logs object to be used for loading the Email Log page.
*
* @var \WPMailSMTP\Admin\PageAbstract $logs
*/
$logs = $this->generate_display_logs_object();
if ( $logs instanceof \WPMailSMTP\Admin\Pages\Logs ) {
wp_safe_redirect( $logs->get_link() );
exit;
}
}
/** /**
* Enqueue admin area scripts and styles. * Enqueue admin area scripts and styles.
* *
@ -269,6 +301,19 @@ class Area {
array( array(
'text_provider_remove' => esc_html__( 'Are you sure you want to reset the current provider connection? You will need to immediately create a new one to be able to send emails.', 'wp-mail-smtp' ), 'text_provider_remove' => esc_html__( 'Are you sure you want to reset the current provider connection? You will need to immediately create a new one to be able to send emails.', 'wp-mail-smtp' ),
'text_settings_not_saved' => esc_html__( 'Changes that you made to the settings are not saved!', 'wp-mail-smtp' ), 'text_settings_not_saved' => esc_html__( 'Changes that you made to the settings are not saved!', 'wp-mail-smtp' ),
'default_mailer_notice' => array(
'title' => esc_html__( 'Heads up!', 'wp-mail-smtp' ),
'content' => wp_kses(
__( '<p>The Default (PHP) mailer is currently selected, but is not recommended because in most cases it does not resolve email delivery issues.</p><p>Please consider selecting and configuring one of the other mailers.</p>', 'wp-mail-smtp' ),
array(
'p' => true,
)
),
'save_button' => esc_html__( 'Save Settings', 'wp-mail-smtp' ),
'cancel_button' => esc_html__( 'Cancel', 'wp-mail-smtp' ),
'icon_alt' => esc_html__( 'Warning icon', 'wp-mail-smtp' ),
),
'plugin_url' => wp_mail_smtp()->plugin_url,
'education' => array( 'education' => array(
'upgrade_icon_lock' => '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="lock" class="svg-inline--fa fa-lock fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zm-104 0H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z"></path></svg>', 'upgrade_icon_lock' => '<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="lock" class="svg-inline--fa fa-lock fa-w-14" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zm-104 0H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z"></path></svg>',
'upgrade_title' => esc_html__( '%name% is a PRO Feature', 'wp-mail-smtp' ), 'upgrade_title' => esc_html__( '%name% is a PRO Feature', 'wp-mail-smtp' ),
@ -469,9 +514,12 @@ class Area {
break; break;
case self::SLUG . '-logs': case self::SLUG . '-logs':
$logs_class = apply_filters( 'wp_mail_smtp_admin_display_get_logs_fqcn', '\WPMailSMTP\Admin\Pages\Logs' ); /**
/** @var \WPMailSMTP\Admin\PageAbstract $logs */ * The Email Logs object to be used for loading the Email Log page.
$logs = new $logs_class(); *
* @var \WPMailSMTP\Admin\PageAbstract $logs
*/
$logs = $this->generate_display_logs_object();
$is_archive = wp_mail_smtp()->is_pro() && wp_mail_smtp()->pro->get_logs()->is_archive(); $is_archive = wp_mail_smtp()->is_pro() && wp_mail_smtp()->pro->get_logs()->is_archive();
?> ?>
@ -500,6 +548,20 @@ class Area {
<?php <?php
} }
/**
* Generate the appropriate Email Log page object used for displaying the Email Log page.
*
* @since 2.1.0
*
* @return \WPMailSMTP\Admin\PageAbstract
*/
public function generate_display_logs_object() {
$logs_class = apply_filters( 'wp_mail_smtp_admin_display_get_logs_fqcn', \WPMailSMTP\Admin\Pages\Logs::class );
return new $logs_class();
}
/** /**
* Display General page tabs. * Display General page tabs.
* *

View File

@ -1,124 +1,137 @@
<?php <?php
namespace WPMailSMTP\Admin\Pages; namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\PageAbstract; use WPMailSMTP\Admin\PageAbstract;
/** /**
* Class ControlTab is a placeholder for Pro Email Control tab settings. * Class ControlTab is a placeholder for Pro Email Control tab settings.
* Displays an upsell. * Displays an upsell.
* *
* @since 1.6.0 * @since 1.6.0
*/ */
class ControlTab extends PageAbstract { class ControlTab extends PageAbstract {
/** /**
* @since 1.6.0 * @since 1.6.0
* *
* @var string Slug of a tab. * @var string Slug of a tab.
*/ */
protected $slug = 'control'; protected $slug = 'control';
/** /**
* @inheritdoc * @inheritdoc
*/ */
public function get_label() { public function get_label() {
return esc_html__( 'Email Controls', 'wp-mail-smtp' ); return esc_html__( 'Email Controls', 'wp-mail-smtp' );
} }
/** /**
* @inheritdoc * @inheritdoc
*/ */
public function get_title() { public function get_title() {
return $this->get_label(); return $this->get_label();
} }
/** /**
* @inheritdoc * {@inheritdoc}
*/ *
public function display() { * @since 2.1.0 Replaced images with SVGs.
*/
$features = array( public function display() {
array(
'image' => 'comments.png', $features = [
'title' => esc_html__( 'Comment Notifications', 'wp-mail-smtp' ), [
'desc' => esc_html__( 'Manage emails sent when comments are published or awaiting moderation.', 'wp-mail-smtp' ), 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" focusable="false" viewBox="0 0 64 64"><path class="st0" d="M39.1,35.5H18l-9.2,6.9c-0.5,0.4-1.2,0.3-1.5-0.2c-0.1-0.2-0.2-0.4-0.2-0.6v-6c-3.9,0-7.1-3.2-7.1-7.1V10.7c0-3.9,3.2-7.1,7.1-7.1h32c3.9,0,7.1,3.2,7.1,7.1v17.8C46.2,32.4,43,35.5,39.1,35.5C39.1,35.5,39.1,35.5,39.1,35.5z"/><path class="st1" d="M64,28.4v17.8c0,3.9-3.2,7.1-7.1,7.1h-3.6v6c0,0.6-0.5,1.1-1.1,1.1c-0.2,0-0.5-0.1-0.6-0.2l-9.2-6.9h-14c-3.9,0-7.1-3.2-7.1-7.1v-7.1h17.8c5.9,0,10.7-4.8,10.7-10.7v-7.1h7.1C60.8,21.3,64,24.5,64,28.4z"/></svg>',
), 'title' => esc_html__( 'Comment Notifications', 'wp-mail-smtp' ),
array( 'desc' => esc_html__( 'Manage emails sent when comments are published or awaiting moderation.', 'wp-mail-smtp' ),
'image' => 'admin.png', ],
'title' => esc_html__( 'Site Admin Email Change Notifications', 'wp-mail-smtp' ), [
'desc' => esc_html__( 'Manage emails sent when site admin\'s account has been changed.', 'wp-mail-smtp' ), 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" focusable="false" viewBox="0 0 64 64"><path class="st0" d="M63.6 45.2l-2.6-1.5c0.3-1.4 0.3-2.9 0-4.3l2.6-1.5c0.3-0.2 0.4-0.5 0.3-0.9 -0.7-2.1-1.8-4.1-3.3-5.7 -0.2-0.3-0.6-0.3-0.9-0.1l-2.6 1.5c-1.1-0.9-2.3-1.7-3.7-2.1v-3c0-0.3-0.2-0.6-0.6-0.7 -2.2-0.5-4.4-0.5-6.6 0 -0.3 0.1-0.6 0.4-0.6 0.7v3c-1.4 0.5-2.6 1.2-3.7 2.1l-2.6-1.5c-0.3-0.2-0.7-0.1-0.9 0.1C37 33 35.9 35 35.2 37.1c-0.1 0.3 0 0.7 0.3 0.9l2.6 1.5c-0.3 1.4-0.3 2.9 0 4.3l-2.6 1.5c-0.3 0.2-0.4 0.5-0.3 0.9 0.7 2.1 1.8 4.1 3.3 5.7 0.2 0.3 0.6 0.3 0.9 0.1l2.6-1.5c1.1 0.9 2.3 1.7 3.7 2.1v3c0 0.3 0.2 0.6 0.6 0.7 2.2 0.5 4.4 0.5 6.6 0 0.3-0.1 0.6-0.4 0.6-0.7v-3c1.4-0.5 2.6-1.2 3.7-2.1l2.6 1.5c0.3 0.2 0.7 0.1 0.9-0.1 1.5-1.6 2.7-3.6 3.3-5.7C64.1 45.7 63.9 45.4 63.6 45.2zM49.6 46.5c-2.7 0-4.9-2.2-4.9-4.9s2.2-4.9 4.9-4.9c2.7 0 4.9 2.2 4.9 4.9S52.3 46.5 49.6 46.5z"/><path class="st1" d="M42.5 55.6v-0.9c-0.2-0.1-0.5-0.3-0.7-0.4l-0.8 0.5c-1.6 0.9-3.6 0.6-4.9-0.7 -1.8-2-3.2-4.4-4-7 -0.6-1.8 0.2-3.7 1.8-4.6l0.8-0.5c0-0.3 0-0.5 0-0.8L34 40.8c-1.6-0.9-2.3-2.8-1.8-4.6 0.1-0.3 0.2-0.6 0.3-0.9 -0.4 0-0.8-0.1-1.1-0.1h-1.7c-4.6 2.1-10 2.1-14.6 0h-1.7C6 35.2 0 41.2 0 48.6v4.2c0 2.7 2.2 4.8 4.8 4.8l0 0H40c1 0 1.9-0.3 2.7-0.9C42.6 56.4 42.5 56 42.5 55.6zM22.4 32c7.1 0 12.8-5.7 12.8-12.8S29.5 6.4 22.4 6.4 9.6 12.1 9.6 19.2 15.3 32 22.4 32z"/></svg>',
), 'title' => esc_html__( 'Site Admin Email Change Notifications', 'wp-mail-smtp' ),
array( 'desc' => esc_html__( 'Manage emails sent when site admin\'s account has been changed.', 'wp-mail-smtp' ),
'image' => 'users.png', ],
'title' => esc_html__( 'User Change Notifications', 'wp-mail-smtp' ), [
'desc' => esc_html__( 'Limit emails triggered by password changed/reset, email changed, and more.', 'wp-mail-smtp' ), 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" focusable="false" viewBox="0 0 64 64"><path class="st0" d="M9.6 28.8c3.5 0 6.4-2.9 6.4-6.4S13.1 16 9.6 16s-6.4 2.9-6.4 6.4S6.1 28.8 9.6 28.8zM57.6 32h-6.4c-1.7 0-3.3 0.7-4.5 1.9 4.1 2.2 6.9 6.3 7.5 10.9h6.6c1.8 0 3.2-1.4 3.2-3.2v-3.2C64 34.9 61.1 32 57.6 32zM6.4 32C2.9 32 0 34.9 0 38.4v3.2c0 1.8 1.4 3.2 3.2 3.2h6.6c0.6-4.6 3.4-8.7 7.5-10.9 -1.2-1.2-2.8-1.9-4.5-1.9H6.4zM54.4 28.8c3.5 0 6.4-2.9 6.4-6.4S57.9 16 54.4 16 48 18.9 48 22.4 50.9 28.8 54.4 28.8z"/><path class="st1" d="M39.7 35.2h-0.8c-2.1 1-4.5 1.6-6.8 1.6 -2.5 0-4.8-0.6-6.9-1.6h-0.8c-6.4 0-11.5 5.2-11.5 11.5v2.9c0 2.7 2.1 4.8 4.8 4.8h28.8c2.6 0 4.8-2.2 4.8-4.8v-2.9C51.2 40.4 46 35.2 39.7 35.2zM32 32c6.2 0 11.2-5 11.2-11.2S38.2 9.6 32 9.6s-11.2 5-11.2 11.2C20.8 27 25.8 32 32 32L32 32z"/></svg>',
), 'title' => esc_html__( 'User Change Notifications', 'wp-mail-smtp' ),
array( 'desc' => esc_html__( 'Limit emails triggered by password changed/reset, email changed, and more.', 'wp-mail-smtp' ),
'image' => 'personal.png', ],
'title' => esc_html__( 'Personal Data Requests Notifications', 'wp-mail-smtp' ), [
'desc' => esc_html__( 'Control emails for data requests and data removal actions.', 'wp-mail-smtp' ), 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" focusable="false" viewBox="0 0 64 64"><path class="st0" d="M35.9 52.6L32 60l-3.9-7.4L30 44l-2.2-4.5c2.8 0.6 5.7 0.6 8.5 0L34 44 35.9 52.6zM32 35.9c8.8 0 16-7.1 16-15.9 -0.9 0.2-1.9 0.4-3 0.5v0.8c0 0-0.8 0.4-0.9 0.8 -0.5 1.6-1 3.3-2.2 4.5 -1.4 1.3-6.5 3-8.7-3.4 -0.4-1.1-2.1-1.1-2.5 0 -2.3 6.8-7.6 4.4-8.7 3.4 -1.3-1.2-1.7-2.9-2.2-4.5 -0.1-0.3-0.9-0.8-0.9-0.8v-0.8c-1.1-0.2-2.1-0.3-3-0.5C16 28.8 23.2 35.9 32 35.9z"/><path class="st1" d="M19 20.5v0.8c0 0 0.8 0.5 0.9 0.8 0.5 1.6 1 3.3 2.2 4.5 1.1 1 6.4 3.4 8.7-3.4 0.4-1.1 2.1-1.1 2.5 0 2.2 6.4 7.3 4.7 8.7 3.4 1.3-1.2 1.7-2.9 2.2-4.5 0.1-0.4 0.9-0.8 0.9-0.8v-0.8c6.6-1 11-2.7 11-4.6 0-1.7-3.4-3.3-8.8-4.3 -1.2-4-3.3-8-5-10.1C41 0 39-0.4 37.2 0.4l-3.5 1.7c-1.1 0.6-2.5 0.6-3.6 0l-3.5-1.7C25-0.4 23 0 21.8 1.5c-1.7 2.1-3.8 6.1-5 10.1 -5.4 1-8.8 2.5-8.8 4.3C8 17.8 12.3 19.6 19 20.5zM52 38.5l3-7.8c0.4-1-0.1-2.2-1.2-2.6 -0.2-0.1-0.5-0.1-0.7-0.1h-4L32 60 14.9 27.9H11c-1.1 0-2 0.9-2 2 0 0.3 0.1 0.5 0.2 0.8l3.2 7.5c-5.2 3-8.4 8.5-8.4 14.5V58c0 3.3 2.7 6 6 6l0 0H54c3.3 0 6-2.7 6-6l0 0v-5.2C60.1 46.9 57 41.5 52 38.5L52 38.5z"/></svg>',
), 'title' => esc_html__( 'Personal Data Requests Notifications', 'wp-mail-smtp' ),
array( 'desc' => esc_html__( 'Control emails for data requests and data removal actions.', 'wp-mail-smtp' ),
'image' => 'update.png', ],
'title' => esc_html__( 'Automatic Update Notifications', 'wp-mail-smtp' ), [
'desc' => esc_html__( 'Manage emails sent by the core automatic update process.', 'wp-mail-smtp' ), 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" focusable="false" viewBox="0 0 64 64"><path class="st0" d="M0 57.6V40.3c0-1.7 1.4-3.1 3.1-3.1h17.3c2.8 0 4.1 3.3 2.2 5.3l-5.4 5.4c4 3.8 9.3 5.9 14.8 5.8 10 0 18.6-6.9 21-16.4 0.2-0.7 0.8-1.2 1.5-1.2h7.4c0.9 0 1.5 0.7 1.5 1.5 0 0.1 0 0.2 0 0.3C60.7 52.8 47.6 64 32 64c-8.2 0-16.2-3.2-22.1-8.9l-4.6 4.6C3.3 61.7 0 60.3 0 57.6z"/><path class="st1" d="M0.6 26C3.3 11.2 16.4 0 32 0c8.2 0 16.2 3.2 22.1 8.9l4.6-4.6C60.7 2.3 64 3.7 64 6.5v17.3c0 1.7-1.4 3.1-3.1 3.1H43.6c-2.8 0-4.1-3.3-2.2-5.3l5.4-5.4c-4-3.8-9.3-5.9-14.8-5.8 -10 0-18.6 6.9-21 16.4 -0.2 0.7-0.8 1.2-1.5 1.2H2.1c-0.9 0-1.5-0.7-1.5-1.5C0.5 26.2 0.5 26.1 0.6 26z"/></svg>',
), 'title' => esc_html__( 'Automatic Update Notifications', 'wp-mail-smtp' ),
array( 'desc' => esc_html__( 'Manage emails sent by the core automatic update process.', 'wp-mail-smtp' ),
'image' => 'user_new.png', ],
'title' => esc_html__( 'New User Notifications', 'wp-mail-smtp' ), [
'desc' => esc_html__( 'Toggle emails sent to both user and site administrator about new user accounts.', 'wp-mail-smtp' ), 'svg' => '<svg xmlns="http://www.w3.org/2000/svg" focusable="false" viewBox="0 0 64 64"><path class="st0" d="M64 28.8V32c0 0.9-0.7 1.6-1.6 1.6H56V40c0 0.9-0.7 1.6-1.6 1.6h-3.2c-0.9 0-1.6-0.7-1.6-1.6v-6.4h-6.4c-0.9 0-1.6-0.7-1.6-1.6v-3.2c0-0.9 0.7-1.6 1.6-1.6h6.4v-6.4c0-0.9 0.7-1.6 1.6-1.6h3.2c0.9 0 1.6 0.7 1.6 1.6v6.4h6.4C63.3 27.2 64 27.9 64 28.8z"/><path class="st1" d="M22.4 32c7.1 0 12.8-5.7 12.8-12.8S29.5 6.4 22.4 6.4 9.6 12.1 9.6 19.2 15.3 32 22.4 32zM31.4 35.2h-1.7c-4.6 2.1-9.9 2.1-14.6 0h-1.7C6 35.2 0 41.2 0 48.6v4.2c0 2.7 2.2 4.8 4.8 4.8l0 0H40c2.7 0 4.8-2.1 4.8-4.8l0 0v-4.2C44.8 41.2 38.8 35.2 31.4 35.2z"/></svg>',
), 'title' => esc_html__( 'New User Notifications', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Toggle emails sent to both user and site administrator about new user accounts.', 'wp-mail-smtp' ),
) ],
?> ];
<div class="wp-mail-smtp-page-upsell"> $allowed_svg_html = [
<h2><?php esc_html_e( 'Unlock Email Controls', 'wp-mail-smtp' ); ?></h2> 'svg' => [
'xmlns' => [],
<h3> 'focusable' => [],
<?php esc_html_e( 'Email Controls allows you to granularly manage emails sent by WordPress.', 'wp-mail-smtp' ); ?> 'viewbox' => [],
</h3> ],
'path' => [
<div class="wp-mail-smtp-page-upsell-content"> 'class' => [],
'd' => [],
<div class="wp-mail-smtp-page-upsell-features"> ],
<?php foreach ( $features as $feature ) : ?> ];
<div class="wp-mail-smtp-page-upsell-feature"> ?>
<div class="wp-mail-smtp-page-upsell-feature-image">
<img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/control/' . $feature['image'] ); ?>" alt=""> <div class="wp-mail-smtp-page-upsell">
</div> <h2><?php esc_html_e( 'Unlock Email Controls', 'wp-mail-smtp' ); ?></h2>
<div class="wp-mail-smtp-page-upsell-feature-content">
<h4><?php echo esc_html( $feature['title'] ); ?></h4> <h3>
<p><?php echo esc_html( $feature['desc'] ); ?></p> <?php esc_html_e( 'Email Controls allows you to granularly manage emails sent by WordPress.', 'wp-mail-smtp' ); ?>
</div> </h3>
</div>
<?php endforeach; ?> <div class="wp-mail-smtp-page-upsell-content">
</div>
<div class="wp-mail-smtp-page-upsell-features">
</div> <?php foreach ( $features as $feature ) : ?>
<div class="wp-mail-smtp-page-upsell-feature">
<div class="wp-mail-smtp-page-upsell-button"> <div class="wp-mail-smtp-page-upsell-feature-image">
<a href="https://wpmailsmtp.com/lite-upgrade/?discount=LITEUPGRADE&amp;utm_source=WordPress&amp;utm_medium=logs&amp;utm_campaign=liteplugin" <?php echo wp_kses( $feature['svg'], $allowed_svg_html ); ?>
class="wp-mail-smtp-btn wp-mail-smtp-btn-lg wp-mail-smtp-btn-orange" target="_blank" rel="noopener noreferrer"> </div>
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?> <div class="wp-mail-smtp-page-upsell-feature-content">
</a> <h4><?php echo esc_html( $feature['title'] ); ?></h4>
</div> <p><?php echo esc_html( $feature['desc'] ); ?></p>
</div>
</div> </div>
<?php endforeach; ?>
<?php </div>
}
</div>
/**
* Not used as we display an upsell. <div class="wp-mail-smtp-page-upsell-button">
* <a href="https://wpmailsmtp.com/lite-upgrade/?discount=LITEUPGRADE&amp;utm_source=WordPress&amp;utm_medium=logs&amp;utm_campaign=liteplugin"
* @since 1.6.0 class="wp-mail-smtp-btn wp-mail-smtp-btn-lg wp-mail-smtp-btn-orange" target="_blank" rel="noopener noreferrer">
* <?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
* @param array $data </a>
*/ </div>
public function process_post( $data ) {
} </div>
}
<?php
}
/**
* Not used as we display an upsell.
*
* @since 1.6.0
*
* @param array $data
*/
public function process_post( $data ) {
}
}

View File

@ -1,85 +1,69 @@
<?php <?php
namespace WPMailSMTP\Admin\Pages; namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\Area; use WPMailSMTP\Admin\Area;
use WPMailSMTP\Admin\PageAbstract; use WPMailSMTP\Admin\PageAbstract;
/** /**
* Class Logs * Class Logs
*/ *
class Logs extends PageAbstract { * @since 1.5.0
*/
/** class Logs extends PageAbstract {
* @since 1.5.0
* /**
* @var string Slug of a page. * Slug of a page.
*/ *
protected $slug = 'logs'; * @since 1.5.0
*
/** * @var string
* Get the page/tab link. */
* protected $slug = 'logs';
* @since 1.5.0
* /**
* @return string * Get the page/tab link.
*/ *
public function get_link() { * @since 1.5.0
* @since 2.1.0 Changed the URL to point to the email log settings tab.
return add_query_arg( *
'page', * @return string
Area::SLUG . '-' . $this->slug, */
admin_url( 'admin.php' ) public function get_link() {
);
} return add_query_arg(
'tab',
/** $this->slug,
* @inheritdoc admin_url( 'admin.php?page=' . Area::SLUG )
*/ );
public function get_label() { }
return esc_html__( 'Email Log', 'wp-mail-smtp' );
} /**
* Link label of a tab.
/** *
* @inheritdoc * @since 1.5.0
*/ *
public function get_title() { * @return string
return $this->get_label(); */
} public function get_label() {
return esc_html__( 'Email Log', 'wp-mail-smtp' );
/** }
* @inheritdoc
*/ /**
public function display() { * Title of a tab.
?> *
* @since 1.5.0
<div class="wp-mail-smtp-page-title"> *
<h1 class="page-title"> * @return string
<?php echo esc_html( $this->get_label() ); ?> */
</h1> public function get_title() {
</div> return $this->get_label();
}
<div class="wp-mail-smtp-page-upsell">
<h2><?php esc_html_e( 'Unlock Email Logging', 'wp-mail-smtp' ); ?></h2> /**
* Tab content.
<h3> *
<?php esc_html_e( 'Keep track of every email sent from your WordPress site with email logging.', 'wp-mail-smtp' ); ?><br> * @since 2.1.0 Moved the display content to the email log settings tab.
<?php esc_html_e( 'Troubleshoot sending issues, recover lost emails, and more!', 'wp-mail-smtp' ); ?> */
</h3> public function display() {}
}
<div class="wp-mail-smtp-page-upsell-images">
<img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/logs/archive.png' ); ?>" alt="<?php esc_attr_e( 'Logs Archive Page Screenshot', 'wp-mail-smtp' ); ?>">
<img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/logs/single.png' ); ?>" alt="<?php esc_attr_e( 'Logs Single Page Screenshot', 'wp-mail-smtp' ); ?>">
</div>
<div class="wp-mail-smtp-page-upsell-button">
<a href="https://wpmailsmtp.com/lite-upgrade/?discount=LITEUPGRADE&amp;utm_source=WordPress&amp;utm_medium=logs&amp;utm_campaign=liteplugin" class="wp-mail-smtp-btn wp-mail-smtp-btn-lg wp-mail-smtp-btn-orange wp-mail-smtp-upgrade-modal" target="_blank" rel="noopener noreferrer">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
</div>
<?php
}
}

View File

@ -1,73 +1,85 @@
<?php <?php
namespace WPMailSMTP\Admin\Pages; namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\Area; use WPMailSMTP\Admin\PageAbstract;
use WPMailSMTP\Admin\PageAbstract;
/**
/** * Class LogsTab is a placeholder for Lite users and redirects them to Email Log page.
* Class LogsTab is a placeholder for Lite users and redirects them to Email Log page. *
* * @since 1.6.0
* @since 1.6.0 */
*/ class LogsTab extends PageAbstract {
class LogsTab extends PageAbstract {
/**
/** * Part of the slug of a tab.
* Part of the slug of a tab. *
* * @since 1.6.0
* @since 1.6.0 *
* * @var string
* @var string */
*/ protected $slug = 'logs';
protected $slug = 'logs';
/**
/** * @inheritdoc
* @inheritdoc *
* * @since 1.6.0
* @since 1.6.0 */
*/ public function get_label() {
public function get_label() {
return esc_html__( 'Email Log', 'wp-mail-smtp' );
return esc_html__( 'Email Log', 'wp-mail-smtp' ); }
}
/**
/** * @inheritdoc
* @inheritdoc *
* * @since 1.6.0
* @since 1.6.0 */
*/ public function get_title() {
public function get_title() {
return $this->get_label();
return $this->get_label(); }
}
/**
/** * Display the upsell content for the Email Log feature.
* Custom URL for this tab, redirects to Email Log page. *
* * @since 1.6.0
* @since 1.6.0 * @since 2.1.0 Moved the display content from the email log page (WP admin menu "Email Log" page).
* */
* @return string public function display() {
*/ ?>
public function get_link() {
<div class="wp-mail-smtp-page-upsell">
return wp_mail_smtp()->get_admin()->get_admin_page_url( Area::SLUG . '-' . $this->slug ); <h2><?php esc_html_e( 'Unlock Email Logging', 'wp-mail-smtp' ); ?></h2>
}
<h3>
/** <?php esc_html_e( 'Keep track of every email sent from your WordPress site with email logging.', 'wp-mail-smtp' ); ?><br>
* Not used as we are simply redirecting users. <?php esc_html_e( 'Troubleshoot sending issues, recover lost emails, and more!', 'wp-mail-smtp' ); ?>
* </h3>
* @since 1.6.0
*/ <div class="wp-mail-smtp-page-upsell-images">
public function display() { <img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/logs/archive.png' ); ?>" alt="<?php esc_attr_e( 'Logs Archive Page Screenshot', 'wp-mail-smtp' ); ?>">
} <img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/logs/single.png' ); ?>" alt="<?php esc_attr_e( 'Logs Single Page Screenshot', 'wp-mail-smtp' ); ?>">
</div>
/**
* Not used as we are simply redirecting users. <div class="wp-mail-smtp-page-upsell-button">
* <a href="https://wpmailsmtp.com/lite-upgrade/?discount=LITEUPGRADE&amp;utm_source=WordPress&amp;utm_medium=logs&amp;utm_campaign=liteplugin" class="wp-mail-smtp-btn wp-mail-smtp-btn-lg wp-mail-smtp-btn-orange wp-mail-smtp-upgrade-modal" target="_blank" rel="noopener noreferrer">
* @since 1.6.0 <?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
* </a>
* @param array $data </div>
*/
public function process_post( $data ) { </div>
}
} <?php
}
/**
* Not used as we are simply redirecting users.
*
* @since 1.6.0
*
* @param array $data
*/
public function process_post( $data ) {
}
}

View File

@ -88,19 +88,22 @@ class MiscTab extends PageAbstract {
'<code>wp-config.php</code>' '<code>wp-config.php</code>'
); );
} else { } else {
printf( /* translators: %s - file to put that constant in. */ printf(
esc_html__( 'If you want to enable this option using constants, put the lines below to your %s file:', 'wp-mail-smtp' ), wp_kses( /* translators: %s - The URL to the constants support article. */
'<code>wp-config.php</code>' __( 'Please read this <a href="%s" target="_blank" rel="noopener noreferrer">support article</a> if you want to enable this option using constants.', 'wp-mail-smtp' ),
[
'a' => [
'href' => [],
'target' => [],
'rel' => [],
],
]
),
'https://wpmailsmtp.com/docs/how-to-secure-smtp-settings-by-using-constants/'
); );
} }
?> ?>
</p> </p>
<?php if ( ! $options->is_const_defined( 'general', 'do_not_send' ) ) : ?>
<pre>
define( 'WPMS_ON', true );
define( 'WPMS_DO_NOT_SEND', true );
</pre>
<?php endif; ?>
</div> </div>
</div> </div>

View File

@ -98,12 +98,12 @@ class TestTab extends PageAbstract {
$disabled = ''; $disabled = '';
$help_text = ''; $help_text = '';
if ( $mailer = wp_mail_smtp()->get_providers()->get_mailer(
! wp_mail_smtp()->get_providers()->get_mailer( Options::init()->get( 'mail', 'mailer' ),
Options::init()->get( 'mail', 'mailer' ), wp_mail_smtp()->get_processor()->get_phpmailer()
wp_mail_smtp()->get_processor()->get_phpmailer() );
)->is_mailer_complete()
) { if ( ! $mailer || ! $mailer->is_mailer_complete() ) {
$btn = 'wp-mail-smtp-btn-red'; $btn = 'wp-mail-smtp-btn-red';
$disabled = 'disabled'; $disabled = 'disabled';
@ -435,6 +435,18 @@ Lead Developer, WP Mail SMTP';
$mailer_text .= $mailer->get_debug_info(); $mailer_text .= $mailer->get_debug_info();
} }
$phpmailer_error = $phpmailer->ErrorInfo; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
// Append any PHPMailer errors to the mailer debug (except SMTP mailer, which has the full error output below).
if (
! empty( $phpmailer_error ) &&
! $options->is_mailer_smtp()
) {
$mailer_text .= '<br><br><strong>PHPMailer Debug:</strong><br>' .
wp_strip_all_tags( $phpmailer_error ) .
'<br>';
}
/* /*
* General Debug. * General Debug.
*/ */
@ -486,137 +498,163 @@ Lead Developer, WP Mail SMTP';
$smtp_port = $options->get( 'smtp', 'port' ); $smtp_port = $options->get( 'smtp', 'port' );
$smtp_encryption = $options->get( 'smtp', 'encryption' ); $smtp_encryption = $options->get( 'smtp', 'encryption' );
$details = array( $details = [
// [any] - cURL error 60/77. // [any] - cURL error 60/77.
array( [
'mailer' => 'any', 'mailer' => 'any',
'errors' => array( 'errors' => [
array( 'cURL error 60' ), [ 'cURL error 60' ],
array( 'cURL error 77' ), [ 'cURL error 77' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'SSL certificate issue.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'SSL certificate issue.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'This means your web server cannot reliably make secure connections (make requests to HTTPS sites).', 'wp-mail-smtp' ), esc_html__( 'This means your web server cannot reliably make secure connections (make requests to HTTPS sites).', 'wp-mail-smtp' ),
esc_html__( 'Typically this error is returned when web server is not configured properly.', 'wp-mail-smtp' ), esc_html__( 'Typically this error is returned when web server is not configured properly.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
esc_html__( 'Contact your web hosting provider and inform them your site has an issue with SSL certificates.', 'wp-mail-smtp' ), esc_html__( 'Contact your web hosting provider and inform them your site has an issue with SSL certificates.', 'wp-mail-smtp' ),
esc_html__( 'The exact error you can provide them is in the Error log, available at the bottom of this page.', 'wp-mail-smtp' ), esc_html__( 'The exact error you can provide them is in the Error log, available at the bottom of this page.', 'wp-mail-smtp' ),
esc_html__( 'Ask them to resolve the issue then try again.', 'wp-mail-smtp' ), esc_html__( 'Ask them to resolve the issue then try again.', 'wp-mail-smtp' ),
), ],
), ],
// [any] - cURL error 6/7. // [any] - cURL error 6/7.
array( [
'mailer' => 'any', 'mailer' => 'any',
'errors' => array( 'errors' => [
array( 'cURL error 6' ), [ 'cURL error 6' ],
array( 'cURL error 7' ), [ 'cURL error 7' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Could not connect to host.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Could not connect to host.', 'wp-mail-smtp' ) . '</strong>',
! empty( $smtp_host ) ! empty( $smtp_host )
? sprintf( ? sprintf( /* translators: %s - SMTP host address. */
/* translators: %s - SMTP host address. */
esc_html__( 'This means your web server was unable to connect to %s.', 'wp-mail-smtp' ), esc_html__( 'This means your web server was unable to connect to %s.', 'wp-mail-smtp' ),
$smtp_host $smtp_host
) )
: esc_html__( 'This means your web server was unable to connect to the host server.', 'wp-mail-smtp' ), : esc_html__( 'This means your web server was unable to connect to the host server.', 'wp-mail-smtp' ),
esc_html__( 'Typically this error is returned your web server is blocking the connections or the SMTP host denying the request.', 'wp-mail-smtp' ), esc_html__( 'Typically this error is returned your web server is blocking the connections or the SMTP host denying the request.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
sprintf( sprintf( /* translators: %s - SMTP host address. */
/* translators: %s - SMTP host address. */
esc_html__( 'Contact your web hosting provider and ask them to verify your server can connect to %s. Additionally, ask them if a firewall or security policy may be preventing the connection.', 'wp-mail-smtp' ), esc_html__( 'Contact your web hosting provider and ask them to verify your server can connect to %s. Additionally, ask them if a firewall or security policy may be preventing the connection.', 'wp-mail-smtp' ),
$smtp_host $smtp_host
), ),
esc_html__( 'If using "Other SMTP" Mailer, triple check your SMTP settings including host address, email, and password.', 'wp-mail-smtp' ), esc_html__( 'If using "Other SMTP" Mailer, triple check your SMTP settings including host address, email, and password.', 'wp-mail-smtp' ),
esc_html__( 'If using "Other SMTP" Mailer, contact your SMTP host to confirm they are accepting outside connections with the settings you have configured (address, username, port, security, etc).', 'wp-mail-smtp' ), esc_html__( 'If using "Other SMTP" Mailer, contact your SMTP host to confirm they are accepting outside connections with the settings you have configured (address, username, port, security, etc).', 'wp-mail-smtp' ),
), ],
), ],
// [any] - cURL error XX (other). // [any] - cURL error XX (other).
array( [
'mailer' => 'any', 'mailer' => 'any',
'errors' => array( 'errors' => [
array( 'cURL error' ), [ 'cURL error' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Could not connect to your host.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Could not connect to your host.', 'wp-mail-smtp' ) . '</strong>',
! empty( $smtp_host ) ! empty( $smtp_host )
? sprintf( ? sprintf( /* translators: %s - SMTP host address. */
/* translators: %s - SMTP host address. */
esc_html__( 'This means your web server was unable to connect to %s.', 'wp-mail-smtp' ), esc_html__( 'This means your web server was unable to connect to %s.', 'wp-mail-smtp' ),
$smtp_host $smtp_host
) )
: esc_html__( 'This means your web server was unable to connect to the host server.', 'wp-mail-smtp' ), : esc_html__( 'This means your web server was unable to connect to the host server.', 'wp-mail-smtp' ),
esc_html__( 'Typically this error is returned when web server is not configured properly.', 'wp-mail-smtp' ), esc_html__( 'Typically this error is returned when web server is not configured properly.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
esc_html__( 'Contact your web hosting provider and inform them you are having issues making outbound connections.', 'wp-mail-smtp' ), esc_html__( 'Contact your web hosting provider and inform them you are having issues making outbound connections.', 'wp-mail-smtp' ),
esc_html__( 'The exact error you can provide them is in the Error log, available at the bottom of this page.', 'wp-mail-smtp' ), esc_html__( 'The exact error you can provide them is in the Error log, available at the bottom of this page.', 'wp-mail-smtp' ),
esc_html__( 'Ask them to resolve the issue then try again.', 'wp-mail-smtp' ), esc_html__( 'Ask them to resolve the issue then try again.', 'wp-mail-smtp' ),
), ],
), ],
// [smtp] - SMTP Error: Count not authenticate. // [smtp] - SMTP Error: Count not authenticate.
array( [
'mailer' => 'smtp', 'mailer' => 'smtp',
'errors' => array( 'errors' => [
array( 'SMTP Error: Could not authenticate.' ), [ 'SMTP Error: Could not authenticate.' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Could not authenticate your SMTP account.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Could not authenticate your SMTP account.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'This means we were able to connect to your SMTP host, but were not able to proceed using the email/password in the settings.', 'wp-mail-smtp' ), esc_html__( 'This means we were able to connect to your SMTP host, but were not able to proceed using the email/password in the settings.', 'wp-mail-smtp' ),
esc_html__( 'Typically this error is returned when the email or password is not correct or is not what the SMTP host is expecting.', 'wp-mail-smtp' ), esc_html__( 'Typically this error is returned when the email or password is not correct or is not what the SMTP host is expecting.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
esc_html__( 'Triple check your SMTP settings including host address, email, and password. If you have recently reset your password you will need to update the settings.', 'wp-mail-smtp' ), esc_html__( 'Triple check your SMTP settings including host address, email, and password. If you have recently reset your password you will need to update the settings.', 'wp-mail-smtp' ),
esc_html__( 'Contact your SMTP host to confirm you are using the correct username and password.', 'wp-mail-smtp' ), esc_html__( 'Contact your SMTP host to confirm you are using the correct username and password.', 'wp-mail-smtp' ),
esc_html__( 'Verify with your SMTP host that your account has permissions to send emails using outside connections.', 'wp-mail-smtp' ), esc_html__( 'Verify with your SMTP host that your account has permissions to send emails using outside connections.', 'wp-mail-smtp' ),
), ],
), ],
// [smtp] - Sending bulk email, hitting rate limit. // [smtp] - Sending bulk email, hitting rate limit.
array( [
'mailer' => 'smtp', 'mailer' => 'smtp',
'errors' => array( 'errors' => [
array( 'We do not authorize the use of this system to transport unsolicited' ), [ 'We do not authorize the use of this system to transport unsolicited' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Error due to unsolicited and/or bulk e-mail.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Error due to unsolicited and/or bulk e-mail.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'This means the connection to your SMTP host was made successfully, but the host rejected the email.', 'wp-mail-smtp' ), esc_html__( 'This means the connection to your SMTP host was made successfully, but the host rejected the email.', 'wp-mail-smtp' ),
esc_html__( 'Typically this error is returned when you are sending too many e-mails or e-mails that have been identified as spam.', 'wp-mail-smtp' ), esc_html__( 'Typically this error is returned when you are sending too many e-mails or e-mails that have been identified as spam.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
esc_html__( 'Check the emails that are sending are sending individually. Example: email is not sending to 30 recipients. You can install any WordPress e-mail logging plugin to do that.', 'wp-mail-smtp' ), esc_html__( 'Check the emails that are sending are sending individually. Example: email is not sending to 30 recipients. You can install any WordPress e-mail logging plugin to do that.', 'wp-mail-smtp' ),
esc_html__( 'Contact your SMTP host to ask about sending/rate limits.', 'wp-mail-smtp' ), esc_html__( 'Contact your SMTP host to ask about sending/rate limits.', 'wp-mail-smtp' ),
esc_html__( 'Verify with them your SMTP account is in good standing and your account has not been flagged.', 'wp-mail-smtp' ), esc_html__( 'Verify with them your SMTP account is in good standing and your account has not been flagged.', 'wp-mail-smtp' ),
), ],
), ],
// [smtp] - Unauthenticated senders not allowed. // [smtp] - Unauthenticated senders not allowed.
array( [
'mailer' => 'smtp', 'mailer' => 'smtp',
'errors' => array( 'errors' => [
array( 'Unauthenticated senders not allowed' ), [ 'Unauthenticated senders not allowed' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Unauthenticated senders are not allowed.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Unauthenticated senders are not allowed.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'This means the connection to your SMTP host was made successfully, but you should enable Authentication and provide correct Username and Password.', 'wp-mail-smtp' ), esc_html__( 'This means the connection to your SMTP host was made successfully, but you should enable Authentication and provide correct Username and Password.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
esc_html__( 'Go to WP Mail SMTP plugin Settings page.', 'wp-mail-smtp' ), esc_html__( 'Go to WP Mail SMTP plugin Settings page.', 'wp-mail-smtp' ),
esc_html__( 'Enable Authentication', 'wp-mail-smtp' ), esc_html__( 'Enable Authentication', 'wp-mail-smtp' ),
esc_html__( 'Enter correct SMTP Username (usually this is an email address) and Password in the appropriate fields.', 'wp-mail-smtp' ), esc_html__( 'Enter correct SMTP Username (usually this is an email address) and Password in the appropriate fields.', 'wp-mail-smtp' ),
), ],
), ],
// [smtp] - SMTP connect() failed. // [smtp] - certificate verify failed.
array( // Has to be defined before "SMTP connect() failed" error, since this is a more specific error,
// which contains the "SMTP connect() failed" error message as well.
[
'mailer' => 'smtp', 'mailer' => 'smtp',
'errors' => array( 'errors' => [
array( 'SMTP connect() failed' ), [ 'certificate verify failed' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Misconfigured server certificate.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'This means OpenSSL on your server isn\'t able to verify the host certificate.', 'wp-mail-smtp' ),
esc_html__( 'There are a few reasons why this is happening. It could be that the host certificate is misconfigured, or this server\'s OpenSSL is using an outdated CA bundle.', 'wp-mail-smtp' ),
],
'steps' => [
esc_html__( 'Verify that the host\'s SSL certificate is valid.', 'wp-mail-smtp' ),
sprintf(
wp_kses( /* translators: %s - URL to the PHP openssl manual */
__( 'Contact your hosting support, show them the "full Error Log for debugging" below and share this <a href="%s" target="_blank" rel="noopener noreferrer">link</a> with them.', 'wp-mail-smtp' ),
[
'a' => [
'href' => [],
'target' => [],
'rel' => [],
],
]
),
'https://www.php.net/manual/en/migration56.openssl.php'
),
],
],
// [smtp] - SMTP connect() failed.
[
'mailer' => 'smtp',
'errors' => [
[ 'SMTP connect() failed' ],
],
'description' => [
'<strong>' . esc_html__( 'Could not connect to the SMTP host.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Could not connect to the SMTP host.', 'wp-mail-smtp' ) . '</strong>',
! empty( $smtp_host ) ! empty( $smtp_host )
? sprintf( ? sprintf( /* translators: %s - SMTP host address. */
/* translators: %s - SMTP host address. */
esc_html__( 'This means your web server was unable to connect to %s.', 'wp-mail-smtp' ), esc_html__( 'This means your web server was unable to connect to %s.', 'wp-mail-smtp' ),
$smtp_host $smtp_host
) )
@ -625,22 +663,21 @@ Lead Developer, WP Mail SMTP';
'-' . esc_html__( 'SMTP settings are incorrect (wrong port, security setting, incorrect host).', 'wp-mail-smtp' ) . '<br>' . '-' . esc_html__( 'SMTP settings are incorrect (wrong port, security setting, incorrect host).', 'wp-mail-smtp' ) . '<br>' .
'-' . esc_html__( 'Your web server is blocking the connection.', 'wp-mail-smtp' ) . '<br>' . '-' . esc_html__( 'Your web server is blocking the connection.', 'wp-mail-smtp' ) . '<br>' .
'-' . esc_html__( 'Your SMTP host is rejecting the connection.', 'wp-mail-smtp' ), '-' . esc_html__( 'Your SMTP host is rejecting the connection.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
esc_html__( 'Triple check your SMTP settings including host address, email, and password, port, and security.', 'wp-mail-smtp' ), esc_html__( 'Triple check your SMTP settings including host address, email, and password, port, and security.', 'wp-mail-smtp' ),
sprintf( sprintf(
wp_kses( wp_kses( /* translators: %1$s - SMTP host address, %2$s - SMTP port, %3$s - SMTP encryption. */
/* translators: %1$s - SMTP host address, %2$s - SMTP port, %3$s - SMTP encryption. */
__( 'Contact your web hosting provider and ask them to verify your server can connect to %1$s on port %2$s using %3$s encryption. Additionally, ask them if a firewall or security policy may be preventing the connection - many shared hosts block certain ports.<br><strong>Note: this is the most common cause of this issue.</strong>', 'wp-mail-smtp' ), __( 'Contact your web hosting provider and ask them to verify your server can connect to %1$s on port %2$s using %3$s encryption. Additionally, ask them if a firewall or security policy may be preventing the connection - many shared hosts block certain ports.<br><strong>Note: this is the most common cause of this issue.</strong>', 'wp-mail-smtp' ),
array( [
'a' => array( 'a' => [
'href' => array(), 'href' => [],
'rel' => array(), 'rel' => [],
'target' => array(), 'target' => [],
), ],
'strong' => array(), 'strong' => [],
'br' => array(), 'br' => [],
) ]
), ),
$smtp_host, $smtp_host,
$smtp_port, $smtp_port,
@ -648,281 +685,332 @@ Lead Developer, WP Mail SMTP';
), ),
esc_html__( 'Contact your SMTP host to confirm you are using the correct username and password.', 'wp-mail-smtp' ), esc_html__( 'Contact your SMTP host to confirm you are using the correct username and password.', 'wp-mail-smtp' ),
esc_html__( 'Verify with your SMTP host that your account has permissions to send emails using outside connections.', 'wp-mail-smtp' ), esc_html__( 'Verify with your SMTP host that your account has permissions to send emails using outside connections.', 'wp-mail-smtp' ),
), ],
), ],
// [mailgun] - Please activate your Mailgun account. // [mailgun] - Please activate your Mailgun account.
array( [
'mailer' => 'mailgun', 'mailer' => 'mailgun',
'errors' => array( 'errors' => [
array( 'Please activate your Mailgun account' ), [ 'Please activate your Mailgun account' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Mailgun failed.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Mailgun failed.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'It seems that you forgot to activate your Mailgun account.', 'wp-mail-smtp' ), esc_html__( 'It seems that you forgot to activate your Mailgun account.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
esc_html__( 'Check your inbox you used to create a Mailgun account. Click the activation link in an email from Mailgun.', 'wp-mail-smtp' ), esc_html__( 'Check your inbox you used to create a Mailgun account. Click the activation link in an email from Mailgun.', 'wp-mail-smtp' ),
esc_html__( 'If you do not see activation email, go to your Mailgun control panel and resend the activation email.', 'wp-mail-smtp' ), esc_html__( 'If you do not see activation email, go to your Mailgun control panel and resend the activation email.', 'wp-mail-smtp' ),
), ],
), ],
// [mailgun] - Forbidden. // [mailgun] - Forbidden.
array( [
'mailer' => 'mailgun', 'mailer' => 'mailgun',
'errors' => array( 'errors' => [
array( 'Forbidden' ), [ 'Forbidden' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Mailgun failed.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Mailgun failed.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'Typically this error is because there is an issue with your Mailgun settings, in many cases the API key.', 'wp-mail-smtp' ), esc_html__( 'Typically this error is because there is an issue with your Mailgun settings, in many cases the API key.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
esc_html__( 'Verify your API key is correct.', 'wp-mail-smtp' ), esc_html__( 'Verify your API key is correct.', 'wp-mail-smtp' ),
esc_html__( 'Go to your Mailgun account and view your API key.', 'wp-mail-smtp' ), esc_html__( 'Go to your Mailgun account and view your API key.', 'wp-mail-smtp' ),
esc_html__( 'Note that the API key includes the "key" prefix, so make sure that it is in the WP Mail SMTP Mailgun API setting.', 'wp-mail-smtp' ), esc_html__( 'Note that the API key includes the "key" prefix, so make sure that it is in the WP Mail SMTP Mailgun API setting.', 'wp-mail-smtp' ),
), ],
), ],
// [mailgun] - Free accounts are for test purposes only. // [mailgun] - Free accounts are for test purposes only.
array( [
'mailer' => 'mailgun', 'mailer' => 'mailgun',
'errors' => array( 'errors' => [
array( 'Free accounts are for test purposes only' ), [ 'Free accounts are for test purposes only' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Mailgun failed.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Mailgun failed.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'Your Mailgun account does not have access to send emails.', 'wp-mail-smtp' ), esc_html__( 'Your Mailgun account does not have access to send emails.', 'wp-mail-smtp' ),
esc_html__( 'Typically this error is because you have not set up and/or complete domain name verification for your Mailgun account.', 'wp-mail-smtp' ), esc_html__( 'Typically this error is because you have not set up and/or complete domain name verification for your Mailgun account.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
sprintf( sprintf(
wp_kses( wp_kses( /* translators: %s - Mailgun documentation URL. */
/* translators: %s - Mailgun documentation URL. */
__( 'Go to our how-to guide for setting up <a href="%s" target="_blank" rel="noopener noreferrer">Mailgun with WP Mail SMTP</a>.', 'wp-mail-smtp' ), __( 'Go to our how-to guide for setting up <a href="%s" target="_blank" rel="noopener noreferrer">Mailgun with WP Mail SMTP</a>.', 'wp-mail-smtp' ),
array( [
'a' => array( 'a' => [
'href' => array(), 'href' => [],
'rel' => array(), 'rel' => [],
'target' => array(), 'target' => [],
), ],
) ]
), ),
'https://wpmailsmtp.com/docs/how-to-set-up-the-mailgun-mailer-in-wp-mail-smtp/' 'https://wpmailsmtp.com/docs/how-to-set-up-the-mailgun-mailer-in-wp-mail-smtp/'
), ),
esc_html__( 'Complete the steps in section "2. Verify Your Domain".', 'wp-mail-smtp' ), esc_html__( 'Complete the steps in section "2. Verify Your Domain".', 'wp-mail-smtp' ),
), ],
), ],
// [gmail] - 401: Login Required. // [gmail] - 401: Login Required.
array( [
'mailer' => 'gmail', 'mailer' => 'gmail',
'errors' => array( 'errors' => [
array( '401', 'Login Required' ), [ '401', 'Login Required' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'You have not properly configured Gmail mailer.', 'wp-mail-smtp' ), esc_html__( 'You have not properly configured Gmail mailer.', 'wp-mail-smtp' ),
esc_html__( 'Make sure that you have clicked the "Allow plugin to send emails using your Google account" button under Gmail settings.', 'wp-mail-smtp' ), esc_html__( 'Make sure that you have clicked the "Allow plugin to send emails using your Google account" button under Gmail settings.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
esc_html__( 'Go to plugin Settings page and click the "Allow plugin to send emails using your Google account" button.', 'wp-mail-smtp' ), esc_html__( 'Go to plugin Settings page and click the "Allow plugin to send emails using your Google account" button.', 'wp-mail-smtp' ),
esc_html__( 'After the click you should be redirected to a Gmail authorization screen, where you will be asked a permission to send emails on your behalf.', 'wp-mail-smtp' ), esc_html__( 'After the click you should be redirected to a Gmail authorization screen, where you will be asked a permission to send emails on your behalf.', 'wp-mail-smtp' ),
esc_html__( 'Please click "Agree", if you see that button. If not - you will need to enable less secure apps first:', 'wp-mail-smtp' ) esc_html__( 'Please click "Agree", if you see that button. If not - you will need to enable less secure apps first:', 'wp-mail-smtp' )
. '<ul>' . '<ul>'
. '<li>' . . '<li>' .
sprintf( sprintf(
wp_kses( wp_kses( /* translators: %s - Google support article URL. */
/* translators: %s - Google support article URL. */
__( 'if you are using regular Gmail account, please <a href="%s" target="_blank" rel="noopener noreferrer">read this article</a> to proceed.', 'wp-mail-smtp' ), __( 'if you are using regular Gmail account, please <a href="%s" target="_blank" rel="noopener noreferrer">read this article</a> to proceed.', 'wp-mail-smtp' ),
array( [
'a' => array( 'a' => [
'href' => array(), 'href' => [],
'target' => array(), 'target' => [],
'rel' => array(), 'rel' => [],
), ],
) ]
), ),
'https://support.google.com/accounts/answer/6010255?hl=en' 'https://support.google.com/accounts/answer/6010255?hl=en'
) )
. '</li>' . '</li>'
. '<li>' . . '<li>' .
sprintf( sprintf(
wp_kses( wp_kses( /* translators: %s - Google support article URL. */
/* translators: %s - Google support article URL. */
__( 'if you are using G Suite, please <a href="%s" target="_blank" rel="noopener noreferrer">read this article</a> to proceed.', 'wp-mail-smtp' ), __( 'if you are using G Suite, please <a href="%s" target="_blank" rel="noopener noreferrer">read this article</a> to proceed.', 'wp-mail-smtp' ),
array( [
'a' => array( 'a' => [
'href' => array(), 'href' => [],
'target' => array(), 'target' => [],
'rel' => array(), 'rel' => [],
), ],
) ]
), ),
'https://support.google.com/cloudidentity/answer/6260879?hl=en' 'https://support.google.com/cloudidentity/answer/6260879?hl=en'
) )
. '</li>' . '</li>'
. '</ul>', . '</ul>',
), ],
), ],
// [gmail] - 400: Recipient address required. // [gmail] - 400: Recipient address required.
array( [
'mailer' => 'gmail', 'mailer' => 'gmail',
'errors' => array( 'errors' => [
array( '400', 'Recipient address required' ), [ '400', 'Recipient address required' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'Typically this error is because address the email was sent to is invalid or was empty.', 'wp-mail-smtp' ), esc_html__( 'Typically this error is because address the email was sent to is invalid or was empty.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
esc_html__( 'Check the "Send To" email address used and confirm it is a valid email and was not empty.', 'wp-mail-smtp' ), esc_html__( 'Check the "Send To" email address used and confirm it is a valid email and was not empty.', 'wp-mail-smtp' ),
sprintf( sprintf( /* translators: 1 - correct email address example. 2 - incorrect email address example. */
/* translators: 1 - correct email address example. 2 - incorrect email address example. */
esc_html__( 'It should be something like this: %1$s. These are incorrect values: %2$s.', 'wp-mail-smtp' ), esc_html__( 'It should be something like this: %1$s. These are incorrect values: %2$s.', 'wp-mail-smtp' ),
'<code>info@example.com</code>', '<code>info@example.com</code>',
'<code>info@localhost</code>, <code>info@192.168.1.1</code>' '<code>info@localhost</code>, <code>info@192.168.1.1</code>'
), ),
esc_html__( 'Make sure that the generated email has a TO header, useful when you are responsible for email creation.', 'wp-mail-smtp' ), esc_html__( 'Make sure that the generated email has a TO header, useful when you are responsible for email creation.', 'wp-mail-smtp' ),
), ],
), ],
// [gmail] - Token has been expired or revoked. // [gmail] - Token has been expired or revoked.
array( [
'mailer' => 'gmail', 'mailer' => 'gmail',
'errors' => array( 'errors' => [
array( 'invalid_grant', 'Token has been expired or revoked' ), [ 'invalid_grant', 'Token has been expired or revoked' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'Unfortunately, this error can be due to many different reasons.', 'wp-mail-smtp' ), esc_html__( 'Unfortunately, this error can be due to many different reasons.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
sprintf( sprintf(
wp_kses( wp_kses( /* translators: %s - Blog article URL. */
/* translators: %s - Blog article URL. */
__( 'Please <a href="%s" target="_blank" rel="noopener noreferrer">read this article</a> to learn more about what can cause this error and how it can be resolved.', 'wp-mail-smtp' ), __( 'Please <a href="%s" target="_blank" rel="noopener noreferrer">read this article</a> to learn more about what can cause this error and how it can be resolved.', 'wp-mail-smtp' ),
array( [
'a' => array( 'a' => [
'href' => array(), 'href' => [],
'target' => array(), 'target' => [],
'rel' => array(), 'rel' => [],
), ],
) ]
), ),
'https://blog.timekit.io/google-oauth-invalid-grant-nightmare-and-how-to-fix-it-9f4efaf1da35' 'https://blog.timekit.io/google-oauth-invalid-grant-nightmare-and-how-to-fix-it-9f4efaf1da35'
), ),
), ],
), ],
// [gmail] - Code was already redeemed. // [gmail] - Code was already redeemed.
array( [
'mailer' => 'gmail', 'mailer' => 'gmail',
'errors' => array( 'errors' => [
array( 'invalid_grant', 'Code was already redeemed' ), [ 'invalid_grant', 'Code was already redeemed' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'Authentication code that Google returned to you has already been used on your previous auth attempt.', 'wp-mail-smtp' ), esc_html__( 'Authentication code that Google returned to you has already been used on your previous auth attempt.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
esc_html__( 'Make sure that you are not trying to manually clean up the plugin options to retry the "Allow..." step.', 'wp-mail-smtp' ), esc_html__( 'Make sure that you are not trying to manually clean up the plugin options to retry the "Allow..." step.', 'wp-mail-smtp' ),
esc_html__( 'Reinstall the plugin with clean plugin data turned on on Misc page. This will remove all the plugin options and you will be safe to retry.', 'wp-mail-smtp' ), esc_html__( 'Reinstall the plugin with clean plugin data turned on on Misc page. This will remove all the plugin options and you will be safe to retry.', 'wp-mail-smtp' ),
esc_html__( 'Make sure there is no aggressive caching on site admin area pages or try to clean cache between attempts.', 'wp-mail-smtp' ), esc_html__( 'Make sure there is no aggressive caching on site admin area pages or try to clean cache between attempts.', 'wp-mail-smtp' ),
), ],
), ],
// [gmail] - 400: Mail service not enabled. // [gmail] - 400: Mail service not enabled.
array( [
'mailer' => 'gmail', 'mailer' => 'gmail',
'errors' => array( 'errors' => [
array( '400', 'Mail service not enabled' ), [ '400', 'Mail service not enabled' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'There are various reasons for that, please review the steps below.', 'wp-mail-smtp' ), esc_html__( 'There are various reasons for that, please review the steps below.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
sprintf( sprintf(
wp_kses( wp_kses( /* translators: %s - Google G Suite Admin area URL. */
/* translators: %s - Google G Suite Admin area URL. */
__( 'Make sure that your G Suite trial period has not expired. You can check the status <a href="%s" target="_blank" rel="noopener noreferrer">here</a>.', 'wp-mail-smtp' ), __( 'Make sure that your G Suite trial period has not expired. You can check the status <a href="%s" target="_blank" rel="noopener noreferrer">here</a>.', 'wp-mail-smtp' ),
array( [
'a' => array( 'a' => [
'href' => array(), 'href' => [],
'rel' => array(), 'rel' => [],
'target' => array(), 'target' => [],
), ],
) ]
), ),
'https://admin.google.com' 'https://admin.google.com'
), ),
sprintf( sprintf(
wp_kses( wp_kses( /* translators: %s - Google G Suite Admin area URL. */
/* translators: %s - Google G Suite Admin area URL. */
__( 'Make sure that Gmail app in your G Suite is actually enabled. You can check that in Apps list in <a href="%s" target="_blank" rel="noopener noreferrer">G Suite Admin</a> area.', 'wp-mail-smtp' ), __( 'Make sure that Gmail app in your G Suite is actually enabled. You can check that in Apps list in <a href="%s" target="_blank" rel="noopener noreferrer">G Suite Admin</a> area.', 'wp-mail-smtp' ),
array( [
'a' => array( 'a' => [
'href' => array(), 'href' => [],
'rel' => array(), 'rel' => [],
'target' => array(), 'target' => [],
), ],
) ]
), ),
'https://admin.google.com' 'https://admin.google.com'
), ),
sprintf( sprintf(
wp_kses( wp_kses( /* translators: %s - Google Developers Console URL. */
/* translators: %s - Google Developers Console URL. */
__( 'Make sure that you have Gmail API enabled, and you can do that <a href="%s" target="_blank" rel="noopener noreferrer">here</a>.', 'wp-mail-smtp' ), __( 'Make sure that you have Gmail API enabled, and you can do that <a href="%s" target="_blank" rel="noopener noreferrer">here</a>.', 'wp-mail-smtp' ),
array( [
'a' => array( 'a' => [
'href' => array(), 'href' => [],
'rel' => array(), 'rel' => [],
'target' => array(), 'target' => [],
), ],
) ]
), ),
'https://console.developers.google.com/' 'https://console.developers.google.com/'
), ),
), ],
), ],
// [gmail] - 403: Project X is not found and cannot be used for API calls. // [gmail] - 403: Project X is not found and cannot be used for API calls.
array( [
'mailer' => 'gmail', 'mailer' => 'gmail',
'errors' => array( 'errors' => [
array( '403', 'is not found and cannot be used for API calls' ), [ '403', 'is not found and cannot be used for API calls' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
), ],
'steps' => array( 'steps' => [
esc_html__( 'Make sure that the used Client ID/Secret correspond to a proper project that has Gmail API enabled.', 'wp-mail-smtp' ), esc_html__( 'Make sure that the used Client ID/Secret correspond to a proper project that has Gmail API enabled.', 'wp-mail-smtp' ),
sprintf( sprintf(
wp_kses( wp_kses( /* translators: %s - Gmail documentation URL. */
/* translators: %s - Gmail documentation URL. */
esc_html__( 'Please follow our <a href="%s" target="_blank" rel="noopener noreferrer">Gmail tutorial</a> to be sure that all the correct project and data is applied.', 'wp-mail-smtp' ), esc_html__( 'Please follow our <a href="%s" target="_blank" rel="noopener noreferrer">Gmail tutorial</a> to be sure that all the correct project and data is applied.', 'wp-mail-smtp' ),
array( [
'a' => array( 'a' => [
'href' => array(), 'href' => [],
'rel' => array(), 'rel' => [],
'target' => array(), 'target' => [],
), ],
) ]
), ),
'https://wpmailsmtp.com/docs/how-to-set-up-the-gmail-mailer-in-wp-mail-smtp/' 'https://wpmailsmtp.com/docs/how-to-set-up-the-gmail-mailer-in-wp-mail-smtp/'
), ),
), ],
), ],
// [gmail] - The OAuth client was disabled. // [gmail] - The OAuth client was disabled.
array( [
'mailer' => 'gmail', 'mailer' => 'gmail',
'errors' => array( 'errors' => [
array( 'disabled_client', 'The OAuth client was disabled' ), [ 'disabled_client', 'The OAuth client was disabled' ],
), ],
'description' => array( 'description' => [
'<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'Google API Error.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'You may have added a new API to a project', 'wp-mail-smtp' ), esc_html__( 'You may have added a new API to a project', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
esc_html__( 'Make sure that the used Client ID/Secret correspond to a proper project that has Gmail API enabled.', 'wp-mail-smtp' ), esc_html__( 'Make sure that the used Client ID/Secret correspond to a proper project that has Gmail API enabled.', 'wp-mail-smtp' ),
esc_html__( 'Try to use a separate project for your emails, so the project has only 1 Gmail API in it enabled. You will need to remove the old project and create a new one from scratch.', 'wp-mail-smtp' ), esc_html__( 'Try to use a separate project for your emails, so the project has only 1 Gmail API in it enabled. You will need to remove the old project and create a new one from scratch.', 'wp-mail-smtp' ),
), ],
), ],
); // [SMTP.com] - The "channel - not found" issue.
[
'mailer' => 'smtpcom',
'errors' => [
[ 'channel - not found' ],
],
'description' => [
'<strong>' . esc_html__( 'SMTP.com API Error.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'Your Sender Name option is incorrect.', 'wp-mail-smtp' ),
],
'steps' => [
esc_html__( 'Please make sure you entered an accurate Sender Name in WP Mail SMTP plugin settings.', 'wp-mail-smtp' ),
],
],
// [gmail] - GuzzleHttp requires cURL, the allow_url_fopen ini setting, or a custom HTTP handler.
[
'mailer' => 'gmail',
'errors' => [
[ 'GuzzleHttp requires cURL, the allow_url_fopen ini setting, or a custom HTTP handler' ],
],
'description' => [
'<strong>' . esc_html__( 'GuzzleHttp requirements.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'GuzzleHttp requires cURL, the allow_url_fopen ini setting, or a custom HTTP handler.', 'wp-mail-smtp' ),
],
'steps' => [
esc_html__( 'Edit your php.ini file on your hosting server.', 'wp-mail-smtp' ),
esc_html__( '(Recommended) Enable PHP extension: cURL, by adding "extension=curl" to the php.ini file (without the quotation marks) OR', 'wp-mail-smtp' ),
esc_html__( '(If cURL can\'t be enabled on your hosting server) Enable PHP setting: allow_url_fopen, by adding "allow_url_fopen = On" to the php.ini file (without the quotation marks)', 'wp-mail-smtp' ),
esc_html__( 'If you don\'t know how to do the above we strongly suggest contacting your hosting support and provide them the "full Error Log for debugging" below and these steps. They should be able to fix this issue for you.', 'wp-mail-smtp' ),
],
],
];
/**
* [any] - PHP 7.4.x and PCRE library issues.
*
* @see https://wordpress.org/support/topic/cant-send-emails-using-php-7-4/
*/
if (
version_compare( phpversion(), '7.4', '>=' ) &&
defined( 'PCRE_VERSION' ) &&
version_compare( PCRE_VERSION, '10.0', '>' ) &&
version_compare( PCRE_VERSION, '10.32', '<=' )
) {
$details[] = [
'mailer' => 'any',
'errors' => [
[ 'Invalid address: (setFrom)' ],
],
'description' => [
'<strong>' . esc_html__( 'PCRE library issue', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'It looks like your server is running PHP version 7.4.x with an outdated PCRE library (libpcre2) that has a known issue with email address validation.', 'wp-mail-smtp' ),
esc_html__( 'There is a known issue with PHP version 7.4.x, when using libpcre2 library version lower than 10.33.', 'wp-mail-smtp' ),
],
'steps' => [
esc_html__( 'Contact your web hosting provider and inform them you are having issues with libpcre2 library on PHP 7.4.', 'wp-mail-smtp' ),
esc_html__( 'They should be able to resolve this issue for you.', 'wp-mail-smtp' ),
esc_html__( 'For a quick fix, until your web hosting resolves this, you can downgrade to PHP version 7.3 on your server.', 'wp-mail-smtp' ),
],
];
}
// Error detection logic. // Error detection logic.
foreach ( $details as $data ) { foreach ( $details as $data ) {
@ -953,27 +1041,27 @@ Lead Developer, WP Mail SMTP';
} }
// Return defaults. // Return defaults.
return array( return [
'description' => array( 'description' => [
'<strong>' . esc_html__( 'An issue was detected.', 'wp-mail-smtp' ) . '</strong>', '<strong>' . esc_html__( 'An issue was detected.', 'wp-mail-smtp' ) . '</strong>',
esc_html__( 'This means your test email was unable to be sent.', 'wp-mail-smtp' ), esc_html__( 'This means your test email was unable to be sent.', 'wp-mail-smtp' ),
esc_html__( 'Typically this error is returned for one of the following reasons:', 'wp-mail-smtp' ), esc_html__( 'Typically this error is returned for one of the following reasons:', 'wp-mail-smtp' ),
'- ' . esc_html__( 'Plugin settings are incorrect (wrong SMTP settings, invalid Mailer configuration, etc).', 'wp-mail-smtp' ) . '<br>' . '- ' . esc_html__( 'Plugin settings are incorrect (wrong SMTP settings, invalid Mailer configuration, etc).', 'wp-mail-smtp' ) . '<br>' .
'- ' . esc_html__( 'Your web server is blocking the connection.', 'wp-mail-smtp' ) . '<br>' . '- ' . esc_html__( 'Your web server is blocking the connection.', 'wp-mail-smtp' ) . '<br>' .
'- ' . esc_html__( 'Your host is rejecting the connection.', 'wp-mail-smtp' ), '- ' . esc_html__( 'Your host is rejecting the connection.', 'wp-mail-smtp' ),
), ],
'steps' => array( 'steps' => [
esc_html__( 'Triple check the plugin settings, consider reconfiguring to make sure everything is correct (eg bad copy and paste).', 'wp-mail-smtp' ), esc_html__( 'Triple check the plugin settings, consider reconfiguring to make sure everything is correct (eg bad copy and paste).', 'wp-mail-smtp' ),
wp_kses( wp_kses(
__( 'Contact your web hosting provider and ask them to verify your server can make outside connections. Additionally, ask them if a firewall or security policy may be preventing the connection - many shared hosts block certain ports.<br><strong>Note: this is the most common cause of this issue.</strong>', 'wp-mail-smtp' ), __( 'Contact your web hosting provider and ask them to verify your server can make outside connections. Additionally, ask them if a firewall or security policy may be preventing the connection - many shared hosts block certain ports.<br><strong>Note: this is the most common cause of this issue.</strong>', 'wp-mail-smtp' ),
array( [
'strong' => array(), 'strong' => [],
'br' => array(), 'br' => [],
) ]
), ),
esc_html__( 'Try using a different mailer.', 'wp-mail-smtp' ), esc_html__( 'Try using a different mailer.', 'wp-mail-smtp' ),
), ],
); ];
} }
/** /**

View File

@ -0,0 +1,203 @@
<?php
namespace WPMailSMTP\Admin;
use WPMailSMTP\Options;
/**
* Class for admin notice requesting plugin review.
*
* @since 2.1.0
*/
class Review {
/**
* The name of the WP option for the review notice data.
*
* Data attributes:
* - time
* - dismissed
*
* @since 2.1.0
*/
const NOTICE_OPTION = 'wp_mail_smtp_review_notice';
/**
* Days the plugin waits before displaying a review request.
*
* @since 2.1.0
*/
const WAIT_PERIOD = 14;
/**
* Initialize hooks.
*
* @since 2.1.0
*/
public function hooks() {
add_action( 'admin_notices', array( $this, 'review_request' ) );
add_action( 'wp_ajax_wp_mail_smtp_review_dismiss', array( $this, 'review_dismiss' ) );
}
/**
* Add admin notices as needed for reviews.
*
* @since 2.1.0
*/
public function review_request() {
// Only consider showing the review request to admin users.
if ( ! is_super_admin() ) {
return;
}
// Verify that we can do a check for reviews.
$review = get_option( self::NOTICE_OPTION );
$time = time();
$load = false;
if ( empty( $review ) ) {
$review = [
'time' => $time,
'dismissed' => false,
];
update_option( self::NOTICE_OPTION, $review );
} else {
// Check if it has been dismissed or not.
if ( isset( $review['dismissed'] ) && ! $review['dismissed'] ) {
$load = true;
}
}
// If we cannot load, return early.
if ( ! $load ) {
return;
}
$this->review();
}
/**
* Maybe show review request.
*
* @since 2.1.0
*/
private function review() {
// Get the currently selected mailer.
$mailer = Options::init()->get( 'mail', 'mailer' );
// Skip if the default mailer is selected.
if ( $mailer === 'mail' ) {
return;
}
// Fetch when plugin was initially activated.
$activated = get_option( 'wp_mail_smtp_activated_time' );
// Skip if the plugin activated time is not set.
if ( empty( $activated ) ) {
return;
}
// Check if mailer setup is complete.
$mailer_setup_complete = wp_mail_smtp()
->get_providers()
->get_mailer( $mailer, wp_mail_smtp()->get_processor()->get_phpmailer() )
->is_mailer_complete();
// Skip if the mailer is not set or the plugin is active for less then a defined number of days.
if ( ! $mailer_setup_complete || ( $activated + ( DAY_IN_SECONDS * self::WAIT_PERIOD ) ) > time() ) {
return;
}
// We have a candidate! Output a review message.
?>
<div class="notice notice-info is-dismissible wp-mail-smtp-review-notice">
<div class="wp-mail-smtp-review-step wp-mail-smtp-review-step-1">
<p><?php esc_html_e( 'Are you enjoying WP Mail SMTP?', 'wp-mail-smtp' ); ?></p>
<p>
<a href="#" class="wp-mail-smtp-review-switch-step" data-step="3"><?php esc_html_e( 'Yes', 'wp-mail-smtp' ); ?></a><br />
<a href="#" class="wp-mail-smtp-review-switch-step" data-step="2"><?php esc_html_e( 'Not Really', 'wp-mail-smtp' ); ?></a>
</p>
</div>
<div class="wp-mail-smtp-review-step wp-mail-smtp-review-step-2" style="display: none">
<p><?php esc_html_e( 'We\'re sorry to hear you aren\'t enjoying WP Mail SMTP. We would love a chance to improve. Could you take a minute and let us know what we can do better?', 'wp-mail-smtp' ); ?></p>
<p>
<a href="https://wpmailsmtp.com/plugin-feedback/" class="wp-mail-smtp-dismiss-review-notice wp-mail-smtp-review-out" target="_blank" rel="noopener noreferrer">
<?php esc_html_e( 'Give Feedback', 'wp-mail-smtp' ); ?>
</a><br>
<a href="#" class="wp-mail-smtp-dismiss-review-notice" target="_blank" rel="noopener noreferrer">
<?php esc_html_e( 'No thanks', 'wp-mail-smtp' ); ?>
</a>
</p>
</div>
<div class="wp-mail-smtp-review-step wp-mail-smtp-review-step-3" style="display: none">
<p><?php esc_html_e( 'Thats awesome! Could you please do me a BIG favor and give it a 5-star rating on WordPress to help us spread the word and boost our motivation?', 'wp-mail-smtp' ); ?></p>
<p><strong><?php echo wp_kses( __( '~ Jared Atchison<br>Lead Developer, WP Mail SMTP', 'wp-mail-smtp' ), [ 'br' => [] ] ); ?></strong></p>
<p>
<a href="https://wordpress.org/support/plugin/wp-mail-smtp/reviews/?filter=5#new-post" class="wp-mail-smtp-dismiss-review-notice wp-mail-smtp-review-out" target="_blank" rel="noopener noreferrer">
<?php esc_html_e( 'Ok, you deserve it', 'wp-mail-smtp' ); ?>
</a><br>
<a href="#" class="wp-mail-smtp-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'Nope, maybe later', 'wp-mail-smtp' ); ?></a><br>
<a href="#" class="wp-mail-smtp-dismiss-review-notice" target="_blank" rel="noopener noreferrer"><?php esc_html_e( 'I already did', 'wp-mail-smtp' ); ?></a>
</p>
</div>
</div>
<script type="text/javascript">
jQuery( document ).ready( function ( $ ) {
$( document ).on( 'click', '.wp-mail-smtp-dismiss-review-notice, .wp-mail-smtp-review-notice button', function( e ) {
if ( ! $( this ).hasClass( 'wp-mail-smtp-review-out' ) ) {
e.preventDefault();
}
$.post( ajaxurl, { action: 'wp_mail_smtp_review_dismiss' } );
$( '.wp-mail-smtp-review-notice' ).remove();
} );
$( document ).on( 'click', '.wp-mail-smtp-review-switch-step', function( e ) {
e.preventDefault();
var target = parseInt( $( this ).attr( 'data-step' ), 10 );
if ( target ) {
var $notice = $( this ).closest( '.wp-mail-smtp-review-notice' );
var $review_step = $notice.find( '.wp-mail-smtp-review-step-' + target );
if ( $review_step.length > 0 ) {
$notice.find( '.wp-mail-smtp-review-step:visible' ).fadeOut( function() {
$review_step.fadeIn();
} );
}
}
} );
} );
</script>
<?php
}
/**
* Dismiss the review admin notice.
*
* @since 2.1.0
*/
public function review_dismiss() {
$review = get_option( self::NOTICE_OPTION, [] );
$review['time'] = time();
$review['dismissed'] = true;
update_option( self::NOTICE_OPTION, $review );
if ( is_super_admin() && is_multisite() ) {
$site_list = get_sites();
foreach ( (array) $site_list as $site ) {
switch_to_blog( $site->blog_id );
update_option( self::NOTICE_OPTION, $review );
restore_current_blog();
}
}
wp_send_json_success();
}
}

View File

@ -95,6 +95,9 @@ class Core {
*/ */
public function hooks() { public function hooks() {
// Action Scheduler requires a special early loading procedure.
add_action( 'plugins_loaded', array( $this, 'load_action_scheduler' ), -10 );
// Activation hook. // Activation hook.
register_activation_hook( WPMS_PLUGIN_FILE, array( $this, 'activate' ) ); register_activation_hook( WPMS_PLUGIN_FILE, array( $this, 'activate' ) );
@ -107,6 +110,9 @@ class Core {
add_action( 'init', array( $this, 'init' ) ); add_action( 'init', array( $this, 'init' ) );
// Initialize Action Scheduler tasks.
add_action( 'init', array( $this, 'get_tasks' ), 5 );
add_action( 'plugins_loaded', array( $this, 'get_pro' ) ); add_action( 'plugins_loaded', array( $this, 'get_pro' ) );
} }
@ -188,6 +194,25 @@ class Core {
return $this->pro; return $this->pro;
} }
/**
* Get/Load the Tasks code of the plugin.
*
* @since 2.1.0
*
* @return \WPMailSMTP\Tasks\Tasks
*/
public function get_tasks() {
static $tasks;
if ( ! isset( $tasks ) ) {
$tasks = apply_filters( 'wp_mail_smtp_core_get_tasks', new Tasks\Tasks() );
$tasks->init();
}
return $tasks;
}
/** /**
* This method allows to overwrite certain core WP functions, because it's fired: * This method allows to overwrite certain core WP functions, because it's fired:
* - after `muplugins_loaded` hook, * - after `muplugins_loaded` hook,
@ -573,6 +598,13 @@ class Core {
// Save default options, only once. // Save default options, only once.
Options::init()->set( Options::get_defaults(), true ); Options::init()->set( Options::get_defaults(), true );
/**
* Store the timestamp of first plugin activation.
*
* @since 2.1.0
*/
add_option( 'wp_mail_smtp_activated_time', time(), '', false );
} }
/** /**
@ -689,4 +721,16 @@ class Core {
return (bool) apply_filters( 'wp_mail_smtp_is_white_labeled', false ); return (bool) apply_filters( 'wp_mail_smtp_is_white_labeled', false );
} }
/**
* Require the action scheduler in an early plugins_loaded hook (-10).
*
* @see https://actionscheduler.org/usage/#load-order
*
* @since 2.1.0
*/
public function load_action_scheduler() {
require_once $this->plugin_path . '/vendor/woocommerce/action-scheduler/action-scheduler.php';
}
} }

View File

@ -1,145 +1,154 @@
<?php <?php
namespace WPMailSMTP; namespace WPMailSMTP;
// Load PHPMailer class, so we can subclass it. // Load PHPMailer class, so we can subclass it.
if ( ! class_exists( 'PHPMailer', false ) ) { if ( ! class_exists( 'PHPMailer', false ) ) {
require_once ABSPATH . WPINC . '/class-phpmailer.php'; require_once ABSPATH . WPINC . '/class-phpmailer.php';
} }
/** /**
* Class MailCatcher replaces the \PHPMailer and modifies the email sending logic. * Class MailCatcher replaces the \PHPMailer and modifies the email sending logic.
* Thus, we can use other mailers API to do what we need, or stop emails completely. * Thus, we can use other mailers API to do what we need, or stop emails completely.
* *
* @since 1.0.0 * @since 1.0.0
*/ */
class MailCatcher extends \PHPMailer { class MailCatcher extends \PHPMailer {
/** /**
* 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.
* It is called out by send() for each email sent. * It is called out by send() for each email sent.
* *
* @since 1.3.0 * @since 1.3.0
* *
* @var string * @var string
*/ */
public $action_function = '\WPMailSMTP\Processor::send_callback'; public $action_function = '\WPMailSMTP\Processor::send_callback';
/** /**
* Modify the default send() behaviour. * Modify the default send() behaviour.
* For those mailers, that relies on PHPMailer class - call it directly. * For those mailers, that relies on PHPMailer class - call it directly.
* For others - init the correct provider and process it. * For others - init the correct provider and process it.
* *
* @since 1.0.0 * @since 1.0.0
* @since 1.4.0 Process "Do Not Send" option, but always allow test email. * @since 1.4.0 Process "Do Not Send" option, but always allow test email.
* *
* @throws \phpmailerException When sending via PhpMailer fails for some reason. * @throws \phpmailerException When sending via PhpMailer fails for some reason.
* *
* @return bool * @return bool
*/ */
public function send() { public function send() {
$options = new Options(); $options = new Options();
$mail_mailer = sanitize_key( $options->get( 'mail', 'mailer' ) ); $mail_mailer = sanitize_key( $options->get( 'mail', 'mailer' ) );
$is_emailing_blocked = false; $is_emailing_blocked = false;
if ( wp_mail_smtp()->is_blocked() ) { if ( wp_mail_smtp()->is_blocked() ) {
$is_emailing_blocked = true; $is_emailing_blocked = true;
} }
// Always allow a test email - check for the specific header. // Always allow a test email - check for the specific header.
foreach ( (array) $this->getCustomHeaders() as $header ) { foreach ( (array) $this->getCustomHeaders() as $header ) {
if ( if (
! empty( $header[0] ) && ! empty( $header[0] ) &&
! empty( $header[1] ) && ! empty( $header[1] ) &&
$header[0] === 'X-Mailer-Type' && $header[0] === 'X-Mailer-Type' &&
trim( $header[1] ) === 'WPMailSMTP/Admin/Test' trim( $header[1] ) === 'WPMailSMTP/Admin/Test'
) { ) {
$is_emailing_blocked = false; $is_emailing_blocked = false;
} }
}; };
// Do not send emails if admin desired that. // Do not send emails if admin desired that.
if ( $is_emailing_blocked ) { if ( $is_emailing_blocked ) {
return false; return false;
} }
// Define a custom header, that will be used to identify the plugin and the mailer. // Define a custom header, that will be used to identify the plugin and the mailer.
$this->XMailer = 'WPMailSMTP/Mailer/' . $mail_mailer . ' ' . WPMS_PLUGIN_VER; $this->XMailer = 'WPMailSMTP/Mailer/' . $mail_mailer . ' ' . WPMS_PLUGIN_VER;
// Use the default PHPMailer, as we inject our settings there for certain providers. // Use the default PHPMailer, as we inject our settings there for certain providers.
if ( if (
$mail_mailer === 'mail' || $mail_mailer === 'mail' ||
$mail_mailer === 'smtp' || $mail_mailer === 'smtp' ||
$mail_mailer === 'pepipost' $mail_mailer === 'pepipost'
) { ) {
try { try {
// Prepare all the headers. // Prepare all the headers.
if ( ! $this->preSend() ) { if ( ! $this->preSend() ) {
return false; return false;
} }
// Allow to hook after all the preparation before the actual sending. // Allow to hook after all the preparation before the actual sending.
do_action( 'wp_mail_smtp_mailcatcher_smtp_send_before', $this ); do_action( 'wp_mail_smtp_mailcatcher_smtp_send_before', $this );
return $this->postSend(); return $this->postSend();
} catch ( \phpmailerException $e ) { } catch ( \phpmailerException $e ) {
$this->mailHeader = ''; $this->mailHeader = '';
$this->setError( $e->getMessage() ); $this->setError( $e->getMessage() );
if ( $this->exceptions ) {
throw $e; // Set the debug error, but not for default PHP mailer.
} if ( $mail_mailer !== 'mail' ) {
Debug::set(
return false; 'Mailer: ' . esc_html( wp_mail_smtp()->get_providers()->get_options( $mail_mailer )->get_title() ) . PHP_EOL .
} $e->getMessage()
} );
}
// We need this so that the \PHPMailer class will correctly prepare all the headers.
$this->Mailer = 'mail'; if ( $this->exceptions ) {
throw $e;
// Prepare everything (including the message) for sending. }
if ( ! $this->preSend() ) {
return false; return false;
} }
}
$mailer = wp_mail_smtp()->get_providers()->get_mailer( $mail_mailer, $this );
// We need this so that the \PHPMailer class will correctly prepare all the headers.
if ( ! $mailer ) { $this->Mailer = 'mail';
return false;
} // Prepare everything (including the message) for sending.
if ( ! $this->preSend() ) {
if ( ! $mailer->is_php_compatible() ) { return false;
return false; }
}
$mailer = wp_mail_smtp()->get_providers()->get_mailer( $mail_mailer, $this );
/*
* Send the actual email. if ( ! $mailer ) {
* We reuse everything, that was preprocessed for usage in \PHPMailer. return false;
*/ }
$mailer->send();
if ( ! $mailer->is_php_compatible() ) {
$is_sent = $mailer->is_email_sent(); return false;
}
// Allow to perform any actions with the data.
do_action( 'wp_mail_smtp_mailcatcher_send_after', $mailer, $this ); /*
* Send the actual email.
return $is_sent; * We reuse everything, that was preprocessed for usage in \PHPMailer.
} */
$mailer->send();
/**
* Returns all custom headers. $is_sent = $mailer->is_email_sent();
* In older versions of \PHPMailer class this method didn't exist.
* As we support WordPress 3.6+ - we need to make sure this method is always present. // Allow to perform any actions with the data.
* do_action( 'wp_mail_smtp_mailcatcher_send_after', $mailer, $this );
* @since 1.5.0
* return $is_sent;
* @return array }
*/
public function getCustomHeaders() { /**
* Returns all custom headers.
return $this->CustomHeader; * In older versions of \PHPMailer class this method didn't exist.
} * As we support WordPress 3.6+ - we need to make sure this method is always present.
} *
* @since 1.5.0
*
* @return array
*/
public function getCustomHeaders() {
return $this->CustomHeader;
}
}

View File

@ -1,257 +1,401 @@
<?php <?php
namespace WPMailSMTP; namespace WPMailSMTP;
/** use WPMailSMTP\Tasks\Meta;
* Class Migration helps migrate all plugin options saved into DB to a new storage location.
* /**
* @since 1.0.0 * Class Migration helps migrate plugin options, DB tables and more.
*/ *
class Migration { * @since 1.0.0 Migrate all plugin options saved from separate WP options into one.
* @since 2.1.0 Major overhaul of this class to use DB migrations (or any other migrations per version).
/** */
* All old values for pre 1.0 version of a plugin. class Migration {
*
* @since 1.0.0 /**
* * Version of the latest migration.
* @var array *
*/ * @since 2.1.0
protected $old_keys = array( */
'pepipost_ssl', const VERSION = 2;
'pepipost_port',
'pepipost_pass', /**
'pepipost_user', * Option key where we save the current migration version.
'smtp_pass', *
'smtp_user', * @since 2.1.0
'smtp_auth', */
'smtp_ssl', const OPTION_NAME = 'wp_mail_smtp_migration_version';
'smtp_port',
'smtp_host', /**
'mail_set_return_path', * Current migration version, received from self::OPTION_NAME WP option
'mailer', *
'mail_from_name', * @since 2.1.0
'mail_from', *
'wp_mail_smtp_am_notifications_hidden', * @var int
); */
protected $cur_ver;
/**
* Old values, taken from $old_keys options. /**
* * All old values for pre 1.0 version of a plugin.
* @since 1.0.0 *
* * @since 1.0.0
* @var array *
*/ * @var array
protected $old_values = array(); */
protected $old_keys = array(
/** 'pepipost_ssl',
* Converted array of data from previous option values. 'pepipost_port',
* 'pepipost_pass',
* @since 1.0.0 'pepipost_user',
* 'smtp_pass',
* @var array 'smtp_user',
*/ 'smtp_auth',
protected $new_values = array(); 'smtp_ssl',
'smtp_port',
/** 'smtp_host',
* Migration constructor. 'mail_set_return_path',
* 'mailer',
* @since 1.0.0 'mail_from_name',
*/ 'mail_from',
public function __construct() { 'wp_mail_smtp_am_notifications_hidden',
);
if ( $this->is_migrated() ) {
return; /**
} * Old values, taken from $old_keys options.
*
$this->old_values = $this->get_old_values(); * @since 1.0.0
$this->new_values = $this->get_converted_options(); *
* @var array
Options::init()->set( $this->new_values, true ); */
protected $old_values = array();
// Removing all old options will be enabled some time in the future.
// $this->clean_deprecated_data(); /**
} * Converted array of data from previous option values.
*
/** * @since 1.0.0
* Whether we already migrated or not. *
* * @var array
* @since 1.0.0 */
* protected $new_values = array();
* @return bool
*/ /**
protected function is_migrated() { * Migration constructor.
*
$is_migrated = false; * @since 1.0.0
$new_values = get_option( Options::META_KEY, array() ); * @since 2.1.0 Redefined constructor - major overhaul.
*/
if ( ! empty( $new_values ) ) { public function __construct() {
$is_migrated = true;
} $this->cur_ver = self::get_cur_version();
return $is_migrated; $this->maybe_migrate();
} }
/** /**
* Get all old values from DB. * Static on purpose, to get current migration version without __construct() and validation.
* *
* @since 1.0.0 * @since 2.1.0
* *
* @return array * @return int
*/ */
protected function get_old_values() { public static function get_cur_version() {
$old_values = array(); return (int) get_option( self::OPTION_NAME, 0 );
}
foreach ( $this->old_keys as $old_key ) {
$value = get_option( $old_key, '' ); /**
* Run the migration if needed.
if ( ! empty( $value ) ) { *
$old_values[ $old_key ] = $value; * @since 2.1.0
} */
} protected function maybe_migrate() {
return $old_values; if ( ! is_admin() ) {
} return;
}
/**
* Convert old values from key=>value to a multidimensional array of data. if ( version_compare( $this->cur_ver, self::VERSION, '<' ) ) {
* $this->run( self::VERSION );
* @since 1.0.0 }
*/ }
protected function get_converted_options() {
/**
$converted = array(); * Actual migration launcher.
*
foreach ( $this->old_keys as $old_key ) { * @since 2.1.0
*
$old_value = isset( $this->old_values[ $old_key ] ) ? $this->old_values[ $old_key ] : ''; * @param int $version The version of migration to run.
*/
switch ( $old_key ) { protected function run( $version ) {
case 'pepipost_user':
case 'pepipost_pass': $function_version = (int) $version;
case 'pepipost_port':
case 'pepipost_ssl': if ( method_exists( $this, 'migrate_to_' . $function_version ) ) {
// Do not migrate pepipost options if it's not activated at the moment. $this->{'migrate_to_' . $function_version}();
if ( isset( $this->old_values['mailer'] ) && $this->old_values['mailer'] === 'pepipost' ) { } else {
$shortcut = explode( '_', $old_key ); $message = sprintf( /* translators: %1$s - WP Mail SMTP, %2$s - error message. */
esc_html__( 'There was an error while upgrading the database. Please contact %1$s support with this information: %2$s.', 'wp-mail-smtp' ),
if ( $old_key === 'pepipost_ssl' ) { '<strong>WP Mail SMTP</strong>',
$converted[ $shortcut[0] ]['encryption'] = $old_value; '<code>migration from v' . self::get_cur_version() . ' to v' . self::VERSION . ' failed. Plugin version: v' . WPMS_PLUGIN_VER . '</code>'
} else { );
$converted[ $shortcut[0] ][ $shortcut[1] ] = $old_value;
} WP::add_admin_notice( $message, WP::ADMIN_NOTICE_ERROR );
} }
break; }
case 'smtp_host': /**
case 'smtp_port': * Update migration version in options table.
case 'smtp_ssl': *
case 'smtp_auth': * @since 2.1.0
case 'smtp_user': *
case 'smtp_pass': * @param int $version Migration version.
$shortcut = explode( '_', $old_key ); */
protected function update_db_ver( $version ) {
if ( $old_key === 'smtp_ssl' ) {
$converted[ $shortcut[0] ]['encryption'] = $old_value; if ( empty( $version ) ) {
} elseif ( $old_key === 'smtp_auth' ) { $version = self::VERSION;
$converted[ $shortcut[0] ][ $shortcut[1] ] = ( $old_value === 'true' ? 'yes' : 'no' ); }
} else {
$converted[ $shortcut[0] ][ $shortcut[1] ] = $old_value; // Autoload it, because this value is checked all the time
} // and no need to request it separately from all autoloaded options.
update_option( self::OPTION_NAME, $version, true );
break; }
case 'mail_from': /**
$converted['mail']['from_email'] = $old_value; * Prevent running the same migration twice.
break; * Run migration only when required.
case 'mail_from_name': *
$converted['mail']['from_name'] = $old_value; * @since 2.1.0
break; *
case 'mail_set_return_path': * @param string $version The version of migration to check for potential execution.
$converted['mail']['return_path'] = ( $old_value === 'true' ); */
break; protected function maybe_required_older_migrations( $version ) {
case 'mailer':
$converted['mail']['mailer'] = $old_value; if ( version_compare( $this->cur_ver, $version, '<' ) ) {
break; $this->run( $version );
case 'wp_mail_smtp_am_notifications_hidden': }
$converted['general']['am_notifications_hidden'] = ( isset( $old_value ) && $old_value === 'true' ); }
break;
} /**
} * Migration from 0.x to 1.0.0.
* Move separate plugin WP options to one main plugin WP option setting.
$converted = $this->get_converted_constants_options( $converted ); *
* @since 2.1.0
return $converted; */
} private function migrate_to_1() {
/** if ( $this->is_migrated() ) {
* Some users use constants in wp-config.php to define values. return;
* We need to prioritize them and reapply data to options. }
* Use only those that are actually defined.
* $this->old_values = $this->get_old_values();
* @since 1.0.0 $this->new_values = $this->get_converted_options();
*
* @param array $converted Options::init()->set( $this->new_values, true );
*
* @return array $this->update_db_ver( 1 );
*/ }
protected function get_converted_constants_options( $converted ) {
/**
// Are we configured via constants? * Migration from 1.x to 2.1.0.
if ( ! defined( 'WPMS_ON' ) || ! WPMS_ON ) { * Create Tasks\Meta table, if it does not exist.
return $converted; *
} * @since 2.1.0
*/
/* private function migrate_to_2() {
* Mail settings.
*/ $this->maybe_required_older_migrations( 1 );
if ( defined( 'WPMS_MAIL_FROM' ) ) {
$converted['mail']['from_email'] = WPMS_MAIL_FROM; $meta = new Meta();
}
if ( defined( 'WPMS_MAIL_FROM_NAME' ) ) { // Create the table if it doesn't exist.
$converted['mail']['from_name'] = WPMS_MAIL_FROM_NAME; if ( $meta && ! $meta->table_exists() ) {
} $meta->create_table();
if ( defined( 'WPMS_MAILER' ) ) { }
$converted['mail']['mailer'] = WPMS_MAILER;
} $this->update_db_ver( 2 );
if ( defined( 'WPMS_SET_RETURN_PATH' ) ) { }
$converted['mail']['return_path'] = WPMS_SET_RETURN_PATH;
} /**
* Whether we already migrated or not.
/* *
* SMTP settings. * @since 1.0.0
*/ *
if ( defined( 'WPMS_SMTP_HOST' ) ) { * @return bool
$converted['smtp']['host'] = WPMS_SMTP_HOST; */
} protected function is_migrated() {
if ( defined( 'WPMS_SMTP_PORT' ) ) {
$converted['smtp']['port'] = WPMS_SMTP_PORT; $is_migrated = false;
} $new_values = get_option( Options::META_KEY, array() );
if ( defined( 'WPMS_SSL' ) ) {
$converted['smtp']['ssl'] = WPMS_SSL; if ( ! empty( $new_values ) ) {
} $is_migrated = true;
if ( defined( 'WPMS_SMTP_AUTH' ) ) { }
$converted['smtp']['auth'] = WPMS_SMTP_AUTH;
} return $is_migrated;
if ( defined( 'WPMS_SMTP_USER' ) ) { }
$converted['smtp']['user'] = WPMS_SMTP_USER;
} /**
if ( defined( 'WPMS_SMTP_PASS' ) ) { * Get all old values from DB.
$converted['smtp']['pass'] = WPMS_SMTP_PASS; *
} * @since 1.0.0
*
return $converted; * @return array
} */
protected function get_old_values() {
/**
* Delete all old values that are stored separately each. $old_values = array();
*
* @since 1.0.0 foreach ( $this->old_keys as $old_key ) {
*/ $value = get_option( $old_key, '' );
protected function clean_deprecated_data() {
if ( ! empty( $value ) ) {
foreach ( $this->old_keys as $old_key ) { $old_values[ $old_key ] = $value;
delete_option( $old_key ); }
} }
}
} return $old_values;
}
/**
* Convert old values from key=>value to a multidimensional array of data.
*
* @since 1.0.0
*/
protected function get_converted_options() {
$converted = array();
foreach ( $this->old_keys as $old_key ) {
$old_value = isset( $this->old_values[ $old_key ] ) ? $this->old_values[ $old_key ] : '';
switch ( $old_key ) {
case 'pepipost_user':
case 'pepipost_pass':
case 'pepipost_port':
case 'pepipost_ssl':
// Do not migrate pepipost options if it's not activated at the moment.
if ( isset( $this->old_values['mailer'] ) && $this->old_values['mailer'] === 'pepipost' ) {
$shortcut = explode( '_', $old_key );
if ( $old_key === 'pepipost_ssl' ) {
$converted[ $shortcut[0] ]['encryption'] = $old_value;
} else {
$converted[ $shortcut[0] ][ $shortcut[1] ] = $old_value;
}
}
break;
case 'smtp_host':
case 'smtp_port':
case 'smtp_ssl':
case 'smtp_auth':
case 'smtp_user':
case 'smtp_pass':
$shortcut = explode( '_', $old_key );
if ( $old_key === 'smtp_ssl' ) {
$converted[ $shortcut[0] ]['encryption'] = $old_value;
} elseif ( $old_key === 'smtp_auth' ) {
$converted[ $shortcut[0] ][ $shortcut[1] ] = ( $old_value === 'true' ? 'yes' : 'no' );
} else {
$converted[ $shortcut[0] ][ $shortcut[1] ] = $old_value;
}
break;
case 'mail_from':
$converted['mail']['from_email'] = $old_value;
break;
case 'mail_from_name':
$converted['mail']['from_name'] = $old_value;
break;
case 'mail_set_return_path':
$converted['mail']['return_path'] = ( $old_value === 'true' );
break;
case 'mailer':
$converted['mail']['mailer'] = $old_value;
break;
case 'wp_mail_smtp_am_notifications_hidden':
$converted['general']['am_notifications_hidden'] = ( isset( $old_value ) && $old_value === 'true' );
break;
}
}
$converted = $this->get_converted_constants_options( $converted );
return $converted;
}
/**
* Some users use constants in wp-config.php to define values.
* We need to prioritize them and reapply data to options.
* Use only those that are actually defined.
*
* @since 1.0.0
*
* @param array $converted
*
* @return array
*/
protected function get_converted_constants_options( $converted ) {
// Are we configured via constants?
if ( ! defined( 'WPMS_ON' ) || ! WPMS_ON ) {
return $converted;
}
/*
* Mail settings.
*/
if ( defined( 'WPMS_MAIL_FROM' ) ) {
$converted['mail']['from_email'] = WPMS_MAIL_FROM;
}
if ( defined( 'WPMS_MAIL_FROM_NAME' ) ) {
$converted['mail']['from_name'] = WPMS_MAIL_FROM_NAME;
}
if ( defined( 'WPMS_MAILER' ) ) {
$converted['mail']['mailer'] = WPMS_MAILER;
}
if ( defined( 'WPMS_SET_RETURN_PATH' ) ) {
$converted['mail']['return_path'] = WPMS_SET_RETURN_PATH;
}
/*
* SMTP settings.
*/
if ( defined( 'WPMS_SMTP_HOST' ) ) {
$converted['smtp']['host'] = WPMS_SMTP_HOST;
}
if ( defined( 'WPMS_SMTP_PORT' ) ) {
$converted['smtp']['port'] = WPMS_SMTP_PORT;
}
if ( defined( 'WPMS_SSL' ) ) {
$converted['smtp']['ssl'] = WPMS_SSL;
}
if ( defined( 'WPMS_SMTP_AUTH' ) ) {
$converted['smtp']['auth'] = WPMS_SMTP_AUTH;
}
if ( defined( 'WPMS_SMTP_USER' ) ) {
$converted['smtp']['user'] = WPMS_SMTP_USER;
}
if ( defined( 'WPMS_SMTP_PASS' ) ) {
$converted['smtp']['pass'] = WPMS_SMTP_PASS;
}
return $converted;
}
/**
* Delete all old values that are stored separately each.
*
* @since 1.0.0
*/
protected function clean_deprecated_data() {
foreach ( $this->old_keys as $old_key ) {
delete_option( $old_key );
}
}
}

View File

@ -19,21 +19,22 @@ class Options {
* @since 1.4.0 Added Mailgun:region. * @since 1.4.0 Added Mailgun:region.
* @since 1.5.0 Added Outlook/AmazonSES. * @since 1.5.0 Added Outlook/AmazonSES.
* @since 1.8.0 Added Pepipost API. * @since 1.8.0 Added Pepipost API.
* @since 2.0.0 Added SMTP.com API.
* *
* @since * @since
* *
* @var array Map of all the default options of the plugin. * @var array Map of all the default options of the plugin.
*/ */
private static $map = array( private static $map = [
'mail' => array( 'mail' => [
'from_name', 'from_name',
'from_email', 'from_email',
'mailer', 'mailer',
'return_path', 'return_path',
'from_name_force', 'from_name_force',
'from_email_force', 'from_email_force',
), ],
'smtp' => array( 'smtp' => [
'host', 'host',
'port', 'port',
'encryption', 'encryption',
@ -41,62 +42,64 @@ class Options {
'auth', 'auth',
'user', 'user',
'pass', 'pass',
), ],
'gmail' => array( 'gmail' => [
'client_id', 'client_id',
'client_secret', 'client_secret',
), ],
'outlook' => array( 'outlook' => [
'client_id', 'client_id',
'client_secret', 'client_secret',
), ],
'amazonses' => array( 'amazonses' => [
'client_id', 'client_id',
'client_secret', 'client_secret',
'region', 'region',
'emails_pending', 'emails_pending',
), ],
'mailgun' => array( 'mailgun' => [
'api_key', 'api_key',
'domain', 'domain',
'region', 'region',
), ],
'sendgrid' => array( 'sendgrid' => [
'api_key', 'api_key',
), ],
'smtpcom' => array( 'smtpcom' => [
'api_key', 'api_key',
'channel', 'channel',
), ],
'sendinblue' => array( 'sendinblue' => [
'api_key', 'api_key',
), ],
'pepipostapi' => array( 'pepipostapi' => [
'api_key', 'api_key',
), ],
'pepipost' => array( 'pepipost' => [
'host', 'host',
'port', 'port',
'encryption', 'encryption',
'auth', 'auth',
'user', 'user',
'pass', 'pass',
), ],
'license' => array( 'license' => [
'key', 'key',
), ],
); ];
/** /**
* That's where plugin options are saved in wp_options table. * That's where plugin options are saved in wp_options table.
* *
* @var string * @since 1.0.0
*/ */
const META_KEY = 'wp_mail_smtp'; const META_KEY = 'wp_mail_smtp';
/** /**
* All the plugin options. * All the plugin options.
* *
* @since 1.0.0
*
* @var array * @var array
*/ */
private $_options = array(); private $_options = array();
@ -141,6 +144,7 @@ class Options {
* Default options that are saved on plugin activation. * Default options that are saved on plugin activation.
* *
* @since 1.3.0 * @since 1.3.0
* @since 2.1.0 Set the Force from email to "on" by default.
* *
* @return array * @return array
*/ */
@ -152,7 +156,7 @@ class Options {
'from_name' => get_bloginfo( 'name' ), 'from_name' => get_bloginfo( 'name' ),
'mailer' => 'mail', 'mailer' => 'mail',
'return_path' => false, 'return_path' => false,
'from_email_force' => false, 'from_email_force' => true,
'from_name_force' => false, 'from_name_force' => false,
), ),
'smtp' => array( 'smtp' => array(
@ -784,7 +788,7 @@ class Options {
* @since 1.5.0 Added Outlook/AmazonSES, Email Log. Stop saving const values into DB. * @since 1.5.0 Added Outlook/AmazonSES, Email Log. Stop saving const values into DB.
* *
* @param array $options Plugin options to save. * @param array $options Plugin options to save.
* @param bool $once Whether to update existing options or to add these options only once. * @param bool $once Whether to update existing options or to add these options only once.
*/ */
public function set( $options, $once = false ) { public function set( $options, $once = false ) {
/* /*

View File

@ -9,6 +9,18 @@ namespace WPMailSMTP;
*/ */
class Processor { class Processor {
/**
* This attribute will hold the "original" WP from email address passed to the wp_mail_from filter,
* that is not equal to the default email address.
*
* It should hold an email address set via the wp_mail_from filter, before we might overwrite it.
*
* @since 2.1.0
*
* @var string
*/
protected $wp_mail_from;
/** /**
* Processor constructor. * Processor constructor.
* *
@ -81,6 +93,11 @@ class Processor {
$phpmailer->SMTPAutoTLS = false; $phpmailer->SMTPAutoTLS = false;
} }
// Check if original WP from email can be set as the reply_to attribute.
if ( $this->allow_setting_original_from_email_to_reply_to( $phpmailer->getReplyToAddresses(), $mailer ) ) {
$phpmailer->addReplyTo( $this->wp_mail_from );
}
// If we're sending via SMTP, set the host. // If we're sending via SMTP, set the host.
if ( 'smtp' === $mailer ) { if ( 'smtp' === $mailer ) {
// Set the other options. // Set the other options.
@ -104,12 +121,62 @@ class Processor {
$phpmailer->Password = $options->get( $mailer, 'pass' ); $phpmailer->Password = $options->get( $mailer, 'pass' );
} }
// Maybe set default reply-to header.
$this->set_default_reply_to( $phpmailer );
// You can add your own options here. // You can add your own options here.
// See the phpmailer documentation for more info: https://github.com/PHPMailer/PHPMailer/tree/5.2-stable. // See the phpmailer documentation for more info: https://github.com/PHPMailer/PHPMailer/tree/5.2-stable.
/** @noinspection PhpUnusedLocalVariableInspection It's passed by reference. */ /** @noinspection PhpUnusedLocalVariableInspection It's passed by reference. */
$phpmailer = apply_filters( 'wp_mail_smtp_custom_options', $phpmailer ); $phpmailer = apply_filters( 'wp_mail_smtp_custom_options', $phpmailer );
} }
/**
* Check if it's allowed to set the original WP from email to the reply_to field.
*
* @since 2.1.0
*
* @param array $reply_to Array of currently set reply to emails.
* @param string $mailer The slug of current mailer.
*
* @return bool
*/
protected function allow_setting_original_from_email_to_reply_to( $reply_to, $mailer ) {
$options = new Options();
$forced = $options->get( 'mail', 'from_email_force' );
$from_email = $options->get( 'mail', 'from_email' );
if ( ! empty( $reply_to ) ) {
return false;
}
if ( in_array( $mailer, array( 'gmail', 'outlook' ), true ) ) {
$forced = true;
switch ( $mailer ) {
case 'gmail':
$sender = wp_mail_smtp()->get_providers()->get_auth( 'gmail' )->get_user_info();
break;
case 'outlook':
$sender = $options->get( 'outlook', 'user_details' );
break;
}
$from_email = ! empty( $sender['email'] ) ? $sender['email'] : '';
}
if (
empty( $this->wp_mail_from ) ||
$from_email === $this->wp_mail_from ||
! $forced
) {
return false;
}
return true;
}
/** /**
* This method will be called every time 'smtp' and 'mail' mailers will be used to send emails. * This method will be called every time 'smtp' and 'mail' mailers will be used to send emails.
* *
@ -157,6 +224,11 @@ class Processor {
$from_email = $options->get( 'mail', 'from_email' ); $from_email = $options->get( 'mail', 'from_email' );
$def_email = $this->get_default_email(); $def_email = $this->get_default_email();
// Save the "original" set WP email from address for later use.
if ( $wp_email !== $def_email ) {
$this->wp_mail_from = $wp_email;
}
// Return FROM EMAIL if forced in settings. // Return FROM EMAIL if forced in settings.
if ( $forced & ! empty( $from_email ) ) { if ( $forced & ! empty( $from_email ) ) {
return $from_email; return $from_email;
@ -250,4 +322,34 @@ class Processor {
return $phpmailer; return $phpmailer;
} }
/**
* Set the default reply_to header, if:
* - no other reply_to headers are already set and,
* - the default reply_to address filter `wp_mail_smtp_processor_default_reply_to_addresses` is configured.
*
* @since 2.1.1
*
* @param \PHPMailer $phpmailer The PHPMailer object.
*/
private function set_default_reply_to( $phpmailer ) {
if ( ! empty( $phpmailer->getReplyToAddresses() ) ) {
return;
}
$default_reply_to_emails = apply_filters( 'wp_mail_smtp_processor_set_default_reply_to', '' );
if ( empty( $default_reply_to_emails ) ) {
return;
}
foreach ( explode( ',', $default_reply_to_emails ) as $email ) {
$email = trim( $email );
if ( filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
$phpmailer->addReplyTo( $email );
}
}
}
} }

View File

@ -92,26 +92,28 @@ class Mailer extends MailerAbstract {
$this->phpmailer->Sender = $gmail_creds['email']; $this->phpmailer->Sender = $gmail_creds['email'];
} }
// Get the raw MIME email using MailCatcher data.
// We need here to make base64URL-safe string.
$base64 = str_replace(
array( '+', '/', '=' ),
array( '-', '_', '' ),
base64_encode( $this->phpmailer->getSentMIMEMessage() )
);
$message->setRaw( $base64 );
$service = new \Google_Service_Gmail( $auth->get_client() );
try { try {
// Prepare a message for sending.
$this->phpmailer->preSend();
// Get the raw MIME email using MailCatcher data.
// We need here to make base64URL-safe string.
$base64 = str_replace(
[ '+', '/', '=' ],
[ '-', '_', '' ],
base64_encode( $this->phpmailer->getSentMIMEMessage() ) //phpcs:ignore
);
$message->setRaw( $base64 );
$service = new \Google_Service_Gmail( $auth->get_client() );
$response = $service->users_messages->send( 'me', $message ); $response = $service->users_messages->send( 'me', $message );
$this->process_response( $response ); $this->process_response( $response );
} catch ( \Exception $e ) { } catch ( \Exception $e ) {
Debug::set( Debug::set(
'Mailer: Gmail' . "\r\n" . 'Mailer: Gmail' . "\r\n" .
$e->getMessage() $this->process_exception_message( $e->getMessage() )
); );
return; return;
@ -124,7 +126,7 @@ class Mailer extends MailerAbstract {
* @since 1.0.0 * @since 1.0.0
* @since 1.5.0 Added action "wp_mail_smtp_providers_gmail_mailer_process_response" with $response. * @since 1.5.0 Added action "wp_mail_smtp_providers_gmail_mailer_process_response" with $response.
* *
* @param \Google_Service_Gmail_Message $response * @param \Google_Service_Gmail_Message $response Instance of Gmail response.
*/ */
protected function process_response( $response ) { protected function process_response( $response ) {
@ -160,7 +162,12 @@ class Mailer extends MailerAbstract {
} }
/** /**
* @inheritdoc * This method is relevant to SMTP and Pepipost.
* All other custom mailers should override it with own information.
*
* @since 1.2.0
*
* @return string
*/ */
public function get_debug_info() { public function get_debug_info() {
@ -200,7 +207,11 @@ class Mailer extends MailerAbstract {
} }
/** /**
* @inheritdoc * Whether the mailer has all its settings correctly set up and saved.
*
* @since 1.4.0
*
* @return bool
*/ */
public function is_mailer_complete() { public function is_mailer_complete() {
@ -219,4 +230,75 @@ class Mailer extends MailerAbstract {
return false; return false;
} }
/**
* Process the exception message and append additional explanation to it.
*
* @since 2.1.0
*
* @param mixed $message A string or an object with strings.
*
* @return string
*/
protected function process_exception_message( $message ) {
// Transform the passed message to a string.
if ( ! is_string( $message ) ) {
$message = wp_json_encode( $message );
} else {
$message = wp_strip_all_tags( $message, false );
}
// Define known errors, that we will scan the message with.
$known_errors = array(
array(
'errors' => array(
'invalid_grant',
),
'explanation' => esc_html__( 'Please re-grant Google app permissions!', 'wp-mail-smtp' ) . ' ' . PHP_EOL .
esc_html__( 'Go to WP Mail SMTP plugin settings page. Click the “Remove Connection” button.', 'wp-mail-smtp' ) . ' ' . PHP_EOL .
esc_html__( 'Then click the “Allow plugin to send emails using your Google account” button and re-enable access.', 'wp-mail-smtp' ),
),
);
// Check if we get a match and append the explanation to the original message.
foreach ( $known_errors as $error ) {
foreach ( $error['errors'] as $error_fragment ) {
if ( false !== strpos( $message, $error_fragment ) ) {
return $message . PHP_EOL . $error['explanation'];
}
}
}
// If we get no match we return the original message (as a string).
return $message;
}
/**
* Get the default email addresses for the reply to email parameter.
*
* @deprecated 2.1.1
*
* @since 2.1.0
* @since 2.1.1 Not used anymore.
*
* @return array
*/
public function default_reply_to_addresses() {
_deprecated_function( __CLASS__ . '::' . __METHOD__, '2.1.1 of WP Mail SMTP plugin' );
$gmail_creds = ( new Auth() )->get_user_info();
if ( empty( $gmail_creds['email'] ) ) {
return [];
}
return [
$gmail_creds['email'] => [
$gmail_creds['email'],
'',
],
];
}
} }

View File

@ -132,8 +132,8 @@ class Loader {
* *
* @since 1.0.0 * @since 1.0.0
* *
* @param string $provider * @param string $provider The provider name.
* @param MailCatcher $phpmailer * @param MailCatcher|\PHPMailer $phpmailer The MailCatcher object.
* *
* @return MailerAbstract|null * @return MailerAbstract|null
*/ */

View File

@ -414,4 +414,54 @@ abstract class MailerAbstract implements MailerInterface {
return implode( '<br>', $smtp_text ); return implode( '<br>', $smtp_text );
} }
/**
* Get the email addresses for the reply to email parameter.
*
* @deprecated 2.1.1
*
* @since 2.1.0
* @since 2.1.1 Not used anymore.
*
* @return array
*/
public function get_reply_to_addresses() {
_deprecated_function( __CLASS__ . '::' . __METHOD__, '2.1.1 of WP Mail SMTP plugin' );
$reply_to = $this->phpmailer->getReplyToAddresses();
// Return the passed reply to addresses, if defined.
if ( ! empty( $reply_to ) ) {
return $reply_to;
}
// Return the default reply to addresses.
return apply_filters(
'wp_mail_smtp_providers_mailer_default_reply_to_addresses',
$this->default_reply_to_addresses()
);
}
/**
* Get the default email addresses for the reply to email parameter.
*
* @deprecated 2.1.1
*
* @since 2.1.0
* @since 2.1.1 Not used anymore.
*
* @return array
*/
public function default_reply_to_addresses() {
_deprecated_function( __CLASS__ . '::' . __METHOD__, '2.1.1 of WP Mail SMTP plugin' );
return [
$this->phpmailer->From => [
$this->phpmailer->From,
$this->phpmailer->FromName,
],
];
}
} }

View File

@ -344,20 +344,12 @@ abstract class OptionsAbstract implements OptionsInterface {
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-pass" spellcheck="false" autocomplete="new-password" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-pass" spellcheck="false" autocomplete="new-password"
/> />
<p class="desc"> <p class="desc">
<?php esc_html_e( 'The password is stored in plain text. We highly recommend you set up your password in your WordPress configuration file for improved security.', 'wp-mail-smtp' ); ?> <?php esc_html_e( 'The password will be stored in plain text. For improved security, we highly recommend using your site\'s WordPress configuration file to set your password.', 'wp-mail-smtp' ); ?>
<br> <br>
<?php <a href="https://wpmailsmtp.com/docs/how-to-secure-smtp-settings-by-using-constants/" target="_blank" rel="noopener noreferrer">
printf( <strong><?php esc_html_e( 'Learn More', 'wp-mail-smtp' ); ?></strong>
/* translators: %s - wp-config.php. */ </a>
esc_html__( 'To do this add the lines below to your %s file:', 'wp-mail-smtp' ),
'<code>wp-config.php</code>'
);
?>
</p> </p>
<pre>
define( 'WPMS_ON', true );
define( 'WPMS_SMTP_PASS', 'your_password' );
</pre>
<?php endif; ?> <?php endif; ?>
</div> </div>
</div> </div>
@ -440,13 +432,21 @@ abstract class OptionsAbstract implements OptionsInterface {
<blockquote> <blockquote>
<?php <?php
printf( printf(
/* translators: %s - Provider name. */ wp_kses( /* translators: %s - Provider name */
esc_html__( '%s requires a SSL certificate on a site to work and does not support your current installation. Please contact your host and request a SSL certificate or install a free one, like Let\'s Encrypt.', 'wp-mail-smtp' ), __( '%s requires an SSL certificate, and so is not currently compatible with your site. Please contact your host to request a SSL certificate, or check out <a href="https://www.wpbeginner.com/wp-tutorials/how-to-add-ssl-and-https-in-wordpress/" target="_blank">WPBeginner\'s tutorial on how to set up SSL</a>.', 'wp-mail-smtp' ),
[
'a' => [
'href' => [],
'target' => [],
],
]
),
esc_html( $this->get_title() ) esc_html( $this->get_title() )
); );
?> ?>
<br> <br>
<?php esc_html_e( 'Meanwhile you can switch to some other mailers.', 'wp-mail-smtp' ); ?> <br>
<?php esc_html_e( 'If you\'d prefer not to set up SSL, or need an SMTP solution in the meantime, please select a different mailer option.', 'wp-mail-smtp' ); ?>
</blockquote> </blockquote>
<?php <?php

View File

@ -38,7 +38,7 @@ class Options extends OptionsAbstract {
$description = sprintf( $description = sprintf(
wp_kses( /* translators: %s - URL to smtp.com site. */ wp_kses( /* translators: %s - URL to smtp.com site. */
__( '<strong><a href="%s" target="_blank" rel="noopener noreferrer">SMTP.com</a> is a recommended transactional email service.</strong> With over 22 years of email delivery expertise, SMTP.com has been around for almost as long as email itself. They are known among internet providers as one of the most reliable senders on the internet. Their easy integration process lets you start sending emails in minutes and benefit from years of experience. SMTP.com provides users 10,000 free emails the first 30 days.', 'wp-mail-smtp' ), __( '<strong><a href="%s" target="_blank" rel="noopener noreferrer">SMTP.com</a> is a recommended transactional email service.</strong> With a 22 years of track record of reliable email delivery, SMTP.com is a premiere solution for WordPress developers and website owners. SMTP.com has been around for almost as long as email itself. Their super simple integration interface makes it easy to get started while a powerful API and robust documentation make it a preferred choice among developers. Start a 30-day free trial with 50,000 emails.', 'wp-mail-smtp' ),
$allowed_kses_html $allowed_kses_html
), ),
'https://wpmailsmtp.com/go/smtp/' 'https://wpmailsmtp.com/go/smtp/'

View File

@ -0,0 +1,527 @@
<?php
namespace WPMailSMTP\Tasks;
/**
* Class Meta helps to manage the tasks meta information
* between Action Scheduler and WP Mail SMTP hooks arguments.
* We can't pass arguments longer than >191 chars in JSON to AS,
* so we need to store them somewhere (and clean from time to time).
*
* @since 2.1.0
*/
class Meta {
/**
* Database table name.
*
* @since 2.1.0
*
* @var string
*/
public $table_name;
/**
* Database version.
*
* @since 2.1.0
*
* @var string
*/
public $version;
/**
* Primary key (unique field) for the database table.
*
* @since 2.1.0
*
* @var string
*/
public $primary_key = 'id';
/**
* Database type identifier.
*
* @since 2.1.0
*
* @var string
*/
public $type = 'tasks_meta';
/**
* Primary class constructor.
*
* @since 2.1.0
*/
public function __construct() {
$this->table_name = self::get_table_name();
}
/**
* Get the DB table name.
*
* @since 2.1.0
*
* @return string
*/
public static function get_table_name() {
global $wpdb;
return $wpdb->prefix . 'wpmailsmtp_tasks_meta';
}
/**
* Get table columns.
*
* @since 2.1.0
*/
public function get_columns() {
return array(
'id' => '%d',
'action' => '%s',
'data' => '%s',
'date' => '%s',
);
}
/**
* Default column values.
*
* @since 2.1.0
*
* @return array
*/
public function get_column_defaults() {
return array(
'action' => '',
'data' => '',
'date' => gmdate( 'Y-m-d H:i:s' ),
);
}
/**
* Retrieve a row from the database based on a given row ID.
*
* @since 2.1.0
*
* @param int $row_id Row ID.
*
* @return null|object
*/
private function get_from_db( $row_id ) {
global $wpdb;
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
return $wpdb->get_row(
$wpdb->prepare(
"SELECT * FROM {$this->table_name} WHERE {$this->primary_key} = %s LIMIT 1;", // phpcs:ignore
$row_id
)
);
}
/**
* Retrieve a row based on column and row ID.
*
* @since 2.1.0
*
* @param string $column Column name.
* @param int|string $row_id Row ID.
*
* @return object|null|bool Database query result, object or null on failure.
*/
public function get_by( $column, $row_id ) {
global $wpdb;
if ( empty( $row_id ) || ! array_key_exists( $column, $this->get_columns() ) ) {
return false;
}
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
return $wpdb->get_row(
$wpdb->prepare(
"SELECT * FROM $this->table_name WHERE $column = '%s' LIMIT 1;", // phpcs:ignore
$row_id
)
);
}
/**
* Retrieve a value based on column name and row ID.
*
* @since 2.1.0
*
* @param string $column Column name.
* @param int|string $row_id Row ID.
*
* @return string|null Database query result (as string), or null on failure.
*/
public function get_column( $column, $row_id ) {
global $wpdb;
if ( empty( $row_id ) || ! array_key_exists( $column, $this->get_columns() ) ) {
return false;
}
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
return $wpdb->get_var(
$wpdb->prepare(
"SELECT $column FROM $this->table_name WHERE $this->primary_key = '%s' LIMIT 1;", // phpcs:ignore
$row_id
)
);
}
/**
* Retrieve one column value based on another given column and matching value.
*
* @since 2.1.0
*
* @param string $column Column name.
* @param string $column_where Column to match against in the WHERE clause.
* @param string $column_value Value to match to the column in the WHERE clause.
*
* @return string|null Database query result (as string), or null on failure.
*/
public function get_column_by( $column, $column_where, $column_value ) {
global $wpdb;
if ( empty( $column ) || empty( $column_where ) || empty( $column_value ) || ! array_key_exists( $column, $this->get_columns() ) ) {
return false;
}
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
return $wpdb->get_var(
$wpdb->prepare(
"SELECT $column FROM $this->table_name WHERE $column_where = %s LIMIT 1;", // phpcs:ignore
$column_value
)
);
}
/**
* Insert a new record into the database.
*
* @since 2.1.0
*
* @param array $data Column data.
* @param string $type Optional. Data type context.
*
* @return int ID for the newly inserted record. 0 otherwise.
*/
private function add_to_db( $data, $type = '' ) {
global $wpdb;
// Set default values.
$data = wp_parse_args( $data, $this->get_column_defaults() );
do_action( 'wp_mail_smtp_pre_insert_' . $type, $data );
// Initialise column format array.
$column_formats = $this->get_columns();
// Force fields to lower case.
$data = array_change_key_case( $data );
// White list columns.
$data = array_intersect_key( $data, $column_formats );
// Reorder $column_formats to match the order of columns given in $data.
$data_keys = array_keys( $data );
$column_formats = array_merge( array_flip( $data_keys ), $column_formats );
$wpdb->insert( $this->table_name, $data, $column_formats );
do_action( 'wp_mail_smtp_post_insert_' . $type, $wpdb->insert_id, $data );
return $wpdb->insert_id;
}
/**
* Update an existing record in the database.
*
* @since 2.1.0
*
* @param int|string $row_id Row ID for the record being updated.
* @param array $data Optional. Array of columns and associated data to update. Default empty array.
* @param string $where Optional. Column to match against in the WHERE clause. If empty, $primary_key
* will be used. Default empty.
* @param string $type Optional. Data type context, e.g. 'affiliate', 'creative', etc. Default empty.
*
* @return bool False if the record could not be updated, true otherwise.
*/
public function update( $row_id, $data = array(), $where = '', $type = '' ) {
global $wpdb;
// Row ID must be a positive integer.
$row_id = absint( $row_id );
if ( empty( $row_id ) ) {
return false;
}
if ( empty( $where ) ) {
$where = $this->primary_key;
}
do_action( 'wp_mail_smtp_pre_update_' . $type, $data );
// Initialise column format array.
$column_formats = $this->get_columns();
// Force fields to lower case.
$data = array_change_key_case( $data );
// White list columns.
$data = array_intersect_key( $data, $column_formats );
// Reorder $column_formats to match the order of columns given in $data.
$data_keys = array_keys( $data );
$column_formats = array_merge( array_flip( $data_keys ), $column_formats );
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
if ( false === $wpdb->update( $this->table_name, $data, array( $where => $row_id ), $column_formats ) ) {
return false;
}
do_action( 'wp_mail_smtp_post_update_' . $type, $data );
return true;
}
/**
* Delete a record from the database.
*
* @since 2.1.0
*
* @param int|string $row_id Row ID.
*
* @return bool False if the record could not be deleted, true otherwise.
*/
public function delete( $row_id = 0 ) {
global $wpdb;
// Row ID must be positive integer.
$row_id = absint( $row_id );
if ( empty( $row_id ) ) {
return false;
}
do_action( 'wp_mail_smtp_pre_delete', $row_id );
do_action( 'wp_mail_smtp_pre_delete_' . $this->type, $row_id );
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
if ( false === $wpdb->query( $wpdb->prepare( "DELETE FROM {$this->table_name} WHERE {$this->primary_key} = %d", $row_id ) ) ) { // phpcs:ignore
return false;
}
do_action( 'wp_mail_smtp_post_delete', $row_id );
do_action( 'wp_mail_smtp_post_delete_' . $this->type, $row_id );
return true;
}
/**
* Delete a record from the database by column.
*
* @since 2.1.0
*
* @param string $column Column name.
* @param int|string $column_value Column value.
*
* @return bool False if the record could not be deleted, true otherwise.
*/
public function delete_by( $column, $column_value ) {
global $wpdb;
if ( empty( $column ) || empty( $column_value ) || ! array_key_exists( $column, $this->get_columns() ) ) {
return false;
}
do_action( 'wp_mail_smtp_pre_delete', $column_value );
do_action( 'wp_mail_smtp_pre_delete_' . $this->type, $column_value );
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
if ( false === $wpdb->query( $wpdb->prepare( "DELETE FROM {$this->table_name} WHERE $column = %s", $column_value ) ) ) { // phpcs:ignore
return false;
}
do_action( 'wp_mail_smtp_post_delete', $column_value );
do_action( 'wp_mail_smtp_post_delete_' . $this->type, $column_value );
return true;
}
/**
* Check if the given table exists.
*
* @since 2.1.0
*
* @param string $table The table name. Defaults to the child class table name.
*
* @return string|null If the table name exists.
*/
public function table_exists( $table = '' ) {
global $wpdb;
if ( ! empty( $table ) ) {
$table = sanitize_text_field( $table );
} else {
$table = $this->table_name;
}
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
return $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s', $table ) ) === $table;
}
/**
* Create custom entry meta database table.
* Used in migration.
*
* @since 2.1.0
*/
public function create_table() {
global $wpdb;
require_once ABSPATH . 'wp-admin/includes/upgrade.php';
$charset_collate = '';
if ( ! empty( $wpdb->charset ) ) {
$charset_collate .= "DEFAULT CHARACTER SET {$wpdb->charset}";
}
if ( ! empty( $wpdb->collate ) ) {
$charset_collate .= " COLLATE {$wpdb->collate}";
}
$sql = "CREATE TABLE {$this->table_name} (
id bigint(20) NOT NULL AUTO_INCREMENT,
action varchar(255) NOT NULL,
data longtext NOT NULL,
date datetime NOT NULL,
PRIMARY KEY (id)
) {$charset_collate};";
dbDelta( $sql );
}
/**
* Remove queue records for a defined period of time in the past.
* Calling this method will remove queue records that are older than $period seconds.
*
* @since 2.1.0
*
* @param string $action Action that should be cleaned up.
* @param int $interval Number of seconds from now.
*
* @return int Number of removed tasks meta records.
*/
public function clean_by( $action, $interval ) {
global $wpdb;
if ( empty( $action ) || empty( $interval ) ) {
return 0;
}
$table = self::get_table_name();
$action = sanitize_key( $action );
$date = gmdate( 'Y-m-d H:i:s', time() - (int) $interval );
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
return (int) $wpdb->query(
$wpdb->prepare(
"DELETE FROM `$table` WHERE action = %s AND date < %s", // phpcs:ignore WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$action,
$date
)
);
}
/**
* Inserts a new record into the database.
*
* @since 2.1.0
*
* @param array $data Column data.
* @param string $type Optional. Data type context.
*
* @return int ID for the newly inserted record. 0 otherwise.
*/
public function add( $data, $type = '' ) {
if ( empty( $data['action'] ) || ! is_string( $data['action'] ) ) {
return 0;
}
$data['action'] = sanitize_key( $data['action'] );
if ( isset( $data['data'] ) ) {
$string = wp_json_encode( $data['data'] );
if ( $string === false ) {
$string = '';
}
/*
* We are encoding the string representation of all the data
* to make sure that nothing can harm the database.
* This is not an encryption, and we need this data later as is,
* so we are using one of the fastest way to do that.
* This data is removed from DB on a daily basis.
*/
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
$data['data'] = base64_encode( $string );
}
if ( empty( $type ) ) {
$type = $this->type;
}
return $this->add_to_db( $data, $type );
}
/**
* Retrieve a row from the database based on a given row ID.
*
* @since 2.1.0}
*
* @param int $meta_id Meta ID.
*
* @return null|object
*/
public function get( $meta_id ) {
$meta = $this->get_from_db( $meta_id );
if ( empty( $meta ) || empty( $meta->data ) ) {
return $meta;
}
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
$decoded = base64_decode( $meta->data );
if ( $decoded === false || ! is_string( $decoded ) ) {
$meta->data = '';
} else {
$meta->data = json_decode( $decoded, true );
}
return $meta;
}
}

View File

@ -0,0 +1,304 @@
<?php
namespace WPMailSMTP\Tasks;
/**
* Class Task.
*
* @since 2.1.0
*/
class Task {
/**
* This task is async (runs asap).
*
* @since 2.1.0
*/
const TYPE_ASYNC = 'async';
/**
* This task is a recurring.
*
* @since 2.1.0
*/
const TYPE_RECURRING = 'scheduled';
/**
* This task is run once.
*
* @since 2.1.0
*/
const TYPE_ONCE = 'once';
/**
* Type of the task.
*
* @since 2.1.0
*
* @var string
*/
private $type;
/**
* Action that will be used as a hook.
*
* @since 2.1.0
*
* @var string
*/
private $action;
/**
* Task meta ID.
*
* @since 2.1.0
*
* @var int
*/
private $meta_id;
/**
* All the params that should be passed to the hook.
*
* @since 2.1.0
*
* @var array
*/
private $params;
/**
* When the first instance of the job will run.
* Used for ONCE ane RECURRING tasks.
*
* @since 2.1.0
*
* @var int
*/
private $timestamp;
/**
* How long to wait between runs.
* Used for RECURRING tasks.
*
* @since 2.1.0
*
* @var int
*/
private $interval;
/**
* Task constructor.
*
* @since 2.1.0
*
* @param string $action Action of the task.
*
* @throws \InvalidArgumentException When action is not a string.
* @throws \UnexpectedValueException When action is empty.
*/
public function __construct( $action ) {
if ( ! is_string( $action ) ) {
throw new \InvalidArgumentException( 'Task action should be a string.' );
}
$this->action = sanitize_key( $action );
if ( empty( $this->action ) ) {
throw new \UnexpectedValueException( 'Task action cannot be empty.' );
}
}
/**
* Define the type of the task as async.
*
* @since 2.1.0
*
* @return Task
*/
public function async() {
$this->type = self::TYPE_ASYNC;
return $this;
}
/**
* Define the type of the task as recurring.
*
* @since 2.1.0
*
* @param int $timestamp When the first instance of the job will run.
* @param int $interval How long to wait between runs.
*
* @return Task
*/
public function recurring( $timestamp, $interval ) {
$this->type = self::TYPE_RECURRING;
$this->timestamp = (int) $timestamp;
$this->interval = (int) $interval;
return $this;
}
/**
* Define the type of the task as one-time.
*
* @since 2.1.0
*
* @param int $timestamp When the first instance of the job will run.
*
* @return Task
*/
public function once( $timestamp ) {
$this->type = self::TYPE_ONCE;
$this->timestamp = (int) $timestamp;
return $this;
}
/**
* Pass any number of params that should be saved to Meta table.
*
* @since 2.1.0
*
* @return Task
*/
public function params() {
$this->params = func_get_args();
return $this;
}
/**
* Register the action.
* Should be the final call in a chain.
*
* @since 2.1.0
*
* @return null|string Action ID.
*/
public function register() {
$action_id = null;
// No processing if ActionScheduler is not usable.
if ( ! wp_mail_smtp()->get_tasks()->is_usable() ) {
return $action_id;
}
// Save data to tasks meta table.
$task_meta = new Meta();
$this->meta_id = $task_meta->add(
[
'action' => $this->action,
'data' => $this->params,
]
);
if ( empty( $this->meta_id ) ) {
return $action_id;
}
switch ( $this->type ) {
case self::TYPE_ASYNC:
$action_id = $this->register_async();
break;
case self::TYPE_RECURRING:
$action_id = $this->register_recurring();
break;
case self::TYPE_ONCE:
$action_id = $this->register_once();
break;
}
return $action_id;
}
/**
* Register the async task.
*
* @since 2.1.0
*
* @return null|string Action ID.
*/
protected function register_async() {
if ( ! function_exists( 'as_enqueue_async_action' ) ) {
return null;
}
return as_enqueue_async_action(
$this->action,
[ 'tasks_meta_id' => $this->meta_id ],
Tasks::GROUP
);
}
/**
* Register the recurring task.
*
* @since 2.1.0
*
* @return null|string Action ID.
*/
protected function register_recurring() {
if ( ! function_exists( 'as_schedule_recurring_action' ) ) {
return null;
}
return as_schedule_recurring_action(
$this->timestamp,
$this->interval,
$this->action,
[ 'tasks_meta_id' => $this->meta_id ],
Tasks::GROUP
);
}
/**
* Register the one-time task.
*
* @since 2.1.0
*
* @return null|string Action ID.
*/
protected function register_once() {
if ( ! function_exists( 'as_schedule_single_action' ) ) {
return null;
}
return as_schedule_single_action(
$this->timestamp,
$this->action,
[ 'tasks_meta_id' => $this->meta_id ],
Tasks::GROUP
);
}
/**
* Cancel all occurrences of this task.
*
* @since 2.1.0
*
* @return null|bool|string Null if no matching action found,
* false if AS library is missing,
* string of the scheduled action ID if a scheduled action was found and unscheduled.
*/
public function cancel() {
// Exit if AS function does not exist.
if ( ! function_exists( 'as_unschedule_all_actions' ) ) {
return false;
}
return as_unschedule_all_actions( $this->action );
}
}

View File

@ -0,0 +1,150 @@
<?php
namespace WPMailSMTP\Tasks;
/**
* Class Tasks manages the tasks queue and provides API to work with it.
*
* @since 2.1.0
*/
class Tasks {
/**
* Group that will be assigned to all actions.
*
* @since 2.1.0
*/
const GROUP = 'wp_mail_smtp';
/**
* Perform certain things on class init.
*
* @since 2.1.0
*/
public function init() {
// Register tasks.
foreach ( $this->get_tasks() as $task ) {
if ( ! is_subclass_of( $task, '\WPMailSMTP\Tasks\Task' ) ) {
continue;
}
$new_task = new $task();
// Run the init method, if a task has one defined.
if ( method_exists( $new_task, 'init' ) ) {
$new_task->init();
}
}
add_action( 'admin_menu', array( $this, 'admin_hide_as_menu' ), PHP_INT_MAX );
}
/**
* Get the list of default scheduled tasks.
* Tasks, that are fired under certain specific circumstances
* (like sending emails) are not listed here.
*
* @since 2.1.0
*
* @return Task[] List of tasks classes.
*/
public function get_tasks() {
return apply_filters( 'wp_mail_smtp_tasks_get_tasks', array() );
}
/**
* Hide Action Scheduler admin area when not in debug mode.
*
* @since 2.1.0
*/
public function admin_hide_as_menu() {
// Filter to redefine that WP Mail SMTP hides Tools > Action Scheduler menu item.
if ( apply_filters( 'wp_mail_smtp_tasks_admin_hide_as_menu', true ) ) {
remove_submenu_page( 'tools.php', 'action-scheduler' );
}
}
/**
* Create a new task.
* Used for "inline" tasks, that require additional information
* from the plugin runtime before they can be scheduled.
*
* Example:
* wp_mail_smtp()->get( 'tasks' )
* ->create( 'i_am_the_dude' )
* ->async()
* ->params( 'The Big Lebowski', 1998 )
* ->register();
*
* This `i_am_the_dude` action will be later processed as:
* add_action( 'i_am_the_dude', 'thats_what_you_call_me' );
*
* @since 2.1.0
*
* @param string $action Action that will be used as a hook.
*
* @return \WPMailSMTP\Tasks\Task
*/
public function create( $action ) {
return new Task( $action );
}
/**
* Cancel all the AS actions for a group.
*
* @since 2.1.0
*
* @param string $group Group to cancel all actions for.
*/
public function cancel_all( $group = '' ) {
if ( empty( $group ) ) {
$group = self::GROUP;
} else {
$group = sanitize_key( $group );
}
if ( class_exists( 'ActionScheduler_DBStore' ) ) {
\ActionScheduler_DBStore::instance()->cancel_actions_by_group( $group );
}
}
/**
* Whether ActionScheduler thinks that it has migrated or not.
*
* @since 2.1.0
*
* @return bool
*/
public function is_usable() {
// No tasks if ActionScheduler wasn't loaded.
if ( ! class_exists( 'ActionScheduler_DataController' ) ) {
return false;
}
return \ActionScheduler_DataController::is_migration_complete();
}
/**
* Whether task has been scheduled and is pending.
*
* @since 2.1.0
*
* @param string $hook Hook to check for.
*
* @return bool
*/
public function is_scheduled( $hook ) {
if ( ! function_exists( 'as_next_scheduled_action' ) ) {
return false;
}
return as_next_scheduled_action( $hook );
}
}

View File

@ -18,24 +18,32 @@ class WP {
*/ */
protected static $admin_notices = array(); protected static $admin_notices = array();
/** /**
* CSS class for a success notice.
*
* @since 1.0.0 * @since 1.0.0
* *
* @var string * @var string
*/ */
const ADMIN_NOTICE_SUCCESS = 'notice-success'; const ADMIN_NOTICE_SUCCESS = 'notice-success';
/** /**
* CSS class for an error notice.
*
* @since 1.0.0 * @since 1.0.0
* *
* @var string * @var string
*/ */
const ADMIN_NOTICE_ERROR = 'notice-error'; const ADMIN_NOTICE_ERROR = 'notice-error';
/** /**
* CSS class for an info notice.
*
* @since 1.0.0 * @since 1.0.0
* *
* @var string * @var string
*/ */
const ADMIN_NOTICE_INFO = 'notice-info'; const ADMIN_NOTICE_INFO = 'notice-info';
/** /**
* CSS class for a warning notice.
*
* @since 1.0.0 * @since 1.0.0
* *
* @var string * @var string
@ -43,7 +51,7 @@ class WP {
const ADMIN_NOTICE_WARNING = 'notice-warning'; const ADMIN_NOTICE_WARNING = 'notice-warning';
/** /**
* True is WP is processing an AJAX call. * True if WP is processing an AJAX call.
* *
* @since 1.0.0 * @since 1.0.0
* *
@ -103,7 +111,7 @@ class WP {
<div class="notice wp-mail-smtp-notice <?php echo esc_attr( $notice['class'] ); ?> notice <?php echo esc_attr( $dismissible ); ?>"> <div class="notice wp-mail-smtp-notice <?php echo esc_attr( $notice['class'] ); ?> notice <?php echo esc_attr( $dismissible ); ?>">
<p> <p>
<?php echo $notice['message']; ?> <?php echo wp_kses_post( $notice['message'] ); ?>
</p> </p>
</div> </div>
@ -160,7 +168,7 @@ class WP {
* *
* @since 1.5.0 * @since 1.5.0
* *
* @param string $string * @param string $string String we want to test if it's json.
* *
* @return bool * @return bool
*/ */
@ -178,8 +186,7 @@ class WP {
*/ */
public static function datetime_format() { public static function datetime_format() {
return sprintf( return sprintf( /* translators: %1$s - date, \a\t - specially escaped "at", %2$s - time. */
/* translators: %1$s - date, \a\t - specially escaped "at", %2$s - time. */
esc_html__( '%1$s \a\t %2$s', 'wp-mail-smtp' ), esc_html__( '%1$s \a\t %2$s', 'wp-mail-smtp' ),
get_option( 'date_format' ), get_option( 'date_format' ),
get_option( 'time_format' ) get_option( 'time_format' )
@ -199,14 +206,14 @@ class WP {
} }
/** /**
* Sanitize the value, similar to sanitize_text_field(), but a bit differently. * Sanitize the value, similar to `sanitize_text_field()`, but a bit differently.
* It preserves `<` and `>` for non-HTML tags. * It preserves `<` and `>` for non-HTML tags.
* *
* @since 1.5.0 * @since 1.5.0
* *
* @param string $value * @param string $value String we want to sanitize.
* *
* @return mixed|string|string[]|null * @return string
*/ */
public static function sanitize_value( $value ) { public static function sanitize_value( $value ) {

View File

@ -1,80 +1,99 @@
<?php <?php
/** /**
* Uninstall all WP Mail SMTP data. * Uninstall all WP Mail SMTP data.
* *
* @since 1.3.0 * @since 1.3.0
*/ */
// Exit if accessed directly. // Exit if accessed directly.
if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) { if ( ! defined( 'WP_UNINSTALL_PLUGIN' ) ) {
exit; exit;
} }
// Load plugin file. // Load plugin file.
require_once 'wp_mail_smtp.php'; require_once 'wp_mail_smtp.php';
// Confirm user has decided to remove all data, otherwise stop. // Confirm user has decided to remove all data, otherwise stop.
$settings = get_option( 'wp_mail_smtp', array() ); $settings = get_option( 'wp_mail_smtp', array() );
if ( empty( $settings['general']['uninstall'] ) ) { if ( empty( $settings['general']['uninstall'] ) ) {
return; return;
} }
/* /*
* Remove options. * Remove Legacy options.
*/ */
$options = array( $options = array(
'wp_mail_smtp_initial_version', '_amn_smtp_last_checked',
'wp_mail_smtp_version', 'pepipost_ssl',
'wp_mail_smtp_debug', 'pepipost_port',
'wp_mail_smtp', 'pepipost_pass',
'_amn_smtp_last_checked', 'pepipost_user',
// Legacy options. 'smtp_pass',
'pepipost_ssl', 'smtp_user',
'pepipost_port', 'smtp_auth',
'pepipost_pass', 'smtp_ssl',
'pepipost_user', 'smtp_port',
'smtp_pass', 'smtp_host',
'smtp_user', 'mail_set_return_path',
'smtp_auth', 'mailer',
'smtp_ssl', 'mail_from_name',
'smtp_port', 'mail_from',
'smtp_host', );
'mail_set_return_path',
'mailer', foreach ( $options as $option ) {
'mail_from_name', delete_option( $option );
'mail_from', }
'wp_mail_smtp_am_notifications_hidden',
); global $wpdb;
foreach ( $options as $option ) { // Delete plugin settings.
delete_option( $option ); $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE 'wp\_mail\_smtp%'" );
}
// Delete plugin user meta.
/* $wpdb->query( "DELETE FROM {$wpdb->usermeta} WHERE meta_key LIKE 'wp\_mail\_smtp\_%'" );
* Remove product announcements.
*/ // Remove any transients we've left behind.
$announcements = get_posts( $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_transient\_wp\_mail\_smtp\_%'" );
array( $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_site\_transient\_wp\_mail\_smtp\_%'" );
'post_type' => array( 'amn_smtp' ), $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_transient\_timeout\_wp\_mail\_smtp\_%'" );
'post_status' => 'any', $wpdb->query( "DELETE FROM {$wpdb->options} WHERE option_name LIKE '\_site\_transient\_timeout\_wp\_mail\_smtp\_%'" );
'numberposts' => - 1,
'fields' => 'ids', /*
) * Remove product announcements.
); */
if ( ! empty( $announcements ) ) { $announcements = get_posts(
foreach ( $announcements as $announcement ) { array(
wp_delete_post( $announcement, true ); 'post_type' => array( 'amn_smtp' ),
} 'post_status' => 'any',
} 'numberposts' => - 1,
'fields' => 'ids',
/* )
* Logs for Pro plugin only. );
*/ if ( ! empty( $announcements ) ) {
if ( function_exists( 'wp_mail_smtp' ) && wp_mail_smtp()->is_pro() ) { foreach ( $announcements as $announcement ) {
// DB version. wp_delete_post( $announcement, true );
delete_option( 'wp_mail_smtp_logs_db_version' ); }
// DB table. }
global $wpdb;
$table = \WPMailSMTP\Pro\Emails\Logs\Logs::get_table_name(); /*
$wpdb->query( "DROP TABLE $table;" ); // phpcs:ignore * Logs for Pro plugin only.
} */
if (
function_exists( 'wp_mail_smtp' ) &&
is_readable( wp_mail_smtp()->plugin_path . '/src/Pro/Pro.php' )
) {
// DB table.
$logs_table = \WPMailSMTP\Pro\Emails\Logs\Logs::get_table_name();
$wpdb->query( "DROP TABLE IF EXISTS $logs_table;" ); // phpcs:ignore WordPress.DB
}
/*
* Drop all Action Scheduler data.
*/
require_once dirname( __FILE__ ) . '/vendor/woocommerce/action-scheduler/action-scheduler.php';
// Unschedule all plugin ActionScheduler actions.
( new \WPMailSMTP\Tasks\Tasks() )->cancel_all();
$meta_table = \WPMailSMTP\Tasks\Meta::get_table_name();
$wpdb->query( "DROP TABLE IF EXISTS $meta_table;" ); // phpcs:ignore WordPress.DB

View File

@ -9,6 +9,9 @@ return array(
'7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php', '7b11c4dc42b3b3023073cb14e519683c' => $vendorDir . '/ralouphie/getallheaders/src/getallheaders.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php', 'a0edc8309cc5e1d60e3047b5df6b7052' => $vendorDir . '/guzzlehttp/psr7/src/functions_include.php',
'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php', 'c964ee0ededf28c96ebd9db5099ef910' => $vendorDir . '/guzzlehttp/promises/src/functions_include.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => $vendorDir . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => $vendorDir . '/symfony/polyfill-php72/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => $vendorDir . '/symfony/polyfill-intl-idn/bootstrap.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => $vendorDir . '/guzzlehttp/guzzle/src/functions_include.php',
'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php', 'decc78cc4436b1292c6c0d151b19445c' => $vendorDir . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
); );

View File

@ -8,6 +8,9 @@ $baseDir = dirname($vendorDir);
return array( return array(
'phpseclib\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'), 'phpseclib\\' => array($vendorDir . '/phpseclib/phpseclib/phpseclib'),
'WPMailSMTP\\' => array($baseDir . '/src'), 'WPMailSMTP\\' => array($baseDir . '/src'),
'Symfony\\Polyfill\\Php72\\' => array($vendorDir . '/symfony/polyfill-php72'),
'Symfony\\Polyfill\\Mbstring\\' => array($vendorDir . '/symfony/polyfill-mbstring'),
'Symfony\\Polyfill\\Intl\\Idn\\' => array($vendorDir . '/symfony/polyfill-intl-idn'),
'SendinBlue\\Client\\' => array($vendorDir . '/sendinblue/api-v3-sdk/lib'), 'SendinBlue\\Client\\' => array($vendorDir . '/sendinblue/api-v3-sdk/lib'),
'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'), 'Psr\\Log\\' => array($vendorDir . '/psr/log/Psr/Log'),
'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'), 'Psr\\Http\\Message\\' => array($vendorDir . '/psr/http-message/src'),

View File

@ -10,6 +10,9 @@ class ComposerStaticInit72f613a3d0c2cc77892490951b6e5352
'7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php', '7b11c4dc42b3b3023073cb14e519683c' => __DIR__ . '/..' . '/ralouphie/getallheaders/src/getallheaders.php',
'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php', 'a0edc8309cc5e1d60e3047b5df6b7052' => __DIR__ . '/..' . '/guzzlehttp/psr7/src/functions_include.php',
'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php', 'c964ee0ededf28c96ebd9db5099ef910' => __DIR__ . '/..' . '/guzzlehttp/promises/src/functions_include.php',
'0e6d7bf4a5811bfa5cf40c5ccd6fae6a' => __DIR__ . '/..' . '/symfony/polyfill-mbstring/bootstrap.php',
'25072dd6e2470089de65ae7bf11d3109' => __DIR__ . '/..' . '/symfony/polyfill-php72/bootstrap.php',
'f598d06aa772fa33d905e87be6398fb1' => __DIR__ . '/..' . '/symfony/polyfill-intl-idn/bootstrap.php',
'37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php', '37a3dc5111fe8f707ab4c132ef1dbc62' => __DIR__ . '/..' . '/guzzlehttp/guzzle/src/functions_include.php',
'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php', 'decc78cc4436b1292c6c0d151b19445c' => __DIR__ . '/..' . '/phpseclib/phpseclib/phpseclib/bootstrap.php',
); );
@ -25,6 +28,9 @@ class ComposerStaticInit72f613a3d0c2cc77892490951b6e5352
), ),
'S' => 'S' =>
array ( array (
'Symfony\\Polyfill\\Php72\\' => 23,
'Symfony\\Polyfill\\Mbstring\\' => 26,
'Symfony\\Polyfill\\Intl\\Idn\\' => 26,
'SendinBlue\\Client\\' => 18, 'SendinBlue\\Client\\' => 18,
), ),
'P' => 'P' =>
@ -63,6 +69,18 @@ class ComposerStaticInit72f613a3d0c2cc77892490951b6e5352
array ( array (
0 => __DIR__ . '/../..' . '/src', 0 => __DIR__ . '/../..' . '/src',
), ),
'Symfony\\Polyfill\\Php72\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-php72',
),
'Symfony\\Polyfill\\Mbstring\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-mbstring',
),
'Symfony\\Polyfill\\Intl\\Idn\\' =>
array (
0 => __DIR__ . '/..' . '/symfony/polyfill-intl-idn',
),
'SendinBlue\\Client\\' => 'SendinBlue\\Client\\' =>
array ( array (
0 => __DIR__ . '/..' . '/sendinblue/api-v3-sdk/lib', 0 => __DIR__ . '/..' . '/sendinblue/api-v3-sdk/lib',

View File

@ -19,8 +19,7 @@
* Service definition for Gmail (v1). * Service definition for Gmail (v1).
* *
* <p> * <p>
* The Gmail API lets you view and manage Gmail mailbox data like threads, * Access Gmail mailboxes including sending user email.</p>
* messages, and labels.</p>
* *
* <p> * <p>
* For more information about this service, see the API * For more information about this service, see the API
@ -98,8 +97,8 @@ class Google_Service_Gmail extends Google_Service
{ {
parent::__construct($client); parent::__construct($client);
$this->rootUrl = $rootUrl ?: 'https://www.googleapis.com/'; $this->rootUrl = $rootUrl ?: 'https://www.googleapis.com/';
$this->servicePath = ''; $this->servicePath = 'gmail/v1/users/';
$this->batchPath = 'batch'; $this->batchPath = 'batch/gmail/v1';
$this->version = 'v1'; $this->version = 'v1';
$this->serviceName = 'gmail'; $this->serviceName = 'gmail';
@ -110,7 +109,7 @@ class Google_Service_Gmail extends Google_Service
array( array(
'methods' => array( 'methods' => array(
'getProfile' => array( 'getProfile' => array(
'path' => 'gmail/v1/users/{userId}/profile', 'path' => '{userId}/profile',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -120,7 +119,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'stop' => array( ),'stop' => array(
'path' => 'gmail/v1/users/{userId}/stop', 'path' => '{userId}/stop',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -130,7 +129,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'watch' => array( ),'watch' => array(
'path' => 'gmail/v1/users/{userId}/watch', 'path' => '{userId}/watch',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -150,7 +149,7 @@ class Google_Service_Gmail extends Google_Service
array( array(
'methods' => array( 'methods' => array(
'create' => array( 'create' => array(
'path' => 'gmail/v1/users/{userId}/drafts', 'path' => '{userId}/drafts',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -160,7 +159,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'delete' => array( ),'delete' => array(
'path' => 'gmail/v1/users/{userId}/drafts/{id}', 'path' => '{userId}/drafts/{id}',
'httpMethod' => 'DELETE', 'httpMethod' => 'DELETE',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -175,7 +174,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'get' => array( ),'get' => array(
'path' => 'gmail/v1/users/{userId}/drafts/{id}', 'path' => '{userId}/drafts/{id}',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -194,7 +193,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'list' => array( ),'list' => array(
'path' => 'gmail/v1/users/{userId}/drafts', 'path' => '{userId}/drafts',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -206,6 +205,10 @@ class Google_Service_Gmail extends Google_Service
'location' => 'query', 'location' => 'query',
'type' => 'boolean', 'type' => 'boolean',
), ),
'maxResults' => array(
'location' => 'query',
'type' => 'integer',
),
'pageToken' => array( 'pageToken' => array(
'location' => 'query', 'location' => 'query',
'type' => 'string', 'type' => 'string',
@ -214,13 +217,9 @@ class Google_Service_Gmail extends Google_Service
'location' => 'query', 'location' => 'query',
'type' => 'string', 'type' => 'string',
), ),
'maxResults' => array(
'location' => 'query',
'type' => 'integer',
),
), ),
),'send' => array( ),'send' => array(
'path' => 'gmail/v1/users/{userId}/drafts/send', 'path' => '{userId}/drafts/send',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -230,7 +229,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'update' => array( ),'update' => array(
'path' => 'gmail/v1/users/{userId}/drafts/{id}', 'path' => '{userId}/drafts/{id}',
'httpMethod' => 'PUT', 'httpMethod' => 'PUT',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -255,7 +254,7 @@ class Google_Service_Gmail extends Google_Service
array( array(
'methods' => array( 'methods' => array(
'list' => array( 'list' => array(
'path' => 'gmail/v1/users/{userId}/history', 'path' => '{userId}/history',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -263,9 +262,10 @@ class Google_Service_Gmail extends Google_Service
'type' => 'string', 'type' => 'string',
'required' => true, 'required' => true,
), ),
'pageToken' => array( 'historyTypes' => array(
'location' => 'query', 'location' => 'query',
'type' => 'string', 'type' => 'string',
'repeated' => true,
), ),
'labelId' => array( 'labelId' => array(
'location' => 'query', 'location' => 'query',
@ -275,10 +275,9 @@ class Google_Service_Gmail extends Google_Service
'location' => 'query', 'location' => 'query',
'type' => 'integer', 'type' => 'integer',
), ),
'historyTypes' => array( 'pageToken' => array(
'location' => 'query', 'location' => 'query',
'type' => 'string', 'type' => 'string',
'repeated' => true,
), ),
'startHistoryId' => array( 'startHistoryId' => array(
'location' => 'query', 'location' => 'query',
@ -296,7 +295,7 @@ class Google_Service_Gmail extends Google_Service
array( array(
'methods' => array( 'methods' => array(
'create' => array( 'create' => array(
'path' => 'gmail/v1/users/{userId}/labels', 'path' => '{userId}/labels',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -306,7 +305,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'delete' => array( ),'delete' => array(
'path' => 'gmail/v1/users/{userId}/labels/{id}', 'path' => '{userId}/labels/{id}',
'httpMethod' => 'DELETE', 'httpMethod' => 'DELETE',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -321,7 +320,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'get' => array( ),'get' => array(
'path' => 'gmail/v1/users/{userId}/labels/{id}', 'path' => '{userId}/labels/{id}',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -336,7 +335,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'list' => array( ),'list' => array(
'path' => 'gmail/v1/users/{userId}/labels', 'path' => '{userId}/labels',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -346,7 +345,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'patch' => array( ),'patch' => array(
'path' => 'gmail/v1/users/{userId}/labels/{id}', 'path' => '{userId}/labels/{id}',
'httpMethod' => 'PATCH', 'httpMethod' => 'PATCH',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -361,7 +360,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'update' => array( ),'update' => array(
'path' => 'gmail/v1/users/{userId}/labels/{id}', 'path' => '{userId}/labels/{id}',
'httpMethod' => 'PUT', 'httpMethod' => 'PUT',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -386,7 +385,7 @@ class Google_Service_Gmail extends Google_Service
array( array(
'methods' => array( 'methods' => array(
'batchDelete' => array( 'batchDelete' => array(
'path' => 'gmail/v1/users/{userId}/messages/batchDelete', 'path' => '{userId}/messages/batchDelete',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -396,7 +395,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'batchModify' => array( ),'batchModify' => array(
'path' => 'gmail/v1/users/{userId}/messages/batchModify', 'path' => '{userId}/messages/batchModify',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -406,7 +405,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'delete' => array( ),'delete' => array(
'path' => 'gmail/v1/users/{userId}/messages/{id}', 'path' => '{userId}/messages/{id}',
'httpMethod' => 'DELETE', 'httpMethod' => 'DELETE',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -421,7 +420,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'get' => array( ),'get' => array(
'path' => 'gmail/v1/users/{userId}/messages/{id}', 'path' => '{userId}/messages/{id}',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -434,18 +433,18 @@ class Google_Service_Gmail extends Google_Service
'type' => 'string', 'type' => 'string',
'required' => true, 'required' => true,
), ),
'format' => array(
'location' => 'query',
'type' => 'string',
),
'metadataHeaders' => array( 'metadataHeaders' => array(
'location' => 'query', 'location' => 'query',
'type' => 'string', 'type' => 'string',
'repeated' => true, 'repeated' => true,
), ),
'format' => array(
'location' => 'query',
'type' => 'string',
),
), ),
),'import' => array( ),'import' => array(
'path' => 'gmail/v1/users/{userId}/messages/import', 'path' => '{userId}/messages/import',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -453,7 +452,7 @@ class Google_Service_Gmail extends Google_Service
'type' => 'string', 'type' => 'string',
'required' => true, 'required' => true,
), ),
'processForCalendar' => array( 'deleted' => array(
'location' => 'query', 'location' => 'query',
'type' => 'boolean', 'type' => 'boolean',
), ),
@ -465,13 +464,13 @@ class Google_Service_Gmail extends Google_Service
'location' => 'query', 'location' => 'query',
'type' => 'boolean', 'type' => 'boolean',
), ),
'deleted' => array( 'processForCalendar' => array(
'location' => 'query', 'location' => 'query',
'type' => 'boolean', 'type' => 'boolean',
), ),
), ),
),'insert' => array( ),'insert' => array(
'path' => 'gmail/v1/users/{userId}/messages', 'path' => '{userId}/messages',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -479,17 +478,17 @@ class Google_Service_Gmail extends Google_Service
'type' => 'string', 'type' => 'string',
'required' => true, 'required' => true,
), ),
'internalDateSource' => array(
'location' => 'query',
'type' => 'string',
),
'deleted' => array( 'deleted' => array(
'location' => 'query', 'location' => 'query',
'type' => 'boolean', 'type' => 'boolean',
), ),
'internalDateSource' => array(
'location' => 'query',
'type' => 'string',
),
), ),
),'list' => array( ),'list' => array(
'path' => 'gmail/v1/users/{userId}/messages', 'path' => '{userId}/messages',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -501,26 +500,26 @@ class Google_Service_Gmail extends Google_Service
'location' => 'query', 'location' => 'query',
'type' => 'boolean', 'type' => 'boolean',
), ),
'pageToken' => array(
'location' => 'query',
'type' => 'string',
),
'labelIds' => array( 'labelIds' => array(
'location' => 'query', 'location' => 'query',
'type' => 'string', 'type' => 'string',
'repeated' => true, 'repeated' => true,
), ),
'q' => array(
'location' => 'query',
'type' => 'string',
),
'maxResults' => array( 'maxResults' => array(
'location' => 'query', 'location' => 'query',
'type' => 'integer', 'type' => 'integer',
), ),
'pageToken' => array(
'location' => 'query',
'type' => 'string',
),
'q' => array(
'location' => 'query',
'type' => 'string',
),
), ),
),'modify' => array( ),'modify' => array(
'path' => 'gmail/v1/users/{userId}/messages/{id}/modify', 'path' => '{userId}/messages/{id}/modify',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -535,7 +534,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'send' => array( ),'send' => array(
'path' => 'gmail/v1/users/{userId}/messages/send', 'path' => '{userId}/messages/send',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -545,7 +544,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'trash' => array( ),'trash' => array(
'path' => 'gmail/v1/users/{userId}/messages/{id}/trash', 'path' => '{userId}/messages/{id}/trash',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -560,7 +559,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'untrash' => array( ),'untrash' => array(
'path' => 'gmail/v1/users/{userId}/messages/{id}/untrash', 'path' => '{userId}/messages/{id}/untrash',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -585,7 +584,7 @@ class Google_Service_Gmail extends Google_Service
array( array(
'methods' => array( 'methods' => array(
'get' => array( 'get' => array(
'path' => 'gmail/v1/users/{userId}/messages/{messageId}/attachments/{id}', 'path' => '{userId}/messages/{messageId}/attachments/{id}',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -615,7 +614,7 @@ class Google_Service_Gmail extends Google_Service
array( array(
'methods' => array( 'methods' => array(
'getAutoForwarding' => array( 'getAutoForwarding' => array(
'path' => 'gmail/v1/users/{userId}/settings/autoForwarding', 'path' => '{userId}/settings/autoForwarding',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -625,7 +624,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'getImap' => array( ),'getImap' => array(
'path' => 'gmail/v1/users/{userId}/settings/imap', 'path' => '{userId}/settings/imap',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -635,7 +634,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'getLanguage' => array( ),'getLanguage' => array(
'path' => 'gmail/v1/users/{userId}/settings/language', 'path' => '{userId}/settings/language',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -645,7 +644,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'getPop' => array( ),'getPop' => array(
'path' => 'gmail/v1/users/{userId}/settings/pop', 'path' => '{userId}/settings/pop',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -655,7 +654,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'getVacation' => array( ),'getVacation' => array(
'path' => 'gmail/v1/users/{userId}/settings/vacation', 'path' => '{userId}/settings/vacation',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -665,7 +664,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'updateAutoForwarding' => array( ),'updateAutoForwarding' => array(
'path' => 'gmail/v1/users/{userId}/settings/autoForwarding', 'path' => '{userId}/settings/autoForwarding',
'httpMethod' => 'PUT', 'httpMethod' => 'PUT',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -675,7 +674,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'updateImap' => array( ),'updateImap' => array(
'path' => 'gmail/v1/users/{userId}/settings/imap', 'path' => '{userId}/settings/imap',
'httpMethod' => 'PUT', 'httpMethod' => 'PUT',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -685,7 +684,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'updateLanguage' => array( ),'updateLanguage' => array(
'path' => 'gmail/v1/users/{userId}/settings/language', 'path' => '{userId}/settings/language',
'httpMethod' => 'PUT', 'httpMethod' => 'PUT',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -695,7 +694,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'updatePop' => array( ),'updatePop' => array(
'path' => 'gmail/v1/users/{userId}/settings/pop', 'path' => '{userId}/settings/pop',
'httpMethod' => 'PUT', 'httpMethod' => 'PUT',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -705,7 +704,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'updateVacation' => array( ),'updateVacation' => array(
'path' => 'gmail/v1/users/{userId}/settings/vacation', 'path' => '{userId}/settings/vacation',
'httpMethod' => 'PUT', 'httpMethod' => 'PUT',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -725,7 +724,7 @@ class Google_Service_Gmail extends Google_Service
array( array(
'methods' => array( 'methods' => array(
'create' => array( 'create' => array(
'path' => 'gmail/v1/users/{userId}/settings/delegates', 'path' => '{userId}/settings/delegates',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -735,7 +734,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'delete' => array( ),'delete' => array(
'path' => 'gmail/v1/users/{userId}/settings/delegates/{delegateEmail}', 'path' => '{userId}/settings/delegates/{delegateEmail}',
'httpMethod' => 'DELETE', 'httpMethod' => 'DELETE',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -750,7 +749,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'get' => array( ),'get' => array(
'path' => 'gmail/v1/users/{userId}/settings/delegates/{delegateEmail}', 'path' => '{userId}/settings/delegates/{delegateEmail}',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -765,7 +764,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'list' => array( ),'list' => array(
'path' => 'gmail/v1/users/{userId}/settings/delegates', 'path' => '{userId}/settings/delegates',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -785,7 +784,7 @@ class Google_Service_Gmail extends Google_Service
array( array(
'methods' => array( 'methods' => array(
'create' => array( 'create' => array(
'path' => 'gmail/v1/users/{userId}/settings/filters', 'path' => '{userId}/settings/filters',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -795,7 +794,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'delete' => array( ),'delete' => array(
'path' => 'gmail/v1/users/{userId}/settings/filters/{id}', 'path' => '{userId}/settings/filters/{id}',
'httpMethod' => 'DELETE', 'httpMethod' => 'DELETE',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -810,7 +809,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'get' => array( ),'get' => array(
'path' => 'gmail/v1/users/{userId}/settings/filters/{id}', 'path' => '{userId}/settings/filters/{id}',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -825,7 +824,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'list' => array( ),'list' => array(
'path' => 'gmail/v1/users/{userId}/settings/filters', 'path' => '{userId}/settings/filters',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -845,7 +844,7 @@ class Google_Service_Gmail extends Google_Service
array( array(
'methods' => array( 'methods' => array(
'create' => array( 'create' => array(
'path' => 'gmail/v1/users/{userId}/settings/forwardingAddresses', 'path' => '{userId}/settings/forwardingAddresses',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -855,7 +854,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'delete' => array( ),'delete' => array(
'path' => 'gmail/v1/users/{userId}/settings/forwardingAddresses/{forwardingEmail}', 'path' => '{userId}/settings/forwardingAddresses/{forwardingEmail}',
'httpMethod' => 'DELETE', 'httpMethod' => 'DELETE',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -870,7 +869,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'get' => array( ),'get' => array(
'path' => 'gmail/v1/users/{userId}/settings/forwardingAddresses/{forwardingEmail}', 'path' => '{userId}/settings/forwardingAddresses/{forwardingEmail}',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -885,7 +884,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'list' => array( ),'list' => array(
'path' => 'gmail/v1/users/{userId}/settings/forwardingAddresses', 'path' => '{userId}/settings/forwardingAddresses',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -905,7 +904,7 @@ class Google_Service_Gmail extends Google_Service
array( array(
'methods' => array( 'methods' => array(
'create' => array( 'create' => array(
'path' => 'gmail/v1/users/{userId}/settings/sendAs', 'path' => '{userId}/settings/sendAs',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -915,7 +914,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'delete' => array( ),'delete' => array(
'path' => 'gmail/v1/users/{userId}/settings/sendAs/{sendAsEmail}', 'path' => '{userId}/settings/sendAs/{sendAsEmail}',
'httpMethod' => 'DELETE', 'httpMethod' => 'DELETE',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -930,7 +929,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'get' => array( ),'get' => array(
'path' => 'gmail/v1/users/{userId}/settings/sendAs/{sendAsEmail}', 'path' => '{userId}/settings/sendAs/{sendAsEmail}',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -945,7 +944,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'list' => array( ),'list' => array(
'path' => 'gmail/v1/users/{userId}/settings/sendAs', 'path' => '{userId}/settings/sendAs',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -955,7 +954,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'patch' => array( ),'patch' => array(
'path' => 'gmail/v1/users/{userId}/settings/sendAs/{sendAsEmail}', 'path' => '{userId}/settings/sendAs/{sendAsEmail}',
'httpMethod' => 'PATCH', 'httpMethod' => 'PATCH',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -970,7 +969,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'update' => array( ),'update' => array(
'path' => 'gmail/v1/users/{userId}/settings/sendAs/{sendAsEmail}', 'path' => '{userId}/settings/sendAs/{sendAsEmail}',
'httpMethod' => 'PUT', 'httpMethod' => 'PUT',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -985,7 +984,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'verify' => array( ),'verify' => array(
'path' => 'gmail/v1/users/{userId}/settings/sendAs/{sendAsEmail}/verify', 'path' => '{userId}/settings/sendAs/{sendAsEmail}/verify',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -1010,7 +1009,7 @@ class Google_Service_Gmail extends Google_Service
array( array(
'methods' => array( 'methods' => array(
'delete' => array( 'delete' => array(
'path' => 'gmail/v1/users/{userId}/settings/sendAs/{sendAsEmail}/smimeInfo/{id}', 'path' => '{userId}/settings/sendAs/{sendAsEmail}/smimeInfo/{id}',
'httpMethod' => 'DELETE', 'httpMethod' => 'DELETE',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -1030,7 +1029,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'get' => array( ),'get' => array(
'path' => 'gmail/v1/users/{userId}/settings/sendAs/{sendAsEmail}/smimeInfo/{id}', 'path' => '{userId}/settings/sendAs/{sendAsEmail}/smimeInfo/{id}',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -1050,7 +1049,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'insert' => array( ),'insert' => array(
'path' => 'gmail/v1/users/{userId}/settings/sendAs/{sendAsEmail}/smimeInfo', 'path' => '{userId}/settings/sendAs/{sendAsEmail}/smimeInfo',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -1065,7 +1064,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'list' => array( ),'list' => array(
'path' => 'gmail/v1/users/{userId}/settings/sendAs/{sendAsEmail}/smimeInfo', 'path' => '{userId}/settings/sendAs/{sendAsEmail}/smimeInfo',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -1080,7 +1079,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'setDefault' => array( ),'setDefault' => array(
'path' => 'gmail/v1/users/{userId}/settings/sendAs/{sendAsEmail}/smimeInfo/{id}/setDefault', 'path' => '{userId}/settings/sendAs/{sendAsEmail}/smimeInfo/{id}/setDefault',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -1110,7 +1109,7 @@ class Google_Service_Gmail extends Google_Service
array( array(
'methods' => array( 'methods' => array(
'delete' => array( 'delete' => array(
'path' => 'gmail/v1/users/{userId}/threads/{id}', 'path' => '{userId}/threads/{id}',
'httpMethod' => 'DELETE', 'httpMethod' => 'DELETE',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -1125,7 +1124,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'get' => array( ),'get' => array(
'path' => 'gmail/v1/users/{userId}/threads/{id}', 'path' => '{userId}/threads/{id}',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -1138,18 +1137,18 @@ class Google_Service_Gmail extends Google_Service
'type' => 'string', 'type' => 'string',
'required' => true, 'required' => true,
), ),
'format' => array(
'location' => 'query',
'type' => 'string',
),
'metadataHeaders' => array( 'metadataHeaders' => array(
'location' => 'query', 'location' => 'query',
'type' => 'string', 'type' => 'string',
'repeated' => true, 'repeated' => true,
), ),
'format' => array(
'location' => 'query',
'type' => 'string',
),
), ),
),'list' => array( ),'list' => array(
'path' => 'gmail/v1/users/{userId}/threads', 'path' => '{userId}/threads',
'httpMethod' => 'GET', 'httpMethod' => 'GET',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -1157,30 +1156,30 @@ class Google_Service_Gmail extends Google_Service
'type' => 'string', 'type' => 'string',
'required' => true, 'required' => true,
), ),
'pageToken' => array( 'includeSpamTrash' => array(
'location' => 'query', 'location' => 'query',
'type' => 'string', 'type' => 'boolean',
), ),
'labelIds' => array( 'labelIds' => array(
'location' => 'query', 'location' => 'query',
'type' => 'string', 'type' => 'string',
'repeated' => true, 'repeated' => true,
), ),
'q' => array(
'location' => 'query',
'type' => 'string',
),
'maxResults' => array( 'maxResults' => array(
'location' => 'query', 'location' => 'query',
'type' => 'integer', 'type' => 'integer',
), ),
'includeSpamTrash' => array( 'pageToken' => array(
'location' => 'query', 'location' => 'query',
'type' => 'boolean', 'type' => 'string',
),
'q' => array(
'location' => 'query',
'type' => 'string',
), ),
), ),
),'modify' => array( ),'modify' => array(
'path' => 'gmail/v1/users/{userId}/threads/{id}/modify', 'path' => '{userId}/threads/{id}/modify',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -1195,7 +1194,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'trash' => array( ),'trash' => array(
'path' => 'gmail/v1/users/{userId}/threads/{id}/trash', 'path' => '{userId}/threads/{id}/trash',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(
@ -1210,7 +1209,7 @@ class Google_Service_Gmail extends Google_Service
), ),
), ),
),'untrash' => array( ),'untrash' => array(
'path' => 'gmail/v1/users/{userId}/threads/{id}/untrash', 'path' => '{userId}/threads/{id}/untrash',
'httpMethod' => 'POST', 'httpMethod' => 'POST',
'parameters' => array( 'parameters' => array(
'userId' => array( 'userId' => array(

View File

@ -81,12 +81,12 @@ class Google_Service_Gmail_Resource_UsersDrafts extends Google_Service_Resource
* *
* @opt_param bool includeSpamTrash Include drafts from SPAM and TRASH in the * @opt_param bool includeSpamTrash Include drafts from SPAM and TRASH in the
* results. * results.
* @opt_param string maxResults Maximum number of drafts to return.
* @opt_param string pageToken Page token to retrieve a specific page of results * @opt_param string pageToken Page token to retrieve a specific page of results
* in the list. * in the list.
* @opt_param string q Only return draft messages matching the specified query. * @opt_param string q Only return draft messages matching the specified query.
* Supports the same query format as the Gmail search box. For example, * Supports the same query format as the Gmail search box. For example,
* "from:someuser@example.com rfc822msgid: is:unread". * "from:someuser@example.com rfc822msgid: is:unread".
* @opt_param string maxResults Maximum number of drafts to return.
* @return Google_Service_Gmail_ListDraftsResponse * @return Google_Service_Gmail_ListDraftsResponse
*/ */
public function listUsersDrafts($userId, $optParams = array()) public function listUsersDrafts($userId, $optParams = array())

View File

@ -34,11 +34,11 @@ class Google_Service_Gmail_Resource_UsersHistory extends Google_Service_Resource
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* *
* @opt_param string pageToken Page token to retrieve a specific page of results * @opt_param string historyTypes History types to be returned by the function
* in the list.
* @opt_param string labelId Only return messages with a label matching the ID. * @opt_param string labelId Only return messages with a label matching the ID.
* @opt_param string maxResults The maximum number of history records to return. * @opt_param string maxResults The maximum number of history records to return.
* @opt_param string historyTypes History types to be returned by the function * @opt_param string pageToken Page token to retrieve a specific page of results
* in the list.
* @opt_param string startHistoryId Required. Returns history records after the * @opt_param string startHistoryId Required. Returns history records after the
* specified startHistoryId. The supplied startHistoryId should be obtained from * specified startHistoryId. The supplied startHistoryId should be obtained from
* the historyId of a message, thread, or previous list response. History IDs * the historyId of a message, thread, or previous list response. History IDs
@ -46,7 +46,7 @@ class Google_Service_Gmail_Resource_UsersHistory extends Google_Service_Resource
* valid IDs. Supplying an invalid or out of date startHistoryId typically * valid IDs. Supplying an invalid or out of date startHistoryId typically
* returns an HTTP 404 error code. A historyId is typically valid for at least a * returns an HTTP 404 error code. A historyId is typically valid for at least a
* week, but in some rare circumstances may be valid for only a few hours. If * week, but in some rare circumstances may be valid for only a few hours. If
* you receive an HTTP 404 error response, your application should perform a * you receive an HTTP 404 error response, your application should perform a
* full sync. If you receive no nextPageToken in the response, there are no * full sync. If you receive no nextPageToken in the response, there are no
* updates to retrieve and you can store the returned historyId for a future * updates to retrieve and you can store the returned historyId for a future
* request. * request.

View File

@ -85,7 +85,8 @@ class Google_Service_Gmail_Resource_UsersLabels extends Google_Service_Resource
return $this->call('list', array($params), "Google_Service_Gmail_ListLabelsResponse"); return $this->call('list', array($params), "Google_Service_Gmail_ListLabelsResponse");
} }
/** /**
* Patch the specified label. (labels.patch) * Updates the specified label. This method supports patch semantics.
* (labels.patch)
* *
* @param string $userId The user's email address. The special value me can be * @param string $userId The user's email address. The special value me can be
* used to indicate the authenticated user. * used to indicate the authenticated user.

View File

@ -26,7 +26,7 @@
class Google_Service_Gmail_Resource_UsersMessages extends Google_Service_Resource class Google_Service_Gmail_Resource_UsersMessages extends Google_Service_Resource
{ {
/** /**
* Deletes many messages by message ID. Provides no guarantees that messages * Deletes many messages by message ID. Provides no guarantees that messages
* were not already deleted or even existed at all. (messages.batchDelete) * were not already deleted or even existed at all. (messages.batchDelete)
* *
* @param string $userId The user's email address. The special value me can be * @param string $userId The user's email address. The special value me can be
@ -56,7 +56,7 @@ class Google_Service_Gmail_Resource_UsersMessages extends Google_Service_Resourc
} }
/** /**
* Immediately and permanently deletes the specified message. This operation * Immediately and permanently deletes the specified message. This operation
* cannot be undone. Prefer messages.trash instead. (messages.delete) * cannot be undone. Prefer messages.trash instead. (messages.delete)
* *
* @param string $userId The user's email address. The special value me can be * @param string $userId The user's email address. The special value me can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
@ -77,9 +77,9 @@ class Google_Service_Gmail_Resource_UsersMessages extends Google_Service_Resourc
* @param string $id The ID of the message to retrieve. * @param string $id The ID of the message to retrieve.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* *
* @opt_param string format The format to return the message in.
* @opt_param string metadataHeaders When given and format is METADATA, only * @opt_param string metadataHeaders When given and format is METADATA, only
* include headers specified. * include headers specified.
* @opt_param string format The format to return the message in.
* @return Google_Service_Gmail_Message * @return Google_Service_Gmail_Message
*/ */
public function get($userId, $id, $optParams = array()) public function get($userId, $id, $optParams = array())
@ -98,15 +98,15 @@ class Google_Service_Gmail_Resource_UsersMessages extends Google_Service_Resourc
* @param Google_Service_Gmail_Message $postBody * @param Google_Service_Gmail_Message $postBody
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* *
* @opt_param bool processForCalendar Process calendar invites in the email and * @opt_param bool deleted Mark the email as permanently deleted (not TRASH) and
* add any extracted meetings to the Google Calendar for this user. * only visible in Google Vault to a Vault administrator. Only used for G Suite
* accounts.
* @opt_param string internalDateSource Source for Gmail's internal date of the * @opt_param string internalDateSource Source for Gmail's internal date of the
* message. * message.
* @opt_param bool neverMarkSpam Ignore the Gmail spam classifier decision and * @opt_param bool neverMarkSpam Ignore the Gmail spam classifier decision and
* never mark this email as SPAM in the mailbox. * never mark this email as SPAM in the mailbox.
* @opt_param bool deleted Mark the email as permanently deleted (not TRASH) and * @opt_param bool processForCalendar Process calendar invites in the email and
* only visible in Google Vault to a Vault administrator. Only used for G Suite * add any extracted meetings to the Google Calendar for this user.
* accounts.
* @return Google_Service_Gmail_Message * @return Google_Service_Gmail_Message
*/ */
public function import($userId, Google_Service_Gmail_Message $postBody, $optParams = array()) public function import($userId, Google_Service_Gmail_Message $postBody, $optParams = array())
@ -125,11 +125,11 @@ class Google_Service_Gmail_Resource_UsersMessages extends Google_Service_Resourc
* @param Google_Service_Gmail_Message $postBody * @param Google_Service_Gmail_Message $postBody
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* *
* @opt_param string internalDateSource Source for Gmail's internal date of the
* message.
* @opt_param bool deleted Mark the email as permanently deleted (not TRASH) and * @opt_param bool deleted Mark the email as permanently deleted (not TRASH) and
* only visible in Google Vault to a Vault administrator. Only used for G Suite * only visible in Google Vault to a Vault administrator. Only used for G Suite
* accounts. * accounts.
* @opt_param string internalDateSource Source for Gmail's internal date of the
* message.
* @return Google_Service_Gmail_Message * @return Google_Service_Gmail_Message
*/ */
public function insert($userId, Google_Service_Gmail_Message $postBody, $optParams = array()) public function insert($userId, Google_Service_Gmail_Message $postBody, $optParams = array())
@ -147,16 +147,15 @@ class Google_Service_Gmail_Resource_UsersMessages extends Google_Service_Resourc
* *
* @opt_param bool includeSpamTrash Include messages from SPAM and TRASH in the * @opt_param bool includeSpamTrash Include messages from SPAM and TRASH in the
* results. * results.
* @opt_param string pageToken Page token to retrieve a specific page of results
* in the list.
* @opt_param string labelIds Only return messages with labels that match all of * @opt_param string labelIds Only return messages with labels that match all of
* the specified label IDs. * the specified label IDs.
* @opt_param string maxResults Maximum number of messages to return.
* @opt_param string pageToken Page token to retrieve a specific page of results
* in the list.
* @opt_param string q Only return messages matching the specified query. * @opt_param string q Only return messages matching the specified query.
* Supports the same query format as the Gmail search box. For example, * Supports the same query format as the Gmail search box. For example,
* "from:someuser@example.com rfc822msgid:somemsgid@example.com is:unread". * "from:someuser@example.com rfc822msgid: is:unread". Parameter cannot be used
* Parameter cannot be used when accessing the api using the gmail.metadata * when accessing the api using the gmail.metadata scope.
* scope.
* @opt_param string maxResults Maximum number of messages to return.
* @return Google_Service_Gmail_ListMessagesResponse * @return Google_Service_Gmail_ListMessagesResponse
*/ */
public function listUsersMessages($userId, $optParams = array()) public function listUsersMessages($userId, $optParams = array())

View File

@ -29,7 +29,7 @@ class Google_Service_Gmail_Resource_UsersSettings extends Google_Service_Resourc
* Gets the auto-forwarding setting for the specified account. * Gets the auto-forwarding setting for the specified account.
* (settings.getAutoForwarding) * (settings.getAutoForwarding)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* @return Google_Service_Gmail_AutoForwarding * @return Google_Service_Gmail_AutoForwarding
@ -43,7 +43,7 @@ class Google_Service_Gmail_Resource_UsersSettings extends Google_Service_Resourc
/** /**
* Gets IMAP settings. (settings.getImap) * Gets IMAP settings. (settings.getImap)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* @return Google_Service_Gmail_ImapSettings * @return Google_Service_Gmail_ImapSettings
@ -57,7 +57,7 @@ class Google_Service_Gmail_Resource_UsersSettings extends Google_Service_Resourc
/** /**
* Gets language settings. (settings.getLanguage) * Gets language settings. (settings.getLanguage)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* @return Google_Service_Gmail_LanguageSettings * @return Google_Service_Gmail_LanguageSettings
@ -71,7 +71,7 @@ class Google_Service_Gmail_Resource_UsersSettings extends Google_Service_Resourc
/** /**
* Gets POP settings. (settings.getPop) * Gets POP settings. (settings.getPop)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* @return Google_Service_Gmail_PopSettings * @return Google_Service_Gmail_PopSettings
@ -85,7 +85,7 @@ class Google_Service_Gmail_Resource_UsersSettings extends Google_Service_Resourc
/** /**
* Gets vacation responder settings. (settings.getVacation) * Gets vacation responder settings. (settings.getVacation)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* @return Google_Service_Gmail_VacationSettings * @return Google_Service_Gmail_VacationSettings
@ -97,13 +97,13 @@ class Google_Service_Gmail_Resource_UsersSettings extends Google_Service_Resourc
return $this->call('getVacation', array($params), "Google_Service_Gmail_VacationSettings"); return $this->call('getVacation', array($params), "Google_Service_Gmail_VacationSettings");
} }
/** /**
* Updates the auto-forwarding setting for the specified account. A verified * Updates the auto-forwarding setting for the specified account. A verified
* forwarding address must be specified when auto-forwarding is enabled. * forwarding address must be specified when auto-forwarding is enabled.
* *
* This method is only available to service account clients that have been * This method is only available to service account clients that have been
* delegated domain-wide authority. (settings.updateAutoForwarding) * delegated domain-wide authority. (settings.updateAutoForwarding)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param Google_Service_Gmail_AutoForwarding $postBody * @param Google_Service_Gmail_AutoForwarding $postBody
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
@ -118,7 +118,7 @@ class Google_Service_Gmail_Resource_UsersSettings extends Google_Service_Resourc
/** /**
* Updates IMAP settings. (settings.updateImap) * Updates IMAP settings. (settings.updateImap)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param Google_Service_Gmail_ImapSettings $postBody * @param Google_Service_Gmail_ImapSettings $postBody
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
@ -139,7 +139,7 @@ class Google_Service_Gmail_Resource_UsersSettings extends Google_Service_Resourc
* Gmail but have a close variant that is, and so the variant may be chosen and * Gmail but have a close variant that is, and so the variant may be chosen and
* saved instead. (settings.updateLanguage) * saved instead. (settings.updateLanguage)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param Google_Service_Gmail_LanguageSettings $postBody * @param Google_Service_Gmail_LanguageSettings $postBody
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
@ -154,7 +154,7 @@ class Google_Service_Gmail_Resource_UsersSettings extends Google_Service_Resourc
/** /**
* Updates POP settings. (settings.updatePop) * Updates POP settings. (settings.updatePop)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param Google_Service_Gmail_PopSettings $postBody * @param Google_Service_Gmail_PopSettings $postBody
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
@ -169,7 +169,7 @@ class Google_Service_Gmail_Resource_UsersSettings extends Google_Service_Resourc
/** /**
* Updates vacation responder settings. (settings.updateVacation) * Updates vacation responder settings. (settings.updateVacation)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param Google_Service_Gmail_VacationSettings $postBody * @param Google_Service_Gmail_VacationSettings $postBody
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.

View File

@ -27,8 +27,8 @@ class Google_Service_Gmail_Resource_UsersSettingsDelegates extends Google_Servic
{ {
/** /**
* Adds a delegate with its verification status set directly to accepted, * Adds a delegate with its verification status set directly to accepted,
* without sending any verification email. The delegate user must be a member * without sending any verification email. The delegate user must be a member of
* of the same G Suite organization as the delegator user. * the same G Suite organization as the delegator user.
* *
* Gmail imposes limitations on the number of delegates and delegators each user * Gmail imposes limitations on the number of delegates and delegators each user
* in a G Suite organization can have. These limits depend on your organization, * in a G Suite organization can have. These limits depend on your organization,
@ -43,7 +43,7 @@ class Google_Service_Gmail_Resource_UsersSettingsDelegates extends Google_Servic
* This method is only available to service account clients that have been * This method is only available to service account clients that have been
* delegated domain-wide authority. (delegates.create) * delegated domain-wide authority. (delegates.create)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param Google_Service_Gmail_Delegate $postBody * @param Google_Service_Gmail_Delegate $postBody
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
@ -65,7 +65,7 @@ class Google_Service_Gmail_Resource_UsersSettingsDelegates extends Google_Servic
* This method is only available to service account clients that have been * This method is only available to service account clients that have been
* delegated domain-wide authority. (delegates.delete) * delegated domain-wide authority. (delegates.delete)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param string $delegateEmail The email address of the user to be removed as a * @param string $delegateEmail The email address of the user to be removed as a
* delegate. * delegate.
@ -86,7 +86,7 @@ class Google_Service_Gmail_Resource_UsersSettingsDelegates extends Google_Servic
* This method is only available to service account clients that have been * This method is only available to service account clients that have been
* delegated domain-wide authority. (delegates.get) * delegated domain-wide authority. (delegates.get)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param string $delegateEmail The email address of the user whose delegate * @param string $delegateEmail The email address of the user whose delegate
* relationship is to be retrieved. * relationship is to be retrieved.
@ -105,7 +105,7 @@ class Google_Service_Gmail_Resource_UsersSettingsDelegates extends Google_Servic
* This method is only available to service account clients that have been * This method is only available to service account clients that have been
* delegated domain-wide authority. (delegates.listUsersSettingsDelegates) * delegated domain-wide authority. (delegates.listUsersSettingsDelegates)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* @return Google_Service_Gmail_ListDelegatesResponse * @return Google_Service_Gmail_ListDelegatesResponse

View File

@ -26,7 +26,7 @@
class Google_Service_Gmail_Resource_UsersSettingsForwardingAddresses extends Google_Service_Resource class Google_Service_Gmail_Resource_UsersSettingsForwardingAddresses extends Google_Service_Resource
{ {
/** /**
* Creates a forwarding address. If ownership verification is required, a * Creates a forwarding address. If ownership verification is required, a
* message will be sent to the recipient and the resource's verification status * message will be sent to the recipient and the resource's verification status
* will be set to pending; otherwise, the resource will be created with * will be set to pending; otherwise, the resource will be created with
* verification status set to accepted. * verification status set to accepted.
@ -34,7 +34,7 @@ class Google_Service_Gmail_Resource_UsersSettingsForwardingAddresses extends Goo
* This method is only available to service account clients that have been * This method is only available to service account clients that have been
* delegated domain-wide authority. (forwardingAddresses.create) * delegated domain-wide authority. (forwardingAddresses.create)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param Google_Service_Gmail_ForwardingAddress $postBody * @param Google_Service_Gmail_ForwardingAddress $postBody
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
@ -53,7 +53,7 @@ class Google_Service_Gmail_Resource_UsersSettingsForwardingAddresses extends Goo
* This method is only available to service account clients that have been * This method is only available to service account clients that have been
* delegated domain-wide authority. (forwardingAddresses.delete) * delegated domain-wide authority. (forwardingAddresses.delete)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param string $forwardingEmail The forwarding address to be deleted. * @param string $forwardingEmail The forwarding address to be deleted.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
@ -67,7 +67,7 @@ class Google_Service_Gmail_Resource_UsersSettingsForwardingAddresses extends Goo
/** /**
* Gets the specified forwarding address. (forwardingAddresses.get) * Gets the specified forwarding address. (forwardingAddresses.get)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param string $forwardingEmail The forwarding address to be retrieved. * @param string $forwardingEmail The forwarding address to be retrieved.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
@ -83,7 +83,7 @@ class Google_Service_Gmail_Resource_UsersSettingsForwardingAddresses extends Goo
* Lists the forwarding addresses for the specified account. * Lists the forwarding addresses for the specified account.
* (forwardingAddresses.listUsersSettingsForwardingAddresses) * (forwardingAddresses.listUsersSettingsForwardingAddresses)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* @return Google_Service_Gmail_ListForwardingAddressesResponse * @return Google_Service_Gmail_ListForwardingAddressesResponse

View File

@ -26,18 +26,18 @@
class Google_Service_Gmail_Resource_UsersSettingsSendAs extends Google_Service_Resource class Google_Service_Gmail_Resource_UsersSettingsSendAs extends Google_Service_Resource
{ {
/** /**
* Creates a custom "from" send-as alias. If an SMTP MSA is specified, Gmail * Creates a custom "from" send-as alias. If an SMTP MSA is specified, Gmail
* will attempt to connect to the SMTP service to validate the configuration * will attempt to connect to the SMTP service to validate the configuration
* before creating the alias. If ownership verification is required for the * before creating the alias. If ownership verification is required for the
* alias, a message will be sent to the email address and the resource's * alias, a message will be sent to the email address and the resource's
* verification status will be set to pending; otherwise, the resource will be * verification status will be set to pending; otherwise, the resource will be
* created with verification status set to accepted. If a signature is * created with verification status set to accepted. If a signature is provided,
* provided, Gmail will sanitize the HTML before saving it with the alias. * Gmail will sanitize the HTML before saving it with the alias.
* *
* This method is only available to service account clients that have been * This method is only available to service account clients that have been
* delegated domain-wide authority. (sendAs.create) * delegated domain-wide authority. (sendAs.create)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param Google_Service_Gmail_SendAs $postBody * @param Google_Service_Gmail_SendAs $postBody
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
@ -50,13 +50,13 @@ class Google_Service_Gmail_Resource_UsersSettingsSendAs extends Google_Service_R
return $this->call('create', array($params), "Google_Service_Gmail_SendAs"); return $this->call('create', array($params), "Google_Service_Gmail_SendAs");
} }
/** /**
* Deletes the specified send-as alias. Revokes any verification that may have * Deletes the specified send-as alias. Revokes any verification that may have
* been required for using it. * been required for using it.
* *
* This method is only available to service account clients that have been * This method is only available to service account clients that have been
* delegated domain-wide authority. (sendAs.delete) * delegated domain-wide authority. (sendAs.delete)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param string $sendAsEmail The send-as alias to be deleted. * @param string $sendAsEmail The send-as alias to be deleted.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
@ -68,10 +68,10 @@ class Google_Service_Gmail_Resource_UsersSettingsSendAs extends Google_Service_R
return $this->call('delete', array($params)); return $this->call('delete', array($params));
} }
/** /**
* Gets the specified send-as alias. Fails with an HTTP 404 error if the * Gets the specified send-as alias. Fails with an HTTP 404 error if the
* specified address is not a member of the collection. (sendAs.get) * specified address is not a member of the collection. (sendAs.get)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param string $sendAsEmail The send-as alias to be retrieved. * @param string $sendAsEmail The send-as alias to be retrieved.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
@ -84,11 +84,11 @@ class Google_Service_Gmail_Resource_UsersSettingsSendAs extends Google_Service_R
return $this->call('get', array($params), "Google_Service_Gmail_SendAs"); return $this->call('get', array($params), "Google_Service_Gmail_SendAs");
} }
/** /**
* Lists the send-as aliases for the specified account. The result includes the * Lists the send-as aliases for the specified account. The result includes the
* primary send-as address associated with the account as well as any custom * primary send-as address associated with the account as well as any custom
* "from" aliases. (sendAs.listUsersSettingsSendAs) * "from" aliases. (sendAs.listUsersSettingsSendAs)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* @return Google_Service_Gmail_ListSendAsResponse * @return Google_Service_Gmail_ListSendAsResponse
@ -100,9 +100,14 @@ class Google_Service_Gmail_Resource_UsersSettingsSendAs extends Google_Service_R
return $this->call('list', array($params), "Google_Service_Gmail_ListSendAsResponse"); return $this->call('list', array($params), "Google_Service_Gmail_ListSendAsResponse");
} }
/** /**
* Patch the specified send-as alias. (sendAs.patch) * Updates a send-as alias. If a signature is provided, Gmail will sanitize the
* HTML before saving it with the alias.
* *
* @param string $userId User's email address. The special value "me" can be * Addresses other than the primary address for the account can only be updated
* by service account clients that have been delegated domain-wide authority.
* This method supports patch semantics. (sendAs.patch)
*
* @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param string $sendAsEmail The send-as alias to be updated. * @param string $sendAsEmail The send-as alias to be updated.
* @param Google_Service_Gmail_SendAs $postBody * @param Google_Service_Gmail_SendAs $postBody
@ -116,14 +121,14 @@ class Google_Service_Gmail_Resource_UsersSettingsSendAs extends Google_Service_R
return $this->call('patch', array($params), "Google_Service_Gmail_SendAs"); return $this->call('patch', array($params), "Google_Service_Gmail_SendAs");
} }
/** /**
* Updates a send-as alias. If a signature is provided, Gmail will sanitize the * Updates a send-as alias. If a signature is provided, Gmail will sanitize the
* HTML before saving it with the alias. * HTML before saving it with the alias.
* *
* Addresses other than the primary address for the account can only be updated * Addresses other than the primary address for the account can only be updated
* by service account clients that have been delegated domain-wide authority. * by service account clients that have been delegated domain-wide authority.
* (sendAs.update) * (sendAs.update)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param string $sendAsEmail The send-as alias to be updated. * @param string $sendAsEmail The send-as alias to be updated.
* @param Google_Service_Gmail_SendAs $postBody * @param Google_Service_Gmail_SendAs $postBody
@ -143,7 +148,7 @@ class Google_Service_Gmail_Resource_UsersSettingsSendAs extends Google_Service_R
* This method is only available to service account clients that have been * This method is only available to service account clients that have been
* delegated domain-wide authority. (sendAs.verify) * delegated domain-wide authority. (sendAs.verify)
* *
* @param string $userId User's email address. The special value "me" can be * @param string $userId User's email address. The special value "me" can be
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param string $sendAsEmail The send-as alias to be verified. * @param string $sendAsEmail The send-as alias to be verified.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.

View File

@ -48,9 +48,9 @@ class Google_Service_Gmail_Resource_UsersThreads extends Google_Service_Resource
* @param string $id The ID of the thread to retrieve. * @param string $id The ID of the thread to retrieve.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* *
* @opt_param string format The format to return the messages in.
* @opt_param string metadataHeaders When given and format is METADATA, only * @opt_param string metadataHeaders When given and format is METADATA, only
* include headers specified. * include headers specified.
* @opt_param string format The format to return the messages in.
* @return Google_Service_Gmail_Thread * @return Google_Service_Gmail_Thread
*/ */
public function get($userId, $id, $optParams = array()) public function get($userId, $id, $optParams = array())
@ -66,17 +66,17 @@ class Google_Service_Gmail_Resource_UsersThreads extends Google_Service_Resource
* used to indicate the authenticated user. * used to indicate the authenticated user.
* @param array $optParams Optional parameters. * @param array $optParams Optional parameters.
* *
* @opt_param string pageToken Page token to retrieve a specific page of results * @opt_param bool includeSpamTrash Include threads from SPAM and TRASH in the
* in the list. * results.
* @opt_param string labelIds Only return threads with labels that match all of * @opt_param string labelIds Only return threads with labels that match all of
* the specified label IDs. * the specified label IDs.
* @opt_param string maxResults Maximum number of threads to return.
* @opt_param string pageToken Page token to retrieve a specific page of results
* in the list.
* @opt_param string q Only return threads matching the specified query. * @opt_param string q Only return threads matching the specified query.
* Supports the same query format as the Gmail search box. For example, * Supports the same query format as the Gmail search box. For example,
* "from:someuser@example.com rfc822msgid: is:unread". Parameter cannot be used * "from:someuser@example.com rfc822msgid: is:unread". Parameter cannot be used
* when accessing the api using the gmail.metadata scope. * when accessing the api using the gmail.metadata scope.
* @opt_param string maxResults Maximum number of threads to return.
* @opt_param bool includeSpamTrash Include threads from SPAM and TRASH in the
* results.
* @return Google_Service_Gmail_ListThreadsResponse * @return Google_Service_Gmail_ListThreadsResponse
*/ */
public function listUsersThreads($userId, $optParams = array()) public function listUsersThreads($userId, $optParams = array())

View File

@ -23,7 +23,7 @@ function oauth2client_php_autoload($className)
} }
if (count($classPath) > 3) { if (count($classPath) > 3) {
// Maximum class file path depth in this project is 3. // Maximum class file path depth in this project is 3.
$classPath = array_slice($classPath, 0, 3); $classPath = array_slice($classPath, 0, 3);
} }
$filePath = dirname(__FILE__) . '/src/' . implode('/', $classPath) . '.php'; $filePath = dirname(__FILE__) . '/src/' . implode('/', $classPath) . '.php';
if (file_exists($filePath)) { if (file_exists($filePath)) {

View File

@ -82,22 +82,19 @@ class AccessToken
* accepted. By default, the id token must have been issued to this OAuth2 client. * accepted. By default, the id token must have been issued to this OAuth2 client.
* *
* @param string $token The JSON Web Token to be verified. * @param string $token The JSON Web Token to be verified.
* @param array $options [optional] { * @param array $options [optional] Configuration options.
* Configuration options. * @param string $options.audience The indended recipient of the token.
* * @param string $options.issuer The intended issuer of the token.
* @type string $audience The indended recipient of the token. * @param string $options.cacheKey The cache key of the cached certs. Defaults to
* @type string $issuer The intended issuer of the token. * the sha1 of $certsLocation if provided, otherwise is set to
* @type string $certsLocation The location (remote or local) from which * "federated_signon_certs_v3".
* @param string $options.certsLocation The location (remote or local) from which
* to retrieve certificates, if not cached. This value should only be * to retrieve certificates, if not cached. This value should only be
* provided in limited circumstances in which you are sure of the * provided in limited circumstances in which you are sure of the
* behavior. * behavior.
* @type string $cacheKey The cache key of the cached certs. Defaults to * @param bool $options.throwException Whether the function should throw an
* the sha1 of $certsLocation if provided, otherwise is set to
* "federated_signon_certs_v3".
* @type bool $throwException Whether the function should throw an
* exception if the verification fails. This is useful for * exception if the verification fails. This is useful for
* determining the reason verification failed. * determining the reason verification failed.
* }
* @return array|bool the token payload, if successful, or false if not. * @return array|bool the token payload, if successful, or false if not.
* @throws InvalidArgumentException If certs could not be retrieved from a local file. * @throws InvalidArgumentException If certs could not be retrieved from a local file.
* @throws InvalidArgumentException If received certs are in an invalid format. * @throws InvalidArgumentException If received certs are in an invalid format.
@ -129,7 +126,8 @@ class AccessToken
$alg = $this->determineAlg($certs); $alg = $this->determineAlg($certs);
if (!in_array($alg, ['RS256', 'ES256'])) { if (!in_array($alg, ['RS256', 'ES256'])) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
'unrecognized "alg" in certs, expected ES256 or RS256'); 'unrecognized "alg" in certs, expected ES256 or RS256'
);
} }
try { try {
if ($alg == 'RS256') { if ($alg == 'RS256') {
@ -186,13 +184,11 @@ class AccessToken
* *
* @param string $token The JSON Web Token to be verified. * @param string $token The JSON Web Token to be verified.
* @param array $certs Certificate array according to the JWK spec (see * @param array $certs Certificate array according to the JWK spec (see
* https://tools.ietf.org/html/rfc7517). * https://tools.ietf.org/html/rfc7517).
* @param string|null $audience If set, returns false if the provided * @param string|null $audience If set, returns false if the provided
* audience does not match the "aud" claim on * audience does not match the "aud" claim on the JWT.
* the JWT.
* @param string|null $issuer If set, returns false if the provided * @param string|null $issuer If set, returns false if the provided
* issuer does not match the "iss" claim on * issuer does not match the "iss" claim on the JWT.
* the JWT.
* @return array|bool the token payload, if successful, or false if not. * @return array|bool the token payload, if successful, or false if not.
*/ */
private function verifyEs256($token, array $certs, $audience = null, $issuer = null) private function verifyEs256($token, array $certs, $audience = null, $issuer = null)
@ -228,13 +224,11 @@ class AccessToken
* *
* @param string $token The JSON Web Token to be verified. * @param string $token The JSON Web Token to be verified.
* @param array $certs Certificate array according to the JWK spec (see * @param array $certs Certificate array according to the JWK spec (see
* https://tools.ietf.org/html/rfc7517). * https://tools.ietf.org/html/rfc7517).
* @param string|null $audience If set, returns false if the provided * @param string|null $audience If set, returns false if the provided
* audience does not match the "aud" claim on * audience does not match the "aud" claim on the JWT.
* the JWT.
* @param string|null $issuer If set, returns false if the provided * @param string|null $issuer If set, returns false if the provided
* issuer does not match the "iss" claim on * issuer does not match the "iss" claim on the JWT.
* the JWT.
* @return array|bool the token payload, if successful, or false if not. * @return array|bool the token payload, if successful, or false if not.
*/ */
private function verifyRs256($token, array $certs, $audience = null, $issuer = null) private function verifyRs256($token, array $certs, $audience = null, $issuer = null)
@ -325,6 +319,7 @@ class AccessToken
* are PEM encoded certificates. * are PEM encoded certificates.
* *
* @param string $location The location from which to retrieve certs. * @param string $location The location from which to retrieve certs.
* @param string $cacheKey The key under which to cache the retrieved certs.
* @param array $options [optional] Configuration options. * @param array $options [optional] Configuration options.
* @return array * @return array
* @throws InvalidArgumentException If received certs are in an invalid format. * @throws InvalidArgumentException If received certs are in an invalid format.

View File

@ -46,23 +46,25 @@ use Psr\Cache\CacheItemPoolInterface;
* *
* This allows it to be used as follows with GuzzleHttp\Client: * This allows it to be used as follows with GuzzleHttp\Client:
* *
* use Google\Auth\ApplicationDefaultCredentials; * ```
* use GuzzleHttp\Client; * use Google\Auth\ApplicationDefaultCredentials;
* use GuzzleHttp\HandlerStack; * use GuzzleHttp\Client;
* use GuzzleHttp\HandlerStack;
* *
* $middleware = ApplicationDefaultCredentials::getMiddleware( * $middleware = ApplicationDefaultCredentials::getMiddleware(
* 'https://www.googleapis.com/auth/taskqueue' * 'https://www.googleapis.com/auth/taskqueue'
* ); * );
* $stack = HandlerStack::create(); * $stack = HandlerStack::create();
* $stack->push($middleware); * $stack->push($middleware);
* *
* $client = new Client([ * $client = new Client([
* 'handler' => $stack, * 'handler' => $stack,
* 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/', * 'base_uri' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
* 'auth' => 'google_auth' // authorize all requests * 'auth' => 'google_auth' // authorize all requests
* ]); * ]);
* *
* $res = $client->get('myproject/taskqueues/myqueue'); * $res = $client->get('myproject/taskqueues/myqueue');
* ```
*/ */
class ApplicationDefaultCredentials class ApplicationDefaultCredentials
{ {
@ -74,13 +76,12 @@ class ApplicationDefaultCredentials
* this does not fallback to the compute engine defaults. * this does not fallback to the compute engine defaults.
* *
* @param string|array scope the scope of the access request, expressed * @param string|array scope the scope of the access request, expressed
* either as an Array or as a space-delimited String. * either as an Array or as a space-delimited String.
* @param callable $httpHandler callback which delivers psr7 request * @param callable $httpHandler callback which delivers psr7 request
* @param array $cacheConfig configuration for the cache when it's present * @param array $cacheConfig configuration for the cache when it's present
* @param CacheItemPoolInterface $cache an implementation of CacheItemPoolInterface * @param CacheItemPoolInterface $cache A cache implementation, may be
* * provided if you have one already available for use.
* @return AuthTokenSubscriber * @return AuthTokenSubscriber
*
* @throws DomainException if no implementation can be obtained. * @throws DomainException if no implementation can be obtained.
*/ */
public static function getSubscriber( public static function getSubscriber(
@ -102,13 +103,12 @@ class ApplicationDefaultCredentials
* this does not fallback to the compute engine defaults. * this does not fallback to the compute engine defaults.
* *
* @param string|array scope the scope of the access request, expressed * @param string|array scope the scope of the access request, expressed
* either as an Array or as a space-delimited String. * either as an Array or as a space-delimited String.
* @param callable $httpHandler callback which delivers psr7 request * @param callable $httpHandler callback which delivers psr7 request
* @param array $cacheConfig configuration for the cache when it's present * @param array $cacheConfig configuration for the cache when it's present
* @param CacheItemPoolInterface $cache * @param CacheItemPoolInterface $cache A cache implementation, may be
* * provided if you have one already available for use.
* @return AuthTokenMiddleware * @return AuthTokenMiddleware
*
* @throws DomainException if no implementation can be obtained. * @throws DomainException if no implementation can be obtained.
*/ */
public static function getMiddleware( public static function getMiddleware(
@ -131,20 +131,23 @@ class ApplicationDefaultCredentials
* this does not fallback to the Compute Engine defaults. * this does not fallback to the Compute Engine defaults.
* *
* @param string|array scope the scope of the access request, expressed * @param string|array scope the scope of the access request, expressed
* either as an Array or as a space-delimited String. * either as an Array or as a space-delimited String.
* @param callable $httpHandler callback which delivers psr7 request * @param callable $httpHandler callback which delivers psr7 request
* @param array $cacheConfig configuration for the cache when it's present * @param array $cacheConfig configuration for the cache when it's present
* @param CacheItemPoolInterface $cache * @param CacheItemPoolInterface $cache A cache implementation, may be
* provided if you have one already available for use.
* @param string $quotaProject specifies a project to bill for access
* charges associated with the request.
* *
* @return CredentialsLoader * @return CredentialsLoader
*
* @throws DomainException if no implementation can be obtained. * @throws DomainException if no implementation can be obtained.
*/ */
public static function getCredentials( public static function getCredentials(
$scope = null, $scope = null,
callable $httpHandler = null, callable $httpHandler = null,
array $cacheConfig = null, array $cacheConfig = null,
CacheItemPoolInterface $cache = null CacheItemPoolInterface $cache = null,
$quotaProject = null
) { ) {
$creds = null; $creds = null;
$jsonKey = CredentialsLoader::fromEnv() $jsonKey = CredentialsLoader::fromEnv()
@ -160,11 +163,12 @@ class ApplicationDefaultCredentials
} }
if (!is_null($jsonKey)) { if (!is_null($jsonKey)) {
$jsonKey['quota_project'] = $quotaProject;
$creds = CredentialsLoader::makeCredentials($scope, $jsonKey); $creds = CredentialsLoader::makeCredentials($scope, $jsonKey);
} elseif (AppIdentityCredentials::onAppEngine() && !GCECredentials::onAppEngineFlexible()) { } elseif (AppIdentityCredentials::onAppEngine() && !GCECredentials::onAppEngineFlexible()) {
$creds = new AppIdentityCredentials($scope); $creds = new AppIdentityCredentials($scope);
} elseif (GCECredentials::onGce($httpHandler)) { } elseif (GCECredentials::onGce($httpHandler)) {
$creds = new GCECredentials(null, $scope); $creds = new GCECredentials(null, $scope, null, $quotaProject);
} }
if (is_null($creds)) { if (is_null($creds)) {
@ -187,10 +191,9 @@ class ApplicationDefaultCredentials
* @param string $targetAudience The audience for the ID token. * @param string $targetAudience The audience for the ID token.
* @param callable $httpHandler callback which delivers psr7 request * @param callable $httpHandler callback which delivers psr7 request
* @param array $cacheConfig configuration for the cache when it's present * @param array $cacheConfig configuration for the cache when it's present
* @param CacheItemPoolInterface $cache * @param CacheItemPoolInterface $cache A cache implementation, may be
* * provided if you have one already available for use.
* @return AuthTokenMiddleware * @return AuthTokenMiddleware
*
* @throws DomainException if no implementation can be obtained. * @throws DomainException if no implementation can be obtained.
*/ */
public static function getIdTokenMiddleware( public static function getIdTokenMiddleware(
@ -198,7 +201,6 @@ class ApplicationDefaultCredentials
callable $httpHandler = null, callable $httpHandler = null,
array $cacheConfig = null, array $cacheConfig = null,
CacheItemPoolInterface $cache = null CacheItemPoolInterface $cache = null
) { ) {
$creds = self::getIdTokenCredentials($targetAudience, $httpHandler, $cacheConfig, $cache); $creds = self::getIdTokenCredentials($targetAudience, $httpHandler, $cacheConfig, $cache);
@ -213,10 +215,9 @@ class ApplicationDefaultCredentials
* @param string $targetAudience The audience for the ID token. * @param string $targetAudience The audience for the ID token.
* @param callable $httpHandler callback which delivers psr7 request * @param callable $httpHandler callback which delivers psr7 request
* @param array $cacheConfig configuration for the cache when it's present * @param array $cacheConfig configuration for the cache when it's present
* @param CacheItemPoolInterface $cache * @param CacheItemPoolInterface $cache A cache implementation, may be
* * provided if you have one already available for use.
* @return CredentialsLoader * @return CredentialsLoader
*
* @throws DomainException if no implementation can be obtained. * @throws DomainException if no implementation can be obtained.
* @throws InvalidArgumentException if JSON "type" key is invalid * @throws InvalidArgumentException if JSON "type" key is invalid
*/ */

View File

@ -62,22 +62,22 @@ class SysVCacheItemPool implements CacheItemPoolInterface
/** /**
* Create a SystemV shared memory based CacheItemPool. * Create a SystemV shared memory based CacheItemPool.
* *
* @param array $options [optional] { * @param array $options [optional] Configuration options.
* Configuration options. * @param int $options.variableKey The variable key for getting the data from
* * the shared memory. **Defaults to** 1.
* @type int $variableKey The variable key for getting the data from * @param $options.proj string The project identifier for ftok. This needs to
* the shared memory. **Defaults to** 1. * be a one character string. **Defaults to** 'A'.
* @type string $proj The project identifier for ftok. This needs to * @param $options.memsize int The memory size in bytes for shm_attach.
* be a one character string. **Defaults to** 'A'. * **Defaults to** 10000.
* @type int $memsize The memory size in bytes for shm_attach. * @param $options.perm int The permission for shm_attach. **Defaults to**
* **Defaults to** 10000. * 0600.
* @type int $perm The permission for shm_attach. **Defaults to** 0600.
*/ */
public function __construct($options = []) public function __construct($options = [])
{ {
if (! extension_loaded('sysvshm')) { if (! extension_loaded('sysvshm')) {
throw new \RuntimeException( throw new \RuntimeException(
'sysvshm extension is required to use this ItemPool'); 'sysvshm extension is required to use this ItemPool'
);
} }
$this->options = $options + [ $this->options = $options + [
'variableKey' => self::VAR_KEY, 'variableKey' => self::VAR_KEY,
@ -90,9 +90,6 @@ class SysVCacheItemPool implements CacheItemPoolInterface
$this->sysvKey = ftok(__FILE__, $this->options['proj']); $this->sysvKey = ftok(__FILE__, $this->options['proj']);
} }
/**
* {@inheritdoc}
*/
public function getItem($key) public function getItem($key)
{ {
$this->loadItems(); $this->loadItems();

View File

@ -90,7 +90,7 @@ class AppIdentityCredentials extends CredentialsLoader implements
* SERVER_SOFTWARE environment variable (prod) or the APPENGINE_RUNTIME * SERVER_SOFTWARE environment variable (prod) or the APPENGINE_RUNTIME
* environment variable (dev). * environment variable (dev).
* *
* @return true if this an App Engine Instance, false otherwise * @return bool true if this an App Engine Instance, false otherwise
*/ */
public static function onAppEngine() public static function onAppEngine()
{ {
@ -115,7 +115,6 @@ class AppIdentityCredentials extends CredentialsLoader implements
* the GuzzleHttp\ClientInterface instance passed in will not be used. * the GuzzleHttp\ClientInterface instance passed in will not be used.
* *
* @param callable $httpHandler callback which delivers psr7 request * @param callable $httpHandler callback which delivers psr7 request
*
* @return array A set of auth related metadata, containing the following * @return array A set of auth related metadata, containing the following
* keys: * keys:
* - access_token (string) * - access_token (string)

View File

@ -18,6 +18,7 @@
namespace Google\Auth\Credentials; namespace Google\Auth\Credentials;
use Google\Auth\CredentialsLoader; use Google\Auth\CredentialsLoader;
use Google\Auth\GetQuotaProjectInterface;
use Google\Auth\HttpHandler\HttpClientCache; use Google\Auth\HttpHandler\HttpClientCache;
use Google\Auth\HttpHandler\HttpHandlerFactory; use Google\Auth\HttpHandler\HttpHandlerFactory;
use Google\Auth\Iam; use Google\Auth\Iam;
@ -55,9 +56,12 @@ use InvalidArgumentException;
*/ */
class GCECredentials extends CredentialsLoader implements class GCECredentials extends CredentialsLoader implements
SignBlobInterface, SignBlobInterface,
ProjectIdProviderInterface ProjectIdProviderInterface,
GetQuotaProjectInterface
{ {
// phpcs:disable
const cacheKey = 'GOOGLE_AUTH_PHP_GCE'; const cacheKey = 'GOOGLE_AUTH_PHP_GCE';
// phpcs:enable
/** /**
* The metadata IP address on appengine instances. * The metadata IP address on appengine instances.
@ -149,19 +153,27 @@ class GCECredentials extends CredentialsLoader implements
*/ */
private $targetAudience; private $targetAudience;
/**
* @var string|null
*/
private $quotaProject;
/** /**
* @param Iam $iam [optional] An IAM instance. * @param Iam $iam [optional] An IAM instance.
* @param string|array $scope [optional] the scope of the access request, * @param string|array $scope [optional] the scope of the access request,
* expressed either as an array or as a space-delimited string. * expressed either as an array or as a space-delimited string.
* @param string $targetAudience [optional] The audience for the ID token. * @param string $targetAudience [optional] The audience for the ID token.
* @param string $quotaProject [optional] Specifies a project to bill for access
* charges associated with the request.
*/ */
public function __construct(Iam $iam = null, $scope = null, $targetAudience = null) public function __construct(Iam $iam = null, $scope = null, $targetAudience = null, $quotaProject = null)
{ {
$this->iam = $iam; $this->iam = $iam;
if ($scope && $targetAudience) { if ($scope && $targetAudience) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
'Scope and targetAudience cannot both be supplied'); 'Scope and targetAudience cannot both be supplied'
);
} }
$tokenUri = self::getTokenUri(); $tokenUri = self::getTokenUri();
@ -174,7 +186,8 @@ class GCECredentials extends CredentialsLoader implements
$tokenUri = $tokenUri . '?scopes='. $scope; $tokenUri = $tokenUri . '?scopes='. $scope;
} elseif ($targetAudience) { } elseif ($targetAudience) {
$tokenUri = sprintf('http://%s/computeMetadata/%s?audience=%s', $tokenUri = sprintf(
'http://%s/computeMetadata/%s?audience=%s',
self::METADATA_IP, self::METADATA_IP,
self::ID_TOKEN_URI_PATH, self::ID_TOKEN_URI_PATH,
$targetAudience $targetAudience
@ -183,6 +196,7 @@ class GCECredentials extends CredentialsLoader implements
} }
$this->tokenUri = $tokenUri; $this->tokenUri = $tokenUri;
$this->quotaProject = $quotaProject;
} }
/** /**
@ -225,7 +239,7 @@ class GCECredentials extends CredentialsLoader implements
* Determines if this an App Engine Flexible instance, by accessing the * Determines if this an App Engine Flexible instance, by accessing the
* GAE_INSTANCE environment variable. * GAE_INSTANCE environment variable.
* *
* @return true if this an App Engine Flexible Instance, false otherwise * @return bool true if this an App Engine Flexible Instance, false otherwise
*/ */
public static function onAppEngineFlexible() public static function onAppEngineFlexible()
{ {
@ -456,4 +470,14 @@ class GCECredentials extends CredentialsLoader implements
return (string) $resp->getBody(); return (string) $resp->getBody();
} }
/**
* Get the quota project used for this API request
*
* @return string|null
*/
public function getQuotaProject()
{
return $this->quotaProject;
}
} }

View File

@ -43,11 +43,13 @@ class IAMCredentials
{ {
if (!is_string($selector)) { if (!is_string($selector)) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
'selector must be a string'); 'selector must be a string'
);
} }
if (!is_string($token)) { if (!is_string($token)) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
'token must be a string'); 'token must be a string'
);
} }
$this->selector = $selector; $this->selector = $selector;

View File

@ -112,18 +112,21 @@ class ServiceAccountCredentials extends CredentialsLoader implements
} }
if (!array_key_exists('client_email', $jsonKey)) { if (!array_key_exists('client_email', $jsonKey)) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
'json key is missing the client_email field'); 'json key is missing the client_email field'
);
} }
if (!array_key_exists('private_key', $jsonKey)) { if (!array_key_exists('private_key', $jsonKey)) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
'json key is missing the private_key field'); 'json key is missing the private_key field'
);
} }
if (array_key_exists('quota_project', $jsonKey)) { if (array_key_exists('quota_project', $jsonKey)) {
$this->quotaProject = (string) $jsonKey['quota_project']; $this->quotaProject = (string) $jsonKey['quota_project'];
} }
if ($scope && $targetAudience) { if ($scope && $targetAudience) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
'Scope and targetAudience cannot both be supplied'); 'Scope and targetAudience cannot both be supplied'
);
} }
$additionalClaims = []; $additionalClaims = [];
if ($targetAudience) { if ($targetAudience) {
@ -199,7 +202,6 @@ class ServiceAccountCredentials extends CredentialsLoader implements
* @param array $metadata metadata hashmap * @param array $metadata metadata hashmap
* @param string $authUri optional auth uri * @param string $authUri optional auth uri
* @param callable $httpHandler callback which delivers psr7 request * @param callable $httpHandler callback which delivers psr7 request
*
* @return array updated metadata hashmap * @return array updated metadata hashmap
*/ */
public function updateMetadata( public function updateMetadata(

View File

@ -71,11 +71,13 @@ class ServiceAccountJwtAccessCredentials extends CredentialsLoader implements
} }
if (!array_key_exists('client_email', $jsonKey)) { if (!array_key_exists('client_email', $jsonKey)) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
'json key is missing the client_email field'); 'json key is missing the client_email field'
);
} }
if (!array_key_exists('private_key', $jsonKey)) { if (!array_key_exists('private_key', $jsonKey)) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
'json key is missing the private_key field'); 'json key is missing the private_key field'
);
} }
if (array_key_exists('quota_project', $jsonKey)) { if (array_key_exists('quota_project', $jsonKey)) {
$this->quotaProject = (string) $jsonKey['quota_project']; $this->quotaProject = (string) $jsonKey['quota_project'];
@ -98,7 +100,6 @@ class ServiceAccountJwtAccessCredentials extends CredentialsLoader implements
* @param array $metadata metadata hashmap * @param array $metadata metadata hashmap
* @param string $authUri optional auth uri * @param string $authUri optional auth uri
* @param callable $httpHandler callback which delivers psr7 request * @param callable $httpHandler callback which delivers psr7 request
*
* @return array updated metadata hashmap * @return array updated metadata hashmap
*/ */
public function updateMetadata( public function updateMetadata(

View File

@ -74,15 +74,18 @@ class UserRefreshCredentials extends CredentialsLoader implements GetQuotaProjec
} }
if (!array_key_exists('client_id', $jsonKey)) { if (!array_key_exists('client_id', $jsonKey)) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
'json key is missing the client_id field'); 'json key is missing the client_id field'
);
} }
if (!array_key_exists('client_secret', $jsonKey)) { if (!array_key_exists('client_secret', $jsonKey)) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
'json key is missing the client_secret field'); 'json key is missing the client_secret field'
);
} }
if (!array_key_exists('refresh_token', $jsonKey)) { if (!array_key_exists('refresh_token', $jsonKey)) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
'json key is missing the refresh_token field'); 'json key is missing the refresh_token field'
);
} }
$this->auth = new OAuth2([ $this->auth = new OAuth2([
'clientId' => $jsonKey['client_id'], 'clientId' => $jsonKey['client_id'],
@ -109,7 +112,8 @@ class UserRefreshCredentials extends CredentialsLoader implements GetQuotaProjec
. 'To disable this warning, set ' . 'To disable this warning, set '
. self::SUPPRESS_CLOUD_SDK_CREDS_WARNING_ENV . self::SUPPRESS_CLOUD_SDK_CREDS_WARNING_ENV
. ' environment variable to "true".', . ' environment variable to "true".',
E_USER_WARNING); E_USER_WARNING
);
} }
} }

View File

@ -61,7 +61,7 @@ abstract class CredentialsLoader implements FetchAuthTokenInterface
* variable GOOGLE_APPLICATION_CREDENTIALS. Return null if * variable GOOGLE_APPLICATION_CREDENTIALS. Return null if
* GOOGLE_APPLICATION_CREDENTIALS is not specified. * GOOGLE_APPLICATION_CREDENTIALS is not specified.
* *
* @return array JSON key | null * @return array|null JSON key | null
*/ */
public static function fromEnv() public static function fromEnv()
{ {
@ -81,12 +81,13 @@ abstract class CredentialsLoader implements FetchAuthTokenInterface
* Load a JSON key from a well known path. * Load a JSON key from a well known path.
* *
* The well known path is OS dependent: * The well known path is OS dependent:
* - windows: %APPDATA%/gcloud/application_default_credentials.json
* - others: $HOME/.config/gcloud/application_default_credentials.json
* *
* If the file does not exists, this returns null. * * windows: %APPDATA%/gcloud/application_default_credentials.json
* * others: $HOME/.config/gcloud/application_default_credentials.json
* *
* @return array JSON key | null * If the file does not exist, this returns null.
*
* @return array|null JSON key | null
*/ */
public static function fromWellKnownFile() public static function fromWellKnownFile()
{ {
@ -108,9 +109,8 @@ abstract class CredentialsLoader implements FetchAuthTokenInterface
* Create a new Credentials instance. * Create a new Credentials instance.
* *
* @param string|array $scope the scope of the access request, expressed * @param string|array $scope the scope of the access request, expressed
* either as an Array or as a space-delimited String. * either as an Array or as a space-delimited String.
* @param array $jsonKey the JSON credentials. * @param array $jsonKey the JSON credentials.
*
* @return ServiceAccountCredentials|UserRefreshCredentials * @return ServiceAccountCredentials|UserRefreshCredentials
*/ */
public static function makeCredentials($scope, array $jsonKey) public static function makeCredentials($scope, array $jsonKey)
@ -134,10 +134,9 @@ abstract class CredentialsLoader implements FetchAuthTokenInterface
* Create an authorized HTTP Client from an instance of FetchAuthTokenInterface. * Create an authorized HTTP Client from an instance of FetchAuthTokenInterface.
* *
* @param FetchAuthTokenInterface $fetcher is used to fetch the auth token * @param FetchAuthTokenInterface $fetcher is used to fetch the auth token
* @param array $httpClientOptoins (optional) Array of request options to apply. * @param array $httpClientOptions (optional) Array of request options to apply.
* @param callable $httpHandler (optional) http client to fetch the token. * @param callable $httpHandler (optional) http client to fetch the token.
* @param callable $tokenCallback (optional) function to be called when a new token is fetched. * @param callable $tokenCallback (optional) function to be called when a new token is fetched.
*
* @return \GuzzleHttp\Client * @return \GuzzleHttp\Client
*/ */
public static function makeHttpClient( public static function makeHttpClient(
@ -203,7 +202,6 @@ abstract class CredentialsLoader implements FetchAuthTokenInterface
* @param array $metadata metadata hashmap * @param array $metadata metadata hashmap
* @param string $authUri optional auth uri * @param string $authUri optional auth uri
* @param callable $httpHandler callback which delivers psr7 request * @param callable $httpHandler callback which delivers psr7 request
*
* @return array updated metadata hashmap * @return array updated metadata hashmap
*/ */
public function updateMetadata( public function updateMetadata(

View File

@ -46,6 +46,11 @@ class FetchAuthTokenCache implements
*/ */
private $cache; private $cache;
/**
* @param FetchAuthTokenInterface $fetcher A credentials fetcher
* @param array $cacheConfig Configuration for the cache
* @param CacheItemPoolInterface $cache
*/
public function __construct( public function __construct(
FetchAuthTokenInterface $fetcher, FetchAuthTokenInterface $fetcher,
array $cacheConfig = null, array $cacheConfig = null,
@ -66,9 +71,7 @@ class FetchAuthTokenCache implements
* from the supplied fetcher. * from the supplied fetcher.
* *
* @param callable $httpHandler callback which delivers psr7 request * @param callable $httpHandler callback which delivers psr7 request
*
* @return array the response * @return array the response
*
* @throws \Exception * @throws \Exception
*/ */
public function fetchAuthToken(callable $httpHandler = null) public function fetchAuthToken(callable $httpHandler = null)
@ -125,14 +128,14 @@ class FetchAuthTokenCache implements
* Sign a blob using the fetcher. * Sign a blob using the fetcher.
* *
* @param string $stringToSign The string to sign. * @param string $stringToSign The string to sign.
* @param bool $forceOpenssl Require use of OpenSSL for local signing. Does * @param bool $forceOpenSsl Require use of OpenSSL for local signing. Does
* not apply to signing done using external services. **Defaults to** * not apply to signing done using external services. **Defaults to**
* `false`. * `false`.
* @return string The resulting signature. * @return string The resulting signature.
* @throws \RuntimeException If the fetcher does not implement * @throws \RuntimeException If the fetcher does not implement
* `Google\Auth\SignBlobInterface`. * `Google\Auth\SignBlobInterface`.
*/ */
public function signBlob($stringToSign, $forceOpenSsl = false) public function signBlob($stringToSign, $forceOpenSsl = false)
{ {
if (!$this->fetcher instanceof SignBlobInterface) { if (!$this->fetcher instanceof SignBlobInterface) {
throw new \RuntimeException( throw new \RuntimeException(

View File

@ -26,7 +26,6 @@ interface FetchAuthTokenInterface
* Fetches the auth tokens based on the current state. * Fetches the auth tokens based on the current state.
* *
* @param callable $httpHandler callback which delivers psr7 request * @param callable $httpHandler callback which delivers psr7 request
*
* @return array a hash of auth tokens * @return array a hash of auth tokens
*/ */
public function fetchAuthToken(callable $httpHandler = null); public function fetchAuthToken(callable $httpHandler = null);

View File

@ -45,7 +45,6 @@ class Guzzle5HttpHandler
* *
* @param RequestInterface $request * @param RequestInterface $request
* @param array $options * @param array $options
*
* @return ResponseInterface * @return ResponseInterface
*/ */
public function __invoke(RequestInterface $request, array $options = []) public function __invoke(RequestInterface $request, array $options = [])
@ -62,7 +61,6 @@ class Guzzle5HttpHandler
* *
* @param RequestInterface $request * @param RequestInterface $request
* @param array $options * @param array $options
*
* @return Promise * @return Promise
*/ */
public function async(RequestInterface $request, array $options = []) public function async(RequestInterface $request, array $options = [])

View File

@ -26,7 +26,6 @@ class Guzzle6HttpHandler
* *
* @param RequestInterface $request * @param RequestInterface $request
* @param array $options * @param array $options
*
* @return ResponseInterface * @return ResponseInterface
*/ */
public function __invoke(RequestInterface $request, array $options = []) public function __invoke(RequestInterface $request, array $options = [])
@ -40,7 +39,7 @@ class Guzzle6HttpHandler
* @param RequestInterface $request * @param RequestInterface $request
* @param array $options * @param array $options
* *
* @return \GuzzleHttp\Promise\Promise * @return \GuzzleHttp\Promise\PromiseInterface
*/ */
public function async(RequestInterface $request, array $options = []) public function async(RequestInterface $request, array $options = [])
{ {

View File

@ -89,7 +89,6 @@ class AuthTokenMiddleware
* $res = $client->get('myproject/taskqueues/myqueue'); * $res = $client->get('myproject/taskqueues/myqueue');
* *
* @param callable $handler * @param callable $handler
*
* @return \Closure * @return \Closure
*/ */
public function __invoke(callable $handler) public function __invoke(callable $handler)

View File

@ -76,7 +76,8 @@ class ScopedAccessTokenMiddleware
$this->tokenFunc = $tokenFunc; $this->tokenFunc = $tokenFunc;
if (!(is_string($scopes) || is_array($scopes))) { if (!(is_string($scopes) || is_array($scopes))) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
'wants scope should be string or array'); 'wants scope should be string or array'
);
} }
$this->scopes = $scopes; $this->scopes = $scopes;
@ -119,7 +120,6 @@ class ScopedAccessTokenMiddleware
* $res = $client->get('myproject/taskqueues/myqueue'); * $res = $client->get('myproject/taskqueues/myqueue');
* *
* @param callable $handler * @param callable $handler
*
* @return \Closure * @return \Closure
*/ */
public function __invoke(callable $handler) public function __invoke(callable $handler)

View File

@ -71,7 +71,6 @@ class SimpleMiddleware
* $res = $client->get('drive/v2/rest'); * $res = $client->get('drive/v2/rest');
* *
* @param callable $handler * @param callable $handler
*
* @return \Closure * @return \Closure
*/ */
public function __invoke(callable $handler) public function __invoke(callable $handler)

View File

@ -120,7 +120,7 @@ class OAuth2 implements FetchAuthTokenInterface
* The scope of the access request, expressed either as an Array or as a * The scope of the access request, expressed either as an Array or as a
* space-delimited string. * space-delimited string.
* *
* @var string * @var array
*/ */
private $scope; private $scope;
@ -175,6 +175,13 @@ class OAuth2 implements FetchAuthTokenInterface
*/ */
private $signingKey; private $signingKey;
/**
* The signing key id when using assertion profile. Param kid in jwt header
*
* @var string
*/
private $signingKeyId;
/** /**
* The signing algorithm when using an assertion profile. * The signing algorithm when using an assertion profile.
* *
@ -294,6 +301,9 @@ class OAuth2 implements FetchAuthTokenInterface
* - signingKey * - signingKey
* Signing key when using assertion profile * Signing key when using assertion profile
* *
* - signingKeyId
* Signing key id when using assertion profile
*
* - refreshToken * - refreshToken
* The refresh token associated with the access token * The refresh token associated with the access token
* to be refreshed. * to be refreshed.
@ -327,6 +337,7 @@ class OAuth2 implements FetchAuthTokenInterface
'sub' => null, 'sub' => null,
'audience' => null, 'audience' => null,
'signingKey' => null, 'signingKey' => null,
'signingKeyId' => null,
'signingAlgorithm' => null, 'signingAlgorithm' => null,
'scope' => null, 'scope' => null,
'additionalClaims' => [], 'additionalClaims' => [],
@ -345,6 +356,7 @@ class OAuth2 implements FetchAuthTokenInterface
$this->setExpiry($opts['expiry']); $this->setExpiry($opts['expiry']);
$this->setAudience($opts['audience']); $this->setAudience($opts['audience']);
$this->setSigningKey($opts['signingKey']); $this->setSigningKey($opts['signingKey']);
$this->setSigningKeyId($opts['signingKeyId']);
$this->setSigningAlgorithm($opts['signingAlgorithm']); $this->setSigningAlgorithm($opts['signingAlgorithm']);
$this->setScope($opts['scope']); $this->setScope($opts['scope']);
$this->setExtensionParams($opts['extensionParams']); $this->setExtensionParams($opts['extensionParams']);
@ -359,11 +371,21 @@ class OAuth2 implements FetchAuthTokenInterface
* - if present, but invalid, raises DomainException. * - if present, but invalid, raises DomainException.
* - otherwise returns the payload in the idtoken as a PHP object. * - otherwise returns the payload in the idtoken as a PHP object.
* *
* if $publicKey is null, the key is decoded without being verified. * The behavior of this method varies depending on the version of
* `firebase/php-jwt` you are using. In versions lower than 3.0.0, if
* `$publicKey` is null, the key is decoded without being verified. In
* newer versions, if a public key is not given, this method will throw an
* `\InvalidArgumentException`.
* *
* @param string $publicKey The public key to use to authenticate the token * @param string $publicKey The public key to use to authenticate the token
* @param array $allowed_algs List of supported verification algorithms * @param array $allowed_algs List of supported verification algorithms
* * @throws \DomainException if the token is missing an audience.
* @throws \DomainException if the audience does not match the one set in
* the OAuth2 class instance.
* @throws \UnexpectedValueException If the token is invalid
* @throws SignatureInvalidException If the signature is invalid.
* @throws BeforeValidException If the token is not yet valid.
* @throws ExpiredException If the token has expired.
* @return null|object * @return null|object
*/ */
public function verifyIdToken($publicKey = null, $allowed_algs = array()) public function verifyIdToken($publicKey = null, $allowed_algs = array())
@ -388,7 +410,6 @@ class OAuth2 implements FetchAuthTokenInterface
* Obtains the encoded jwt from the instance data. * Obtains the encoded jwt from the instance data.
* *
* @param array $config array optional configuration parameters * @param array $config array optional configuration parameters
*
* @return string * @return string
*/ */
public function toJwt(array $config = []) public function toJwt(array $config = [])
@ -424,8 +445,12 @@ class OAuth2 implements FetchAuthTokenInterface
} }
$assertion += $this->getAdditionalClaims(); $assertion += $this->getAdditionalClaims();
return $this->jwtEncode($assertion, $this->getSigningKey(), return $this->jwtEncode(
$this->getSigningAlgorithm()); $assertion,
$this->getSigningKey(),
$this->getSigningAlgorithm(),
$this->getSigningKeyId()
);
} }
/** /**
@ -490,7 +515,6 @@ class OAuth2 implements FetchAuthTokenInterface
* Fetches the auth tokens based on the current state. * Fetches the auth tokens based on the current state.
* *
* @param callable $httpHandler callback which delivers psr7 request * @param callable $httpHandler callback which delivers psr7 request
*
* @return array the response * @return array the response
*/ */
public function fetchAuthToken(callable $httpHandler = null) public function fetchAuthToken(callable $httpHandler = null)
@ -515,10 +539,6 @@ class OAuth2 implements FetchAuthTokenInterface
*/ */
public function getCacheKey() public function getCacheKey()
{ {
if (is_string($this->scope)) {
return $this->scope;
}
if (is_array($this->scope)) { if (is_array($this->scope)) {
return implode(':', $this->scope); return implode(':', $this->scope);
} }
@ -531,9 +551,7 @@ class OAuth2 implements FetchAuthTokenInterface
* Parses the fetched tokens. * Parses the fetched tokens.
* *
* @param ResponseInterface $resp the response. * @param ResponseInterface $resp the response.
*
* @return array the tokens parsed from the response body. * @return array the tokens parsed from the response body.
*
* @throws \Exception * @throws \Exception
*/ */
public function parseTokenResponse(ResponseInterface $resp) public function parseTokenResponse(ResponseInterface $resp)
@ -559,12 +577,14 @@ class OAuth2 implements FetchAuthTokenInterface
/** /**
* Updates an OAuth 2.0 client. * Updates an OAuth 2.0 client.
* *
* @example * Example:
* client.updateToken([ * ```
* $oauth->updateToken([
* 'refresh_token' => 'n4E9O119d', * 'refresh_token' => 'n4E9O119d',
* 'access_token' => 'FJQbwq9', * 'access_token' => 'FJQbwq9',
* 'expires_in' => 3600 * 'expires_in' => 3600
* ]) * ]);
* ```
* *
* @param array $config * @param array $config
* The configuration parameters related to the token. * The configuration parameters related to the token.
@ -621,16 +641,15 @@ class OAuth2 implements FetchAuthTokenInterface
* Builds the authorization Uri that the user should be redirected to. * Builds the authorization Uri that the user should be redirected to.
* *
* @param array $config configuration options that customize the return url * @param array $config configuration options that customize the return url
*
* @return UriInterface the authorization Url. * @return UriInterface the authorization Url.
*
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function buildFullAuthorizationUri(array $config = []) public function buildFullAuthorizationUri(array $config = [])
{ {
if (is_null($this->getAuthorizationUri())) { if (is_null($this->getAuthorizationUri())) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
'requires an authorizationUri to have been set'); 'requires an authorizationUri to have been set'
);
} }
$params = array_merge([ $params = array_merge([
@ -645,14 +664,16 @@ class OAuth2 implements FetchAuthTokenInterface
// Validate the auth_params // Validate the auth_params
if (is_null($params['client_id'])) { if (is_null($params['client_id'])) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
'missing the required client identifier'); 'missing the required client identifier'
);
} }
if (is_null($params['redirect_uri'])) { if (is_null($params['redirect_uri'])) {
throw new InvalidArgumentException('missing the required redirect URI'); throw new InvalidArgumentException('missing the required redirect URI');
} }
if (!empty($params['prompt']) && !empty($params['approval_prompt'])) { if (!empty($params['prompt']) && !empty($params['approval_prompt'])) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
'prompt and approval_prompt are mutually exclusive'); 'prompt and approval_prompt are mutually exclusive'
);
} }
// Construct the uri object; return it if it is valid. // Construct the uri object; return it if it is valid.
@ -665,7 +686,8 @@ class OAuth2 implements FetchAuthTokenInterface
if ($result->getScheme() != 'https') { if ($result->getScheme() != 'https') {
throw new InvalidArgumentException( throw new InvalidArgumentException(
'Authorization endpoint must be protected by TLS'); 'Authorization endpoint must be protected by TLS'
);
} }
return $result; return $result;
@ -743,7 +765,8 @@ class OAuth2 implements FetchAuthTokenInterface
// @see https://developers.google.com/identity/sign-in/web/server-side-flow // @see https://developers.google.com/identity/sign-in/web/server-side-flow
if ('postmessage' !== (string)$uri) { if ('postmessage' !== (string)$uri) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
'Redirect URI must be absolute'); 'Redirect URI must be absolute'
);
} }
} }
$this->redirectUri = (string)$uri; $this->redirectUri = (string)$uri;
@ -768,7 +791,6 @@ class OAuth2 implements FetchAuthTokenInterface
* a space-delimited String. * a space-delimited String.
* *
* @param string|array $scope * @param string|array $scope
*
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function setScope($scope) public function setScope($scope)
@ -782,13 +804,15 @@ class OAuth2 implements FetchAuthTokenInterface
$pos = strpos($s, ' '); $pos = strpos($s, ' ');
if ($pos !== false) { if ($pos !== false) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
'array scope values should not contain spaces'); 'array scope values should not contain spaces'
);
} }
} }
$this->scope = $scope; $this->scope = $scope;
} else { } else {
throw new InvalidArgumentException( throw new InvalidArgumentException(
'scopes should be a string or array of strings'); 'scopes should be a string or array of strings'
);
} }
} }
@ -828,7 +852,6 @@ class OAuth2 implements FetchAuthTokenInterface
* Sets the current grant type. * Sets the current grant type.
* *
* @param $grantType * @param $grantType
*
* @throws InvalidArgumentException * @throws InvalidArgumentException
*/ */
public function setGrantType($grantType) public function setGrantType($grantType)
@ -839,7 +862,8 @@ class OAuth2 implements FetchAuthTokenInterface
// validate URI // validate URI
if (!$this->isAbsoluteUri($grantType)) { if (!$this->isAbsoluteUri($grantType)) {
throw new InvalidArgumentException( throw new InvalidArgumentException(
'invalid grant type'); 'invalid grant type'
);
} }
$this->grantType = (string)$grantType; $this->grantType = (string)$grantType;
} }
@ -1031,6 +1055,26 @@ class OAuth2 implements FetchAuthTokenInterface
$this->signingKey = $signingKey; $this->signingKey = $signingKey;
} }
/**
* Gets the signing key id when using an assertion profile.
*
* @return string
*/
public function getSigningKeyId()
{
return $this->signingKeyId;
}
/**
* Sets the signing key id when using an assertion profile.
*
* @param string $signingKeyId
*/
public function setSigningKeyId($signingKeyId)
{
$this->signingKeyId = $signingKeyId;
}
/** /**
* Gets the signing algorithm when using an assertion profile. * Gets the signing algorithm when using an assertion profile.
* *
@ -1287,7 +1331,6 @@ class OAuth2 implements FetchAuthTokenInterface
* @todo handle uri as array * @todo handle uri as array
* *
* @param string $uri * @param string $uri
*
* @return null|UriInterface * @return null|UriInterface
*/ */
private function coerceUri($uri) private function coerceUri($uri)
@ -1303,7 +1346,6 @@ class OAuth2 implements FetchAuthTokenInterface
* @param string $idToken * @param string $idToken
* @param string|array|null $publicKey * @param string|array|null $publicKey
* @param array $allowedAlgs * @param array $allowedAlgs
*
* @return object * @return object
*/ */
private function jwtDecode($idToken, $publicKey, $allowedAlgs) private function jwtDecode($idToken, $publicKey, $allowedAlgs)
@ -1315,14 +1357,18 @@ class OAuth2 implements FetchAuthTokenInterface
return \JWT::decode($idToken, $publicKey, $allowedAlgs); return \JWT::decode($idToken, $publicKey, $allowedAlgs);
} }
private function jwtEncode($assertion, $signingKey, $signingAlgorithm) private function jwtEncode($assertion, $signingKey, $signingAlgorithm, $signingKeyId = null)
{ {
if (class_exists('Firebase\JWT\JWT')) { if (class_exists('Firebase\JWT\JWT')) {
return \Firebase\JWT\JWT::encode($assertion, $signingKey, return \Firebase\JWT\JWT::encode(
$signingAlgorithm); $assertion,
$signingKey,
$signingAlgorithm,
$signingKeyId
);
} }
return \JWT::encode($assertion, $signingKey, $signingAlgorithm); return \JWT::encode($assertion, $signingKey, $signingAlgorithm, $signingKeyId);
} }
/** /**
@ -1330,7 +1376,6 @@ class OAuth2 implements FetchAuthTokenInterface
* (RFC 3986). * (RFC 3986).
* *
* @param string $uri * @param string $uri
*
* @return bool * @return bool
*/ */
private function isAbsoluteUri($uri) private function isAbsoluteUri($uri)
@ -1342,7 +1387,6 @@ class OAuth2 implements FetchAuthTokenInterface
/** /**
* @param array $params * @param array $params
*
* @return array * @return array
*/ */
private function addClientCredentials(&$params) private function addClientCredentials(&$params)

View File

@ -79,21 +79,24 @@ class AuthTokenSubscriber implements SubscriberInterface
/** /**
* Updates the request with an Authorization header when auth is 'fetched_auth_token'. * Updates the request with an Authorization header when auth is 'fetched_auth_token'.
* *
* use GuzzleHttp\Client; * Example:
* use Google\Auth\OAuth2; * ```
* use Google\Auth\Subscriber\AuthTokenSubscriber; * use GuzzleHttp\Client;
* use Google\Auth\OAuth2;
* use Google\Auth\Subscriber\AuthTokenSubscriber;
* *
* $config = [..<oauth config param>.]; * $config = [..<oauth config param>.];
* $oauth2 = new OAuth2($config) * $oauth2 = new OAuth2($config)
* $subscriber = new AuthTokenSubscriber($oauth2); * $subscriber = new AuthTokenSubscriber($oauth2);
* *
* $client = new Client([ * $client = new Client([
* 'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/', * 'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
* 'defaults' => ['auth' => 'google_auth'] * 'defaults' => ['auth' => 'google_auth']
* ]); * ]);
* $client->getEmitter()->attach($subscriber); * $client->getEmitter()->attach($subscriber);
* *
* $res = $client->get('myproject/taskqueues/myqueue'); * $res = $client->get('myproject/taskqueues/myqueue');
* ```
* *
* @param BeforeEvent $event * @param BeforeEvent $event
*/ */

View File

@ -78,7 +78,8 @@ class ScopedAccessTokenSubscriber implements SubscriberInterface
$this->tokenFunc = $tokenFunc; $this->tokenFunc = $tokenFunc;
if (!(is_string($scopes) || is_array($scopes))) { if (!(is_string($scopes) || is_array($scopes))) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
'wants scope should be string or array'); 'wants scope should be string or array'
);
} }
$this->scopes = $scopes; $this->scopes = $scopes;
@ -102,28 +103,30 @@ class ScopedAccessTokenSubscriber implements SubscriberInterface
/** /**
* Updates the request with an Authorization header when auth is 'scoped'. * Updates the request with an Authorization header when auth is 'scoped'.
* *
* E.g this could be used to authenticate using the AppEngine * E.g this could be used to authenticate using the AppEngine AppIdentityService.
* AppIdentityService.
* *
* use google\appengine\api\app_identity\AppIdentityService; * Example:
* use Google\Auth\Subscriber\ScopedAccessTokenSubscriber; * ```
* use GuzzleHttp\Client; * use google\appengine\api\app_identity\AppIdentityService;
* use Google\Auth\Subscriber\ScopedAccessTokenSubscriber;
* use GuzzleHttp\Client;
* *
* $scope = 'https://www.googleapis.com/auth/taskqueue' * $scope = 'https://www.googleapis.com/auth/taskqueue'
* $subscriber = new ScopedAccessToken( * $subscriber = new ScopedAccessToken(
* 'AppIdentityService::getAccessToken', * 'AppIdentityService::getAccessToken',
* $scope, * $scope,
* ['prefix' => 'Google\Auth\ScopedAccessToken::'], * ['prefix' => 'Google\Auth\ScopedAccessToken::'],
* $cache = new Memcache() * $cache = new Memcache()
* ); * );
* *
* $client = new Client([ * $client = new Client([
* 'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/', * 'base_url' => 'https://www.googleapis.com/taskqueue/v1beta2/projects/',
* 'defaults' => ['auth' => 'scoped'] * 'defaults' => ['auth' => 'scoped']
* ]); * ]);
* $client->getEmitter()->attach($subscriber); * $client->getEmitter()->attach($subscriber);
* *
* $res = $client->get('myproject/taskqueues/myqueue'); * $res = $client->get('myproject/taskqueues/myqueue');
* ```
* *
* @param BeforeEvent $event * @param BeforeEvent $event
*/ */

View File

@ -62,19 +62,22 @@ class SimpleSubscriber implements SubscriberInterface
/** /**
* Updates the request query with the developer key if auth is set to simple. * Updates the request query with the developer key if auth is set to simple.
* *
* use Google\Auth\Subscriber\SimpleSubscriber; * Example:
* use GuzzleHttp\Client; * ```
* use Google\Auth\Subscriber\SimpleSubscriber;
* use GuzzleHttp\Client;
* *
* $my_key = 'is not the same as yours'; * $my_key = 'is not the same as yours';
* $subscriber = new SimpleSubscriber(['key' => $my_key]); * $subscriber = new SimpleSubscriber(['key' => $my_key]);
* *
* $client = new Client([ * $client = new Client([
* 'base_url' => 'https://www.googleapis.com/discovery/v1/', * 'base_url' => 'https://www.googleapis.com/discovery/v1/',
* 'defaults' => ['auth' => 'simple'] * 'defaults' => ['auth' => 'simple']
* ]); * ]);
* $client->getEmitter()->attach($subscriber); * $client->getEmitter()->attach($subscriber);
* *
* $res = $client->get('drive/v2/rest'); * $res = $client->get('drive/v2/rest');
* ```
* *
* @param BeforeEvent $event * @param BeforeEvent $event
*/ */

View File

@ -2,11 +2,12 @@
namespace GuzzleHttp; namespace GuzzleHttp;
use GuzzleHttp\Cookie\CookieJar; use GuzzleHttp\Cookie\CookieJar;
use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Promise; use GuzzleHttp\Promise;
use GuzzleHttp\Psr7; use GuzzleHttp\Psr7;
use Psr\Http\Message\UriInterface;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface;
/** /**
* @method ResponseInterface get(string|UriInterface $uri, array $options = []) * @method ResponseInterface get(string|UriInterface $uri, array $options = [])
@ -46,9 +47,8 @@ class Client implements ClientInterface
* wire. The function is called with a Psr7\Http\Message\RequestInterface * wire. The function is called with a Psr7\Http\Message\RequestInterface
* and array of transfer options, and must return a * and array of transfer options, and must return a
* GuzzleHttp\Promise\PromiseInterface that is fulfilled with a * GuzzleHttp\Promise\PromiseInterface that is fulfilled with a
* Psr7\Http\Message\ResponseInterface on success. "handler" is a * Psr7\Http\Message\ResponseInterface on success.
* constructor only option that cannot be overridden in per/request * If no handler is provided, a default handler will be created
* options. If no handler is provided, a default handler will be created
* that enables all of the request options below by attaching all of the * that enables all of the request options below by attaching all of the
* default middleware to the handler. * default middleware to the handler.
* - base_uri: (string|UriInterface) Base URI of the client that is merged * - base_uri: (string|UriInterface) Base URI of the client that is merged
@ -75,6 +75,12 @@ class Client implements ClientInterface
$this->configureDefaults($config); $this->configureDefaults($config);
} }
/**
* @param string $method
* @param array $args
*
* @return Promise\PromiseInterface
*/
public function __call($method, $args) public function __call($method, $args)
{ {
if (count($args) < 1) { if (count($args) < 1) {
@ -89,6 +95,14 @@ class Client implements ClientInterface
: $this->request($method, $uri, $opts); : $this->request($method, $uri, $opts);
} }
/**
* Asynchronously send an HTTP request.
*
* @param array $options Request options to apply to the given
* request and to the transfer. See \GuzzleHttp\RequestOptions.
*
* @return Promise\PromiseInterface
*/
public function sendAsync(RequestInterface $request, array $options = []) public function sendAsync(RequestInterface $request, array $options = [])
{ {
// Merge the base URI into the request URI if needed. // Merge the base URI into the request URI if needed.
@ -100,12 +114,35 @@ class Client implements ClientInterface
); );
} }
/**
* Send an HTTP request.
*
* @param array $options Request options to apply to the given
* request and to the transfer. See \GuzzleHttp\RequestOptions.
*
* @return ResponseInterface
* @throws GuzzleException
*/
public function send(RequestInterface $request, array $options = []) public function send(RequestInterface $request, array $options = [])
{ {
$options[RequestOptions::SYNCHRONOUS] = true; $options[RequestOptions::SYNCHRONOUS] = true;
return $this->sendAsync($request, $options)->wait(); return $this->sendAsync($request, $options)->wait();
} }
/**
* Create and send an asynchronous HTTP request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well. Use an array to provide a URL
* template and additional variables to use in the URL template expansion.
*
* @param string $method HTTP method
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
*
* @return Promise\PromiseInterface
*/
public function requestAsync($method, $uri = '', array $options = []) public function requestAsync($method, $uri = '', array $options = [])
{ {
$options = $this->prepareDefaults($options); $options = $this->prepareDefaults($options);
@ -125,12 +162,37 @@ class Client implements ClientInterface
return $this->transfer($request, $options); return $this->transfer($request, $options);
} }
/**
* Create and send an HTTP request.
*
* Use an absolute path to override the base path of the client, or a
* relative path to append to the base path of the client. The URL can
* contain the query string as well.
*
* @param string $method HTTP method.
* @param string|UriInterface $uri URI object or string.
* @param array $options Request options to apply. See \GuzzleHttp\RequestOptions.
*
* @return ResponseInterface
* @throws GuzzleException
*/
public function request($method, $uri = '', array $options = []) public function request($method, $uri = '', array $options = [])
{ {
$options[RequestOptions::SYNCHRONOUS] = true; $options[RequestOptions::SYNCHRONOUS] = true;
return $this->requestAsync($method, $uri, $options)->wait(); return $this->requestAsync($method, $uri, $options)->wait();
} }
/**
* Get a client configuration option.
*
* These options include default request options of the client, a "handler"
* (if utilized by the concrete client), and a "base_uri" if utilized by
* the concrete client.
*
* @param string|null $option The config option to retrieve.
*
* @return mixed
*/
public function getConfig($option = null) public function getConfig($option = null)
{ {
return $option === null return $option === null
@ -138,6 +200,11 @@ class Client implements ClientInterface
: (isset($this->config[$option]) ? $this->config[$option] : null); : (isset($this->config[$option]) ? $this->config[$option] : null);
} }
/**
* @param string|null $uri
*
* @return UriInterface
*/
private function buildUri($uri, array $config) private function buildUri($uri, array $config)
{ {
// for BC we accept null which would otherwise fail in uri_for // for BC we accept null which would otherwise fail in uri_for
@ -147,6 +214,11 @@ class Client implements ClientInterface
$uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri); $uri = Psr7\UriResolver::resolve(Psr7\uri_for($config['base_uri']), $uri);
} }
if (isset($config['idn_conversion']) && ($config['idn_conversion'] !== false)) {
$idnOptions = ($config['idn_conversion'] === true) ? IDNA_DEFAULT : $config['idn_conversion'];
$uri = Utils::idnUriConvert($uri, $idnOptions);
}
return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri; return $uri->getScheme() === '' && $uri->getHost() !== '' ? $uri->withScheme('http') : $uri;
} }
@ -154,6 +226,7 @@ class Client implements ClientInterface
* Configures the default options for a client. * Configures the default options for a client.
* *
* @param array $config * @param array $config
* @return void
*/ */
private function configureDefaults(array $config) private function configureDefaults(array $config)
{ {
@ -162,7 +235,8 @@ class Client implements ClientInterface
'http_errors' => true, 'http_errors' => true,
'decode_content' => true, 'decode_content' => true,
'verify' => true, 'verify' => true,
'cookies' => false 'cookies' => false,
'idn_conversion' => true,
]; ];
// Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set. // Use the standard Linux HTTP_PROXY and HTTPS_PROXY if set.
@ -170,7 +244,7 @@ class Client implements ClientInterface
// We can only trust the HTTP_PROXY environment variable in a CLI // We can only trust the HTTP_PROXY environment variable in a CLI
// process due to the fact that PHP has no reliable mechanism to // process due to the fact that PHP has no reliable mechanism to
// get environment variables that start with "HTTP_". // get environment variables that start with "HTTP_".
if (php_sapi_name() == 'cli' && getenv('HTTP_PROXY')) { if (php_sapi_name() === 'cli' && getenv('HTTP_PROXY')) {
$defaults['proxy']['http'] = getenv('HTTP_PROXY'); $defaults['proxy']['http'] = getenv('HTTP_PROXY');
} }
@ -225,7 +299,7 @@ class Client implements ClientInterface
if (array_key_exists('headers', $options)) { if (array_key_exists('headers', $options)) {
// Allows default headers to be unset. // Allows default headers to be unset.
if ($options['headers'] === null) { if ($options['headers'] === null) {
$defaults['_conditional'] = null; $defaults['_conditional'] = [];
unset($options['headers']); unset($options['headers']);
} elseif (!is_array($options['headers'])) { } elseif (!is_array($options['headers'])) {
throw new \InvalidArgumentException('headers must be an array'); throw new \InvalidArgumentException('headers must be an array');
@ -251,8 +325,7 @@ class Client implements ClientInterface
* The URI of the request is not modified and the request options are used * The URI of the request is not modified and the request options are used
* as-is without merging in default options. * as-is without merging in default options.
* *
* @param RequestInterface $request * @param array $options See \GuzzleHttp\RequestOptions.
* @param array $options
* *
* @return Promise\PromiseInterface * @return Promise\PromiseInterface
*/ */
@ -271,6 +344,7 @@ class Client implements ClientInterface
} }
$request = $this->applyOptions($request, $options); $request = $this->applyOptions($request, $options);
/** @var HandlerStack $handler */
$handler = $options['handler']; $handler = $options['handler'];
try { try {
@ -411,6 +485,11 @@ class Client implements ClientInterface
return $request; return $request;
} }
/**
* Throw Exception with pre-set message.
* @return void
* @throws \InvalidArgumentException Invalid body.
*/
private function invalidBody() private function invalidBody()
{ {
throw new \InvalidArgumentException('Passing in the "body" request ' throw new \InvalidArgumentException('Passing in the "body" request '

View File

@ -1,8 +1,8 @@
<?php <?php
namespace GuzzleHttp; namespace GuzzleHttp;
use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Exception\GuzzleException; use GuzzleHttp\Exception\GuzzleException;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\UriInterface; use Psr\Http\Message\UriInterface;
@ -12,7 +12,10 @@ use Psr\Http\Message\UriInterface;
*/ */
interface ClientInterface interface ClientInterface
{ {
const VERSION = '6.4.1'; /**
* @deprecated Will be removed in Guzzle 7.0.0
*/
const VERSION = '6.5.4';
/** /**
* Send an HTTP request. * Send an HTTP request.

View File

@ -94,8 +94,8 @@ class CookieJar implements CookieJarInterface
*/ */
public function getCookieByName($name) public function getCookieByName($name)
{ {
// don't allow a null name // don't allow a non string name
if ($name === null) { if ($name === null || !is_scalar($name)) {
return null; return null;
} }
foreach ($this->cookies as $cookie) { foreach ($this->cookies as $cookie) {
@ -103,6 +103,8 @@ class CookieJar implements CookieJarInterface
return $cookie; return $cookie;
} }
} }
return null;
} }
public function toArray() public function toArray()

View File

@ -58,9 +58,9 @@ interface CookieJarInterface extends \Countable, \IteratorAggregate
* arguments, then the cookie with the specified name, path and domain is * arguments, then the cookie with the specified name, path and domain is
* removed. * removed.
* *
* @param string $domain Clears cookies matching a domain * @param string|null $domain Clears cookies matching a domain
* @param string $path Clears cookies matching a domain and path * @param string|null $path Clears cookies matching a domain and path
* @param string $name Clears cookies matching a domain, path, and name * @param string|null $name Clears cookies matching a domain, path, and name
* *
* @return CookieJarInterface * @return CookieJarInterface
*/ */

View File

@ -1,9 +1,9 @@
<?php <?php
namespace GuzzleHttp\Exception; namespace GuzzleHttp\Exception;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\UriInterface; use Psr\Http\Message\UriInterface;
/** /**
@ -14,7 +14,7 @@ class RequestException extends TransferException
/** @var RequestInterface */ /** @var RequestInterface */
private $request; private $request;
/** @var ResponseInterface */ /** @var ResponseInterface|null */
private $response; private $response;
/** @var array */ /** @var array */
@ -124,42 +124,17 @@ class RequestException extends TransferException
*/ */
public static function getResponseBodySummary(ResponseInterface $response) public static function getResponseBodySummary(ResponseInterface $response)
{ {
$body = $response->getBody(); return \GuzzleHttp\Psr7\get_message_body_summary($response);
if (!$body->isSeekable() || !$body->isReadable()) {
return null;
}
$size = $body->getSize();
if ($size === 0) {
return null;
}
$summary = $body->read(120);
$body->rewind();
if ($size > 120) {
$summary .= ' (truncated...)';
}
// Matches any printable character, including unicode characters:
// letters, marks, numbers, punctuation, spacing, and separators.
if (preg_match('/[^\pL\pM\pN\pP\pS\pZ\n\r\t]/', $summary)) {
return null;
}
return $summary;
} }
/** /**
* Obfuscates URI if there is an username and a password present * Obfuscates URI if there is a username and a password present
* *
* @param UriInterface $uri * @param UriInterface $uri
* *
* @return UriInterface * @return UriInterface
*/ */
private static function obfuscateUri($uri) private static function obfuscateUri(UriInterface $uri)
{ {
$userInfo = $uri->getUserInfo(); $userInfo = $uri->getUserInfo();

View File

@ -1,8 +1,8 @@
<?php <?php
namespace GuzzleHttp\Handler; namespace GuzzleHttp\Handler;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Promise\FulfilledPromise; use GuzzleHttp\Promise\FulfilledPromise;
use GuzzleHttp\Psr7; use GuzzleHttp\Psr7;
use GuzzleHttp\Psr7\LazyOpenStream; use GuzzleHttp\Psr7\LazyOpenStream;
@ -454,11 +454,16 @@ class CurlFactory implements CurlFactoryInterface
} }
if (isset($options['ssl_key'])) { if (isset($options['ssl_key'])) {
$sslKey = $options['ssl_key']; if (is_array($options['ssl_key'])) {
if (is_array($sslKey)) { if (count($options['ssl_key']) === 2) {
$conf[CURLOPT_SSLKEYPASSWD] = $sslKey[1]; list($sslKey, $conf[CURLOPT_SSLKEYPASSWD]) = $options['ssl_key'];
$sslKey = $sslKey[0]; } else {
list($sslKey) = $options['ssl_key'];
}
} }
$sslKey = isset($sslKey) ? $sslKey: $options['ssl_key'];
if (!file_exists($sslKey)) { if (!file_exists($sslKey)) {
throw new \InvalidArgumentException( throw new \InvalidArgumentException(
"SSL private key not found: {$sslKey}" "SSL private key not found: {$sslKey}"

View File

@ -3,7 +3,7 @@ namespace GuzzleHttp\Handler;
use GuzzleHttp\Promise as P; use GuzzleHttp\Promise as P;
use GuzzleHttp\Promise\Promise; use GuzzleHttp\Promise\Promise;
use GuzzleHttp\Psr7; use GuzzleHttp\Utils;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
/** /**
@ -23,6 +23,7 @@ class CurlMultiHandler
private $active; private $active;
private $handles = []; private $handles = [];
private $delays = []; private $delays = [];
private $options = [];
/** /**
* This handler accepts the following options: * This handler accepts the following options:
@ -30,6 +31,8 @@ class CurlMultiHandler
* - handle_factory: An optional factory used to create curl handles * - handle_factory: An optional factory used to create curl handles
* - select_timeout: Optional timeout (in seconds) to block before timing * - select_timeout: Optional timeout (in seconds) to block before timing
* out while selecting curl handles. Defaults to 1 second. * out while selecting curl handles. Defaults to 1 second.
* - options: An associative array of CURLMOPT_* options and
* corresponding values for curl_multi_setopt()
* *
* @param array $options * @param array $options
*/ */
@ -45,12 +48,23 @@ class CurlMultiHandler
} else { } else {
$this->selectTimeout = 1; $this->selectTimeout = 1;
} }
$this->options = isset($options['options']) ? $options['options'] : [];
} }
public function __get($name) public function __get($name)
{ {
if ($name === '_mh') { if ($name === '_mh') {
return $this->_mh = curl_multi_init(); $this->_mh = curl_multi_init();
foreach ($this->options as $option => $value) {
// A warning is raised in case of a wrong option.
curl_multi_setopt($this->_mh, $option, $value);
}
// Further calls to _mh will return the value directly, without entering the
// __get() method at all.
return $this->_mh;
} }
throw new \BadMethodCallException(); throw new \BadMethodCallException();
@ -88,7 +102,7 @@ class CurlMultiHandler
{ {
// Add any delayed handles if needed. // Add any delayed handles if needed.
if ($this->delays) { if ($this->delays) {
$currentTime = \GuzzleHttp\_current_time(); $currentTime = Utils::currentTime();
foreach ($this->delays as $id => $delay) { foreach ($this->delays as $id => $delay) {
if ($currentTime >= $delay) { if ($currentTime >= $delay) {
unset($this->delays[$id]); unset($this->delays[$id]);
@ -140,7 +154,7 @@ class CurlMultiHandler
if (empty($easy->options['delay'])) { if (empty($easy->options['delay'])) {
curl_multi_add_handle($this->_mh, $easy->handle); curl_multi_add_handle($this->_mh, $easy->handle);
} else { } else {
$this->delays[$id] = \GuzzleHttp\_current_time() + ($easy->options['delay'] / 1000); $this->delays[$id] = Utils::currentTime() + ($easy->options['delay'] / 1000);
} }
} }
@ -192,7 +206,7 @@ class CurlMultiHandler
private function timeToNext() private function timeToNext()
{ {
$currentTime = \GuzzleHttp\_current_time(); $currentTime = Utils::currentTime();
$nextTime = PHP_INT_MAX; $nextTime = PHP_INT_MAX;
foreach ($this->delays as $time) { foreach ($this->delays as $time) {
if ($time < $nextTime) { if ($time < $nextTime) {

View File

@ -66,7 +66,7 @@ class MockHandler implements \Countable
throw new \OutOfBoundsException('Mock queue is empty'); throw new \OutOfBoundsException('Mock queue is empty');
} }
if (isset($options['delay'])) { if (isset($options['delay']) && is_numeric($options['delay'])) {
usleep($options['delay'] * 1000); usleep($options['delay'] * 1000);
} }
@ -175,6 +175,11 @@ class MockHandler implements \Countable
return count($this->queue); return count($this->queue);
} }
public function reset()
{
$this->queue = [];
}
private function invokeStats( private function invokeStats(
RequestInterface $request, RequestInterface $request,
array $options, array $options,

View File

@ -1,12 +1,13 @@
<?php <?php
namespace GuzzleHttp\Handler; namespace GuzzleHttp\Handler;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Exception\ConnectException; use GuzzleHttp\Exception\ConnectException;
use GuzzleHttp\Exception\RequestException;
use GuzzleHttp\Promise\FulfilledPromise; use GuzzleHttp\Promise\FulfilledPromise;
use GuzzleHttp\Promise\PromiseInterface; use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Psr7; use GuzzleHttp\Psr7;
use GuzzleHttp\TransferStats; use GuzzleHttp\TransferStats;
use GuzzleHttp\Utils;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\StreamInterface; use Psr\Http\Message\StreamInterface;
@ -33,7 +34,7 @@ class StreamHandler
usleep($options['delay'] * 1000); usleep($options['delay'] * 1000);
} }
$startTime = isset($options['on_stats']) ? \GuzzleHttp\_current_time() : null; $startTime = isset($options['on_stats']) ? Utils::currentTime() : null;
try { try {
// Does not support the expect header. // Does not support the expect header.
@ -82,7 +83,7 @@ class StreamHandler
$stats = new TransferStats( $stats = new TransferStats(
$request, $request,
$response, $response,
\GuzzleHttp\_current_time() - $startTime, Utils::currentTime() - $startTime,
$error, $error,
[] []
); );

View File

@ -1,7 +1,9 @@
<?php <?php
namespace GuzzleHttp; namespace GuzzleHttp;
use GuzzleHttp\Promise\PromiseInterface;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
/** /**
* Creates a composed Guzzle handler function by stacking middlewares on top of * Creates a composed Guzzle handler function by stacking middlewares on top of
@ -9,7 +11,7 @@ use Psr\Http\Message\RequestInterface;
*/ */
class HandlerStack class HandlerStack
{ {
/** @var callable */ /** @var callable|null */
private $handler; private $handler;
/** @var array */ /** @var array */
@ -59,6 +61,8 @@ class HandlerStack
* *
* @param RequestInterface $request * @param RequestInterface $request
* @param array $options * @param array $options
*
* @return ResponseInterface|PromiseInterface
*/ */
public function __invoke(RequestInterface $request, array $options) public function __invoke(RequestInterface $request, array $options)
{ {

View File

@ -168,6 +168,11 @@ class MessageFormatter
); );
} }
/**
* Get headers from message as string
*
* @return string
*/
private function headers(MessageInterface $message) private function headers(MessageInterface $message)
{ {
$result = ''; $result = '';

View File

@ -1,9 +1,10 @@
<?php <?php
namespace GuzzleHttp; namespace GuzzleHttp;
use GuzzleHttp\Promise\EachPromise;
use GuzzleHttp\Promise\PromiseInterface;
use GuzzleHttp\Promise\PromisorInterface; use GuzzleHttp\Promise\PromisorInterface;
use Psr\Http\Message\RequestInterface; use Psr\Http\Message\RequestInterface;
use GuzzleHttp\Promise\EachPromise;
/** /**
* Sends an iterator of requests concurrently using a capped pool size. * Sends an iterator of requests concurrently using a capped pool size.
@ -69,6 +70,11 @@ class Pool implements PromisorInterface
$this->each = new EachPromise($requests(), $config); $this->each = new EachPromise($requests(), $config);
} }
/**
* Get promise
*
* @return PromiseInterface
*/
public function promise() public function promise()
{ {
return $this->each->promise(); return $this->each->promise();
@ -106,6 +112,11 @@ class Pool implements PromisorInterface
return $res; return $res;
} }
/**
* Execute callback(s)
*
* @return void
*/
private static function cmpCallback(array &$options, $name, array &$results) private static function cmpCallback(array &$options, $name, array &$results)
{ {
if (!isset($options[$name])) { if (!isset($options[$name])) {

View File

@ -66,6 +66,11 @@ class PrepareBodyMiddleware
return $fn(Psr7\modify_request($request, $modify), $options); return $fn(Psr7\modify_request($request, $modify), $options);
} }
/**
* Add expect header
*
* @return void
*/
private function addExpectHeader( private function addExpectHeader(
RequestInterface $request, RequestInterface $request,
array $options, array $options,

View File

@ -13,7 +13,7 @@ use Psr\Http\Message\UriInterface;
* Request redirect middleware. * Request redirect middleware.
* *
* Apply this middleware like other middleware using * Apply this middleware like other middleware using
* {@see GuzzleHttp\Middleware::redirect()}. * {@see \GuzzleHttp\Middleware::redirect()}.
*/ */
class RedirectMiddleware class RedirectMiddleware
{ {
@ -76,7 +76,7 @@ class RedirectMiddleware
/** /**
* @param RequestInterface $request * @param RequestInterface $request
* @param array $options * @param array $options
* @param ResponseInterface|PromiseInterface $response * @param ResponseInterface $response
* *
* @return ResponseInterface|PromiseInterface * @return ResponseInterface|PromiseInterface
*/ */
@ -118,6 +118,11 @@ class RedirectMiddleware
return $promise; return $promise;
} }
/**
* Enable tracking on promise.
*
* @return PromiseInterface
*/
private function withTracking(PromiseInterface $promise, $uri, $statusCode) private function withTracking(PromiseInterface $promise, $uri, $statusCode)
{ {
return $promise->then( return $promise->then(
@ -135,6 +140,13 @@ class RedirectMiddleware
); );
} }
/**
* Check for too many redirects
*
* @return void
*
* @throws TooManyRedirectsException Too many redirects.
*/
private function guardMax(RequestInterface $request, array &$options) private function guardMax(RequestInterface $request, array &$options)
{ {
$current = isset($options['__redirect_count']) $current = isset($options['__redirect_count'])
@ -172,13 +184,19 @@ class RedirectMiddleware
// would do. // would do.
$statusCode = $response->getStatusCode(); $statusCode = $response->getStatusCode();
if ($statusCode == 303 || if ($statusCode == 303 ||
($statusCode <= 302 && $request->getBody() && !$options['allow_redirects']['strict']) ($statusCode <= 302 && !$options['allow_redirects']['strict'])
) { ) {
$modify['method'] = 'GET'; $modify['method'] = 'GET';
$modify['body'] = ''; $modify['body'] = '';
} }
$modify['uri'] = $this->redirectUri($request, $response, $protocols); $uri = $this->redirectUri($request, $response, $protocols);
if (isset($options['idn_conversion']) && ($options['idn_conversion'] !== false)) {
$idnOptions = ($options['idn_conversion'] === true) ? IDNA_DEFAULT : $options['idn_conversion'];
$uri = Utils::idnUriConvert($uri, $idnOptions);
}
$modify['uri'] = $uri;
Psr7\rewind_body($request); Psr7\rewind_body($request);
// Add the Referer header if it is told to do so and only // Add the Referer header if it is told to do so and only

View File

@ -132,6 +132,14 @@ final class RequestOptions
*/ */
const HTTP_ERRORS = 'http_errors'; const HTTP_ERRORS = 'http_errors';
/**
* idn: (bool|int, default=true) A combination of IDNA_* constants for
* idn_to_ascii() PHP's function (see "options" parameter). Set to false to
* disable IDN support completely, or to true to use the default
* configuration (IDNA_DEFAULT constant).
*/
const IDN_CONVERSION = 'idn_conversion';
/** /**
* json: (mixed) Adds JSON data to a request. The provided value is JSON * json: (mixed) Adds JSON data to a request. The provided value is JSON
* encoded and a Content-Type header of application/json will be added to * encoded and a Content-Type header of application/json will be added to

View File

@ -47,11 +47,11 @@ class RetryMiddleware
* *
* @param int $retries * @param int $retries
* *
* @return int * @return int milliseconds.
*/ */
public static function exponentialDelay($retries) public static function exponentialDelay($retries)
{ {
return (int) pow(2, $retries - 1); return (int) pow(2, $retries - 1) * 1000;
} }
/** /**
@ -74,6 +74,11 @@ class RetryMiddleware
); );
} }
/**
* Execute fulfilled closure
*
* @return mixed
*/
private function onFulfilled(RequestInterface $req, array $options) private function onFulfilled(RequestInterface $req, array $options)
{ {
return function ($value) use ($req, $options) { return function ($value) use ($req, $options) {
@ -90,6 +95,11 @@ class RetryMiddleware
}; };
} }
/**
* Execute rejected closure
*
* @return callable
*/
private function onRejected(RequestInterface $req, array $options) private function onRejected(RequestInterface $req, array $options)
{ {
return function ($reason) use ($req, $options) { return function ($reason) use ($req, $options) {
@ -106,6 +116,9 @@ class RetryMiddleware
}; };
} }
/**
* @return self
*/
private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null) private function doRetry(RequestInterface $request, array $options, ResponseInterface $response = null)
{ {
$options['delay'] = call_user_func($this->delay, ++$options['retries'], $response); $options['delay'] = call_user_func($this->delay, ++$options['retries'], $response);

View File

@ -18,11 +18,11 @@ final class TransferStats
private $handlerErrorData; private $handlerErrorData;
/** /**
* @param RequestInterface $request Request that was sent. * @param RequestInterface $request Request that was sent.
* @param ResponseInterface $response Response received (if any) * @param ResponseInterface|null $response Response received (if any)
* @param float|null $transferTime Total handler transfer time. * @param float|null $transferTime Total handler transfer time.
* @param mixed $handlerErrorData Handler error data. * @param mixed $handlerErrorData Handler error data.
* @param array $handlerStats Handler specific stats. * @param array $handlerStats Handler specific stats.
*/ */
public function __construct( public function __construct(
RequestInterface $request, RequestInterface $request,
@ -93,7 +93,7 @@ final class TransferStats
/** /**
* Get the estimated time the request was being transferred by the handler. * Get the estimated time the request was being transferred by the handler.
* *
* @return float Time in seconds. * @return float|null Time in seconds.
*/ */
public function getTransferTime() public function getTransferTime()
{ {

View File

@ -0,0 +1,89 @@
<?php
namespace GuzzleHttp;
use GuzzleHttp\Exception\InvalidArgumentException;
use Psr\Http\Message\UriInterface;
use Symfony\Polyfill\Intl\Idn\Idn;
final class Utils
{
/**
* Wrapper for the hrtime() or microtime() functions
* (depending on the PHP version, one of the two is used)
*
* @return float|mixed UNIX timestamp
*
* @internal
*/
public static function currentTime()
{
return function_exists('hrtime') ? hrtime(true) / 1e9 : microtime(true);
}
/**
* @param int $options
*
* @return UriInterface
* @throws InvalidArgumentException
*
* @internal
*/
public static function idnUriConvert(UriInterface $uri, $options = 0)
{
if ($uri->getHost()) {
$asciiHost = self::idnToAsci($uri->getHost(), $options, $info);
if ($asciiHost === false) {
$errorBitSet = isset($info['errors']) ? $info['errors'] : 0;
$errorConstants = array_filter(array_keys(get_defined_constants()), function ($name) {
return substr($name, 0, 11) === 'IDNA_ERROR_';
});
$errors = [];
foreach ($errorConstants as $errorConstant) {
if ($errorBitSet & constant($errorConstant)) {
$errors[] = $errorConstant;
}
}
$errorMessage = 'IDN conversion failed';
if ($errors) {
$errorMessage .= ' (errors: ' . implode(', ', $errors) . ')';
}
throw new InvalidArgumentException($errorMessage);
} else {
if ($uri->getHost() !== $asciiHost) {
// Replace URI only if the ASCII version is different
$uri = $uri->withHost($asciiHost);
}
}
}
return $uri;
}
/**
* @param string $domain
* @param int $options
* @param array $info
*
* @return string|false
*/
private static function idnToAsci($domain, $options, &$info = [])
{
if (\preg_match('%^[ -~]+$%', $domain) === 1) {
return $domain;
}
if (\extension_loaded('intl') && defined('INTL_IDNA_VARIANT_UTS46')) {
return \idn_to_ascii($domain, $options, INTL_IDNA_VARIANT_UTS46, $info);
}
/*
* The Idn class is marked as @internal. We've locked the version to
* symfony/polyfill-intl-idn to avoid issues in the future.
*/
return Idn::idn_to_ascii($domain, $options, Idn::INTL_IDNA_VARIANT_UTS46, $info);
}
}

View File

@ -56,7 +56,7 @@ function describe_type($input)
/** /**
* Parses an array of header lines into an associative array of headers. * Parses an array of header lines into an associative array of headers.
* *
* @param array $lines Header lines array of strings in the following * @param iterable $lines Header lines array of strings in the following
* format: "Name: Value" * format: "Name: Value"
* @return array * @return array
*/ */
@ -97,8 +97,8 @@ function debug_resource($value = null)
* *
* The returned handler is not wrapped by any default middlewares. * The returned handler is not wrapped by any default middlewares.
* *
* @throws \RuntimeException if no viable Handler is available.
* @return callable Returns the best handler for the given system. * @return callable Returns the best handler for the given system.
* @throws \RuntimeException if no viable Handler is available.
*/ */
function choose_handler() function choose_handler()
{ {
@ -332,15 +332,3 @@ function json_encode($value, $options = 0, $depth = 512)
return $json; return $json;
} }
/**
* Wrapper for the hrtime() or microtime() functions
* (depending on the PHP version, one of the two is used)
*
* @return float|mixed UNIX timestamp
* @internal
*/
function _current_time()
{
return function_exists('hrtime') ? hrtime(true) / 1e9 : microtime(true);
}

View File

@ -14,7 +14,6 @@ namespace Monolog;
use Psr\Log\LoggerInterface; use Psr\Log\LoggerInterface;
use Psr\Log\LogLevel; use Psr\Log\LogLevel;
use Monolog\Handler\AbstractHandler; use Monolog\Handler\AbstractHandler;
use Monolog\Registry;
/** /**
* Monolog error handler * Monolog error handler

View File

@ -142,8 +142,12 @@ class NormalizerFormatter implements FormatterInterface
$data['faultactor'] = $e->faultactor; $data['faultactor'] = $e->faultactor;
} }
if (isset($e->detail) && (is_string($e->detail) || is_object($e->detail) || is_array($e->detail))) { if (isset($e->detail)) {
$data['detail'] = is_string($e->detail) ? $e->detail : reset($e->detail); if (is_string($e->detail)) {
$data['detail'] = $e->detail;
} elseif (is_object($e->detail) || is_array($e->detail)) {
$data['detail'] = $this->toJson($e->detail, true);
}
} }
} }

View File

@ -33,8 +33,8 @@ abstract class AbstractHandler implements HandlerInterface, ResettableInterface
protected $processors = array(); protected $processors = array();
/** /**
* @param int $level The minimum logging level at which this handler will be triggered * @param int|string $level The minimum logging level at which this handler will be triggered
* @param bool $bubble Whether the messages that are handled can bubble up the stack or not * @param bool $bubble Whether the messages that are handled can bubble up the stack or not
*/ */
public function __construct($level = Logger::DEBUG, $bubble = true) public function __construct($level = Logger::DEBUG, $bubble = true)
{ {

View File

@ -12,6 +12,7 @@
namespace Monolog\Handler; namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils;
/** /**
* Stores logs to files that are rotated every day and a limited number of files are kept. * Stores logs to files that are rotated every day and a limited number of files are kept.
@ -45,7 +46,7 @@ class RotatingFileHandler extends StreamHandler
*/ */
public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false) public function __construct($filename, $maxFiles = 0, $level = Logger::DEBUG, $bubble = true, $filePermission = null, $useLocking = false)
{ {
$this->filename = $filename; $this->filename = Utils::canonicalizePath($filename);
$this->maxFiles = (int) $maxFiles; $this->maxFiles = (int) $maxFiles;
$this->nextRotation = new \DateTime('tomorrow'); $this->nextRotation = new \DateTime('tomorrow');
$this->filenameFormat = '{filename}-{date}'; $this->filenameFormat = '{filename}-{date}';

View File

@ -12,6 +12,7 @@
namespace Monolog\Handler; namespace Monolog\Handler;
use Monolog\Logger; use Monolog\Logger;
use Monolog\Utils;
/** /**
* Stores to any stream resource * Stores to any stream resource
@ -45,7 +46,7 @@ class StreamHandler extends AbstractProcessingHandler
if (is_resource($stream)) { if (is_resource($stream)) {
$this->stream = $stream; $this->stream = $stream;
} elseif (is_string($stream)) { } elseif (is_string($stream)) {
$this->url = $stream; $this->url = Utils::canonicalizePath($stream);
} else { } else {
throw new \InvalidArgumentException('A stream must either be a resource or a string.'); throw new \InvalidArgumentException('A stream must either be a resource or a string.');
} }

View File

@ -52,7 +52,7 @@ class GitProcessor implements ProcessorInterface
} }
$branches = `git branch -v --no-abbrev`; $branches = `git branch -v --no-abbrev`;
if (preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) { if ($branches && preg_match('{^\* (.+?)\s+([a-f0-9]{40})(?:\s|$)}m', $branches, $matches)) {
return self::$cache = array( return self::$cache = array(
'branch' => $matches[1], 'branch' => $matches[1],
'commit' => $matches[2], 'commit' => $matches[2],

View File

@ -23,6 +23,36 @@ class Utils
return 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class; return 'c' === $class[0] && 0 === strpos($class, "class@anonymous\0") ? get_parent_class($class).'@anonymous' : $class;
} }
/**
* Makes sure if a relative path is passed in it is turned into an absolute path
*
* @param string $streamUrl stream URL or path without protocol
*
* @return string
*/
public static function canonicalizePath($streamUrl)
{
$prefix = '';
if ('file://' === substr($streamUrl, 0, 7)) {
$streamUrl = substr($streamUrl, 7);
$prefix = 'file://';
}
// other type of stream, not supported
if (false !== strpos($streamUrl, '://')) {
return $streamUrl;
}
// already absolute
if (substr($streamUrl, 0, 1) === '/' || substr($streamUrl, 1, 1) === ':' || substr($streamUrl, 0, 2) === '\\\\') {
return $prefix.$streamUrl;
}
$streamUrl = getcwd() . '/' . $streamUrl;
return $prefix.$streamUrl;
}
/** /**
* Return the JSON representation of a value * Return the JSON representation of a value
* *

View File

@ -0,0 +1,287 @@
<?php
/*
* Copyright (c) 2014 TrueServer B.V.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is furnished
* to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
* Originally forked from
* https://github.com/true/php-punycode/blob/v2.1.1/src/Punycode.php
*/
namespace Symfony\Polyfill\Intl\Idn;
/**
* Partial intl implementation in pure PHP.
*
* Implemented:
* - idn_to_ascii - Convert domain name to IDNA ASCII form
* - idn_to_utf8 - Convert domain name from IDNA ASCII to Unicode
*
* @author Renan Gonçalves <renan.saddam@gmail.com>
* @author Sebastian Kroczek <sk@xbug.de>
* @author Dmitry Lukashin <dmitry@lukashin.ru>
* @author Laurent Bassin <laurent@bassin.info>
*
* @internal
*/
final class Idn
{
const INTL_IDNA_VARIANT_2003 = 0;
const INTL_IDNA_VARIANT_UTS46 = 1;
private static $encodeTable = array(
'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l',
'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x',
'y', 'z', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
);
private static $decodeTable = array(
'a' => 0, 'b' => 1, 'c' => 2, 'd' => 3, 'e' => 4, 'f' => 5,
'g' => 6, 'h' => 7, 'i' => 8, 'j' => 9, 'k' => 10, 'l' => 11,
'm' => 12, 'n' => 13, 'o' => 14, 'p' => 15, 'q' => 16, 'r' => 17,
's' => 18, 't' => 19, 'u' => 20, 'v' => 21, 'w' => 22, 'x' => 23,
'y' => 24, 'z' => 25, '0' => 26, '1' => 27, '2' => 28, '3' => 29,
'4' => 30, '5' => 31, '6' => 32, '7' => 33, '8' => 34, '9' => 35,
);
public static function idn_to_ascii($domain, $options, $variant, &$idna_info = array())
{
if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) {
@trigger_error('idn_to_ascii(): INTL_IDNA_VARIANT_2003 is deprecated', E_USER_DEPRECATED);
}
if (self::INTL_IDNA_VARIANT_UTS46 === $variant) {
$domain = mb_strtolower($domain, 'utf-8');
}
$parts = explode('.', $domain);
foreach ($parts as $i => &$part) {
if ('' === $part && \count($parts) > 1 + $i) {
return false;
}
if (false === $part = self::encodePart($part)) {
return false;
}
}
$output = implode('.', $parts);
$idna_info = array(
'result' => \strlen($output) > 255 ? false : $output,
'isTransitionalDifferent' => false,
'errors' => 0,
);
return $idna_info['result'];
}
public static function idn_to_utf8($domain, $options, $variant, &$idna_info = array())
{
if (\PHP_VERSION_ID >= 70200 && self::INTL_IDNA_VARIANT_2003 === $variant) {
@trigger_error('idn_to_utf8(): INTL_IDNA_VARIANT_2003 is deprecated', E_USER_DEPRECATED);
}
$parts = explode('.', $domain);
foreach ($parts as &$part) {
$length = \strlen($part);
if ($length < 1 || 63 < $length) {
continue;
}
if (0 !== strpos($part, 'xn--')) {
continue;
}
$part = substr($part, 4);
$part = self::decodePart($part);
}
$output = implode('.', $parts);
$idna_info = array(
'result' => \strlen($output) > 255 ? false : $output,
'isTransitionalDifferent' => false,
'errors' => 0,
);
return $idna_info['result'];
}
private static function encodePart($input)
{
if (\substr($input, 0, 1) === '-' || \substr($input, -1) === '-') {
return false;
}
$codePoints = self::listCodePoints($input);
$n = 128;
$bias = 72;
$delta = 0;
$h = $b = \count($codePoints['basic']);
$output = '';
foreach ($codePoints['basic'] as $code) {
$output .= mb_chr($code, 'utf-8');
}
if ($input === $output) {
return $output;
}
if ($b > 0) {
$output .= '-';
}
$codePoints['nonBasic'] = array_unique($codePoints['nonBasic']);
sort($codePoints['nonBasic']);
$i = 0;
$length = mb_strlen($input, 'utf-8');
while ($h < $length) {
$m = $codePoints['nonBasic'][$i++];
$delta += ($m - $n) * ($h + 1);
$n = $m;
foreach ($codePoints['all'] as $c) {
if ($c < $n || $c < 128) {
++$delta;
}
if ($c === $n) {
$q = $delta;
for ($k = 36;; $k += 36) {
$t = self::calculateThreshold($k, $bias);
if ($q < $t) {
break;
}
$code = $t + (($q - $t) % (36 - $t));
$output .= self::$encodeTable[$code];
$q = ($q - $t) / (36 - $t);
}
$output .= self::$encodeTable[$q];
$bias = self::adapt($delta, $h + 1, ($h === $b));
$delta = 0;
++$h;
}
}
++$delta;
++$n;
}
$output = 'xn--'.$output;
return \strlen($output) < 1 || 63 < \strlen($output) ? false : strtolower($output);
}
private static function listCodePoints($input)
{
$codePoints = array(
'all' => array(),
'basic' => array(),
'nonBasic' => array(),
);
$length = mb_strlen($input, 'utf-8');
for ($i = 0; $i < $length; ++$i) {
$char = mb_substr($input, $i, 1, 'utf-8');
$code = mb_ord($char, 'utf-8');
if ($code < 128) {
$codePoints['all'][] = $codePoints['basic'][] = $code;
} else {
$codePoints['all'][] = $codePoints['nonBasic'][] = $code;
}
}
return $codePoints;
}
private static function calculateThreshold($k, $bias)
{
if ($k <= $bias + 1) {
return 1;
}
if ($k >= $bias + 26) {
return 26;
}
return $k - $bias;
}
private static function adapt($delta, $numPoints, $firstTime)
{
$delta = (int) ($firstTime ? $delta / 700 : $delta / 2);
$delta += (int) ($delta / $numPoints);
$k = 0;
while ($delta > 35 * 13) {
$delta = (int) ($delta / 35);
$k = $k + 36;
}
return $k + (int) (36 * $delta / ($delta + 38));
}
private static function decodePart($input)
{
$n = 128;
$i = 0;
$bias = 72;
$output = '';
$pos = strrpos($input, '-');
if (false !== $pos) {
$output = substr($input, 0, $pos++);
} else {
$pos = 0;
}
$outputLength = \strlen($output);
$inputLength = \strlen($input);
while ($pos < $inputLength) {
$oldi = $i;
$w = 1;
for ($k = 36;; $k += 36) {
$digit = self::$decodeTable[$input[$pos++]];
$i += $digit * $w;
$t = self::calculateThreshold($k, $bias);
if ($digit < $t) {
break;
}
$w *= 36 - $t;
}
$bias = self::adapt($i - $oldi, ++$outputLength, 0 === $oldi);
$n = $n + (int) ($i / $outputLength);
$i = $i % $outputLength;
$output = mb_substr($output, 0, $i, 'utf-8').mb_chr($n, 'utf-8').mb_substr($output, $i, $outputLength - 1, 'utf-8');
++$i;
}
return $output;
}
}

View File

@ -0,0 +1,19 @@
Copyright (c) 2018-2019 Fabien Potencier
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is furnished
to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

View File

@ -0,0 +1,141 @@
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
use Symfony\Polyfill\Intl\Idn as p;
if (extension_loaded('intl')) {
return;
}
if (!defined('U_IDNA_PROHIBITED_ERROR')) {
define('U_IDNA_PROHIBITED_ERROR', 66560);
}
if (!defined('U_IDNA_ERROR_START')) {
define('U_IDNA_ERROR_START', 66560);
}
if (!defined('U_IDNA_UNASSIGNED_ERROR')) {
define('U_IDNA_UNASSIGNED_ERROR', 66561);
}
if (!defined('U_IDNA_CHECK_BIDI_ERROR')) {
define('U_IDNA_CHECK_BIDI_ERROR', 66562);
}
if (!defined('U_IDNA_STD3_ASCII_RULES_ERROR')) {
define('U_IDNA_STD3_ASCII_RULES_ERROR', 66563);
}
if (!defined('U_IDNA_ACE_PREFIX_ERROR')) {
define('U_IDNA_ACE_PREFIX_ERROR', 66564);
}
if (!defined('U_IDNA_VERIFICATION_ERROR')) {
define('U_IDNA_VERIFICATION_ERROR', 66565);
}
if (!defined('U_IDNA_LABEL_TOO_LONG_ERROR')) {
define('U_IDNA_LABEL_TOO_LONG_ERROR', 66566);
}
if (!defined('U_IDNA_ZERO_LENGTH_LABEL_ERROR')) {
define('U_IDNA_ZERO_LENGTH_LABEL_ERROR', 66567);
}
if (!defined('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR')) {
define('U_IDNA_DOMAIN_NAME_TOO_LONG_ERROR', 66568);
}
if (!defined('U_IDNA_ERROR_LIMIT')) {
define('U_IDNA_ERROR_LIMIT', 66569);
}
if (!defined('U_STRINGPREP_PROHIBITED_ERROR')) {
define('U_STRINGPREP_PROHIBITED_ERROR', 66560);
}
if (!defined('U_STRINGPREP_UNASSIGNED_ERROR')) {
define('U_STRINGPREP_UNASSIGNED_ERROR', 66561);
}
if (!defined('U_STRINGPREP_CHECK_BIDI_ERROR')) {
define('U_STRINGPREP_CHECK_BIDI_ERROR', 66562);
}
if (!defined('IDNA_DEFAULT')) {
define('IDNA_DEFAULT', 0);
}
if (!defined('IDNA_ALLOW_UNASSIGNED')) {
define('IDNA_ALLOW_UNASSIGNED', 1);
}
if (!defined('IDNA_USE_STD3_RULES')) {
define('IDNA_USE_STD3_RULES', 2);
}
if (!defined('IDNA_CHECK_BIDI')) {
define('IDNA_CHECK_BIDI', 4);
}
if (!defined('IDNA_CHECK_CONTEXTJ')) {
define('IDNA_CHECK_CONTEXTJ', 8);
}
if (!defined('IDNA_NONTRANSITIONAL_TO_ASCII')) {
define('IDNA_NONTRANSITIONAL_TO_ASCII', 16);
}
if (!defined('IDNA_NONTRANSITIONAL_TO_UNICODE')) {
define('IDNA_NONTRANSITIONAL_TO_UNICODE', 32);
}
if (!defined('INTL_IDNA_VARIANT_2003')) {
define('INTL_IDNA_VARIANT_2003', 0);
}
if (!defined('INTL_IDNA_VARIANT_UTS46')) {
define('INTL_IDNA_VARIANT_UTS46', 1);
}
if (!defined('IDNA_ERROR_EMPTY_LABEL')) {
define('IDNA_ERROR_EMPTY_LABEL', 1);
}
if (!defined('IDNA_ERROR_LABEL_TOO_LONG')) {
define('IDNA_ERROR_LABEL_TOO_LONG', 2);
}
if (!defined('IDNA_ERROR_DOMAIN_NAME_TOO_LONG')) {
define('IDNA_ERROR_DOMAIN_NAME_TOO_LONG', 4);
}
if (!defined('IDNA_ERROR_LEADING_HYPHEN')) {
define('IDNA_ERROR_LEADING_HYPHEN', 8);
}
if (!defined('IDNA_ERROR_TRAILING_HYPHEN')) {
define('IDNA_ERROR_TRAILING_HYPHEN', 16);
}
if (!defined('IDNA_ERROR_HYPHEN_3_4')) {
define('IDNA_ERROR_HYPHEN_3_4', 32);
}
if (!defined('IDNA_ERROR_LEADING_COMBINING_MARK')) {
define('IDNA_ERROR_LEADING_COMBINING_MARK', 64);
}
if (!defined('IDNA_ERROR_DISALLOWED')) {
define('IDNA_ERROR_DISALLOWED', 128);
}
if (!defined('IDNA_ERROR_PUNYCODE')) {
define('IDNA_ERROR_PUNYCODE', 256);
}
if (!defined('IDNA_ERROR_LABEL_HAS_DOT')) {
define('IDNA_ERROR_LABEL_HAS_DOT', 512);
}
if (!defined('IDNA_ERROR_INVALID_ACE_LABEL')) {
define('IDNA_ERROR_INVALID_ACE_LABEL', 1024);
}
if (!defined('IDNA_ERROR_BIDI')) {
define('IDNA_ERROR_BIDI', 2048);
}
if (!defined('IDNA_ERROR_CONTEXTJ')) {
define('IDNA_ERROR_CONTEXTJ', 4096);
}
if (PHP_VERSION_ID < 70400) {
if (!function_exists('idn_to_ascii')) {
function idn_to_ascii($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_2003, &$idna_info = array()) { return p\Idn::idn_to_ascii($domain, $options, $variant, $idna_info); }
}
if (!function_exists('idn_to_utf8')) {
function idn_to_utf8($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_2003, &$idna_info = array()) { return p\Idn::idn_to_utf8($domain, $options, $variant, $idna_info); }
}
} else {
if (!function_exists('idn_to_ascii')) {
function idn_to_ascii($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = array()) { return p\Idn::idn_to_ascii($domain, $options, $variant, $idna_info); }
}
if (!function_exists('idn_to_utf8')) {
function idn_to_utf8($domain, $options = IDNA_DEFAULT, $variant = INTL_IDNA_VARIANT_UTS46, &$idna_info = array()) { return p\Idn::idn_to_utf8($domain, $options, $variant, $idna_info); }
}
}

Some files were not shown because too many files have changed in this diff Show More