Commit realizado el 12:13:52 08-04-2024

This commit is contained in:
Pagina Web Monito
2024-04-08 12:13:55 -04:00
commit 0c33094de9
7815 changed files with 1365694 additions and 0 deletions

View File

@@ -0,0 +1,67 @@
<?php
namespace WPMailSMTP;
use WPMailSMTP\Providers\MailerAbstract;
/**
* Abstract class AbstractConnection.
*
* @since 3.7.0
*/
abstract class AbstractConnection implements ConnectionInterface {
/**
* Get the connection title.
*
* @since 3.7.0
*
* @return string
*/
public function get_title() {
return sprintf(
'%s (%s)',
$this->get_name(),
wp_mail_smtp()->get_providers()->get_options( $this->get_mailer_slug(), $this )->get_title()
);
}
/**
* Get connection mailer slug.
*
* @since 3.7.0
*
* @return string
*/
public function get_mailer_slug() {
return $this->get_options()->get( 'mail', 'mailer' );
}
/**
* Get connection mailer object.
*
* @since 3.7.0
*
* @return MailerAbstract
*/
public function get_mailer() {
$phpmailer = wp_mail_smtp()->get_processor()->get_phpmailer();
return wp_mail_smtp()->get_providers()->get_mailer( $this->get_mailer_slug(), $phpmailer, $this );
}
/**
* Whether the connection is primary or not.
*
* @since 3.7.0
*
* @return bool
*/
public function is_primary() {
return false;
}
}

View File

@@ -0,0 +1,164 @@
<?php
namespace WPMailSMTP\Admin;
use WPMailSMTP\Debug;
use WPMailSMTP\Options;
/**
* WP Mail SMTP admin bar menu.
*
* @since 2.3.0
*/
class AdminBarMenu {
/**
* Initialize class.
*
* @since 2.3.0
*/
public function init() {
$this->hooks();
}
/**
* Register hooks.
*
* @since 2.3.0
*/
public function hooks() {
add_action( 'wp_enqueue_scripts', [ $this, 'enqueues' ] );
add_action( 'admin_enqueue_scripts', [ $this, 'enqueues' ] );
add_action( 'admin_bar_menu', [ $this, 'register' ], 999 );
}
/**
* Check if current user has access to see admin bar menu.
*
* @since 2.3.0
*
* @return bool
*/
public function has_access() {
$access = false;
if (
is_user_logged_in() &&
current_user_can( wp_mail_smtp()->get_capability_manage_options() )
) {
$access = true;
}
return apply_filters( 'wp_mail_smtp_admin_adminbarmenu_has_access', $access );
}
/**
* Check if new notifications are available.
*
* @since 2.3.0
*
* @return bool
*/
public function has_notifications() {
return wp_mail_smtp()->get_notifications()->get_count();
}
/**
* Enqueue styles.
*
* @since 2.3.0
*/
public function enqueues() {
if ( ! is_admin_bar_showing() ) {
return;
}
if ( ! $this->has_access() ) {
return;
}
wp_enqueue_style(
'wp-mail-smtp-admin-bar',
wp_mail_smtp()->assets_url . '/css/admin-bar.min.css',
[],
WPMS_PLUGIN_VER
);
}
/**
* Register and render admin menu bar.
*
* @since 2.3.0
*
* @param \WP_Admin_Bar $wp_admin_bar WordPress Admin Bar object.
*/
public function register( \WP_Admin_Bar $wp_admin_bar ) {
if (
! $this->has_access() ||
(
(
empty( Debug::get_last() ) ||
(bool) Options::init()->get( 'general', 'email_delivery_errors_hidden' )
) &&
empty( $this->has_notifications() )
)
) {
return;
}
$items = apply_filters(
'wp_mail_smtp_admin_adminbarmenu_register',
[
'main_menu',
],
$wp_admin_bar
);
foreach ( $items as $item ) {
$this->{ $item }( $wp_admin_bar );
do_action( "wp_mail_smtp_admin_adminbarmenu_register_{$item}_after", $wp_admin_bar );
}
}
/**
* Render primary top-level admin menu bar item.
*
* @since 2.3.0
*
* @param \WP_Admin_Bar $wp_admin_bar WordPress Admin Bar object.
*/
public function main_menu( \WP_Admin_Bar $wp_admin_bar ) {
if (
! empty( Debug::get_last() ) &&
! (bool) Options::init()->get( 'general', 'email_delivery_errors_hidden' )
) {
$indicator = ' <span class="wp-mail-smtp-admin-bar-menu-error">!</span>';
} elseif ( ! empty( $this->has_notifications() ) ) {
$count = $this->has_notifications() < 10 ? $this->has_notifications() : '!';
$indicator = ' <div class="wp-mail-smtp-admin-bar-menu-notification-counter"><span>' . $count . '</span></div>';
}
if ( ! isset( $indicator ) ) {
return;
}
$wp_admin_bar->add_menu(
[
'id' => 'wp-mail-smtp-menu',
'title' => 'WP Mail SMTP' . $indicator,
'href' => apply_filters(
'wp_mail_smtp_admin_adminbarmenu_main_menu_href',
wp_mail_smtp()->get_admin()->get_admin_page_url()
),
]
);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,437 @@
<?php
namespace WPMailSMTP\Admin;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Debug;
use WPMailSMTP\Helpers\UI;
use WPMailSMTP\Options;
/**
* Class ConnectionSettings.
*
* @since 3.7.0
*/
class ConnectionSettings {
/**
* The Connection object.
*
* @since 3.7.0
*
* @var ConnectionInterface
*/
private $connection;
/**
* After process scroll to anchor.
*
* @since 3.7.0
*
* @var false|string
*/
private $scroll_to = false;
/**
* Constructor.
*
* @since 3.7.0
*
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $connection ) {
$this->connection = $connection;
}
/**
* Display connection settings.
*
* @since 3.7.0
*/
public function display() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded, Generic.Metrics.NestingLevel.MaxExceeded
$mailer = $this->connection->get_mailer_slug();
$connection_options = $this->connection->get_options();
$disabled_email = in_array( $mailer, [ 'zoho' ], true ) ? 'disabled' : '';
$disabled_name = in_array( $mailer, [ 'outlook' ], true ) ? 'disabled' : '';
if ( empty( $mailer ) || ! in_array( $mailer, Options::$mailers, true ) ) {
$mailer = 'mail';
}
$mailer_supported_settings = wp_mail_smtp()->get_providers()->get_options( $mailer )->get_supports();
?>
<!-- From Email -->
<div class="wp-mail-smtp-setting-group js-wp-mail-smtp-setting-from_email" style="display: <?php echo empty( $mailer_supported_settings['from_email'] ) ? 'none' : 'block'; ?>;">
<div id="wp-mail-smtp-setting-row-from_email" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-email wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-from_email"><?php esc_html_e( 'From Email', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<input name="wp-mail-smtp[mail][from_email]" type="email"
value="<?php echo esc_attr( $connection_options->get( 'mail', 'from_email' ) ); ?>"
id="wp-mail-smtp-setting-from_email" spellcheck="false"
placeholder="<?php echo esc_attr( wp_mail_smtp()->get_processor()->get_default_email() ); ?>"
<?php disabled( $connection_options->is_const_defined( 'mail', 'from_email' ) || ! empty( $disabled_email ) ); ?>
/>
<?php if ( ! in_array( $mailer, [ 'zoho' ], true ) ) : ?>
<p class="desc">
<?php esc_html_e( 'The email address that emails are sent from.', 'wp-mail-smtp' ); ?>
</p>
<p class="desc">
<?php esc_html_e( 'If you\'re using an email provider (Yahoo, Outlook.com, etc) this should be your email address for that account.', 'wp-mail-smtp' ); ?>
</p>
<p class="desc">
<?php esc_html_e( 'Please note that other plugins can change this, to prevent this use the setting below.', 'wp-mail-smtp' ); ?>
</p>
<?php endif; ?>
</div>
</div>
<div id="wp-mail-smtp-setting-row-from_email_force" class="wp-mail-smtp-setting-row wp-mail-smtp-clear js-wp-mail-smtp-setting-from_email_force" style="display: <?php echo empty( $mailer_supported_settings['from_email_force'] ) ? 'none' : 'block'; ?>;">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-from_email_force"><?php esc_html_e( 'Force From Email', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[mail][from_email_force]',
'id' => 'wp-mail-smtp-setting-from_email_force',
'value' => 'true',
'checked' => (bool) $connection_options->get( 'mail', 'from_email_force' ),
'disabled' => $connection_options->is_const_defined( 'mail', 'from_email_force' ) || ! empty( $disabled_email ),
]
);
?>
<?php if ( ! empty( $disabled_email ) ) : ?>
<p class="desc">
<?php esc_html_e( 'Current provider will automatically force From Email to be the email address that you use to set up the OAuth connection below.', 'wp-mail-smtp' ); ?>
</p>
<?php else : ?>
<p class="desc">
<?php esc_html_e( 'If checked, the From Email setting above will be used for all emails, ignoring values set by other plugins.', 'wp-mail-smtp' ); ?>
</p>
<?php endif; ?>
</div>
</div>
</div>
<!-- From Name -->
<div class="wp-mail-smtp-setting-group js-wp-mail-smtp-setting-from_name" style="display: <?php echo empty( $mailer_supported_settings['from_name'] ) ? 'none' : 'block'; ?>;">
<div id="wp-mail-smtp-setting-row-from_name" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear ">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-from_name"><?php esc_html_e( 'From Name', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<input name="wp-mail-smtp[mail][from_name]" type="text"
value="<?php echo esc_attr( $connection_options->get( 'mail', 'from_name' ) ); ?>"
id="wp-mail-smtp-setting-from_name" spellcheck="false"
placeholder="<?php echo esc_attr( wp_mail_smtp()->get_processor()->get_default_name() ); ?>"
<?php disabled( $connection_options->is_const_defined( 'mail', 'from_name' ) || ! empty( $disabled_name ) ); ?>
/>
<?php if ( empty( $disabled_name ) ) : ?>
<p class="desc">
<?php esc_html_e( 'The name that emails are sent from.', 'wp-mail-smtp' ); ?>
</p>
<?php endif; ?>
</div>
</div>
<div id="wp-mail-smtp-setting-row-from_name_force" class="wp-mail-smtp-setting-row wp-mail-smtp-clear js-wp-mail-smtp-setting-from_name_force" style="display: <?php echo empty( $mailer_supported_settings['from_name_force'] ) ? 'none' : 'block'; ?>;">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-from_name_force"><?php esc_html_e( 'Force From Name', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[mail][from_name_force]',
'id' => 'wp-mail-smtp-setting-from_name_force',
'value' => 'true',
'checked' => (bool) $connection_options->get( 'mail', 'from_name_force' ),
'disabled' => $connection_options->is_const_defined( 'mail', 'from_name_force' ) || ! empty( $disabled_name ),
]
);
?>
<?php if ( ! empty( $disabled_name ) ) : ?>
<p class="desc">
<?php esc_html_e( 'Current provider doesn\'t support setting and forcing From Name. Emails will be sent on behalf of the account name used to setup the OAuth connection below.', 'wp-mail-smtp' ); ?>
</p>
<?php else : ?>
<p class="desc">
<?php esc_html_e( 'If checked, the From Name setting above will be used for all emails, ignoring values set by other plugins.', 'wp-mail-smtp' ); ?>
</p>
<?php endif; ?>
</div>
</div>
</div>
<!-- Return Path -->
<div id="wp-mail-smtp-setting-row-return_path" class="wp-mail-smtp-setting-row wp-mail-smtp-clear js-wp-mail-smtp-setting-return_path" style="display: <?php echo empty( $mailer_supported_settings['return_path'] ) ? 'none' : 'block'; ?>;">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-return_path"><?php esc_html_e( 'Return Path', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[mail][return_path]',
'id' => 'wp-mail-smtp-setting-return_path',
'value' => 'true',
'checked' => (bool) $connection_options->get( 'mail', 'return_path' ),
'disabled' => $connection_options->is_const_defined( 'mail', 'return_path' ),
]
);
?>
<p class="desc">
<?php esc_html_e( 'Return Path indicates where non-delivery receipts - or bounce messages - are to be sent.', 'wp-mail-smtp' ); ?><br/>
<?php esc_html_e( 'If unchecked, bounce messages may be lost.', 'wp-mail-smtp' ); ?>
</p>
</div>
</div>
<!-- Mailer -->
<div id="wp-mail-smtp-setting-row-mailer" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-mailer wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-mailer"><?php esc_html_e( 'Mailer', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<div class="wp-mail-smtp-mailers">
<?php foreach ( wp_mail_smtp()->get_providers()->get_options_all( $this->connection ) as $provider ) : ?>
<div class="wp-mail-smtp-mailer wp-mail-smtp-mailer-<?php echo esc_attr( $provider->get_slug() ); ?> <?php echo $mailer === $provider->get_slug() ? 'active' : ''; ?>">
<div class="wp-mail-smtp-mailer-image <?php echo $provider->is_recommended() ? 'is-recommended' : ''; ?>">
<img src="<?php echo esc_url( $provider->get_logo_url() ); ?>"
alt="<?php echo esc_attr( $provider->get_title() ); ?>">
</div>
<div class="wp-mail-smtp-mailer-text">
<?php if ( $provider->is_disabled() ) : ?>
<input type="radio" name="wp-mail-smtp[mail][mailer]" disabled
data-title="<?php echo esc_attr( $provider->get_title() ); ?>"
class="js-wp-mail-smtp-setting-mailer-radio-input educate"
id="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>"
value="<?php echo esc_attr( $provider->get_slug() ); ?>"
/>
<?php else : ?>
<input id="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>"
data-title="<?php echo esc_attr( $provider->get_title() ); ?>"
type="radio" name="wp-mail-smtp[mail][mailer]"
value="<?php echo esc_attr( $provider->get_slug() ); ?>"
class="js-wp-mail-smtp-setting-mailer-radio-input<?php echo $provider->is_disabled() ? ' educate' : ''; ?>"
<?php checked( $provider->get_slug(), $mailer ); ?>
<?php disabled( $connection_options->is_const_defined( 'mail', 'mailer' ) || $provider->is_disabled() ); ?>
/>
<?php endif; ?>
<label for="wp-mail-smtp-setting-mailer-<?php echo esc_attr( $provider->get_slug() ); ?>">
<?php echo esc_html( $provider->get_title() ); ?>
</label>
</div>
</div>
<?php endforeach; ?>
</div>
<!-- Suggest a mailer -->
<div class="wp-mail-smtp-suggest-new-mailer">
<p class="desc">
<?php esc_html_e( 'Don\'t see what you\'re looking for?', 'wp-mail-smtp' ); ?>
<?php
printf(
'<a href="%1$s" target="_blank" rel="noopener noreferrer">%2$s</a>',
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/suggest-a-mailer/', 'Suggest a Mailer' ) ),
esc_html__( 'Suggest a Mailer', 'wp-mail-smtp' )
);
?>
</p>
</div>
</div>
</div>
<!-- Mailer Options -->
<div class="wp-mail-smtp-setting-group wp-mail-smtp-mailer-options">
<?php foreach ( wp_mail_smtp()->get_providers()->get_options_all( $this->connection ) as $provider ) : ?>
<?php $provider_desc = $provider->get_description(); ?>
<div class="wp-mail-smtp-mailer-option wp-mail-smtp-mailer-option-<?php echo esc_attr( $provider->get_slug() ); ?> <?php echo $mailer === $provider->get_slug() ? 'active' : 'hidden'; ?>">
<?php if ( ! $provider->is_disabled() ) : ?>
<!-- Mailer Title/Notice/Description -->
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading <?php echo empty( $provider_desc ) ? 'no-desc' : ''; ?>">
<div class="wp-mail-smtp-setting-field">
<h2><?php echo esc_html( $provider->get_title() ); ?></h2>
<?php
$provider_edu_notice = $provider->get_notice( 'educational' );
$is_dismissed = (bool) get_user_meta( get_current_user_id(), "wp_mail_smtp_notice_educational_for_{$provider->get_slug()}_dismissed", true );
if ( ! empty( $provider_edu_notice ) && ! $is_dismissed ) :
?>
<p class="inline-notice inline-edu-notice"
data-notice="educational"
data-mailer="<?php echo esc_attr( $provider->get_slug() ); ?>">
<a href="#" title="<?php esc_attr_e( 'Dismiss this notice', 'wp-mail-smtp' ); ?>"
class="wp-mail-smtp-mailer-notice-dismiss js-wp-mail-smtp-mailer-notice-dismiss">
<span class="dashicons dashicons-dismiss"></span>
</a>
<?php echo wp_kses_post( $provider_edu_notice ); ?>
</p>
<?php endif; ?>
<?php if ( ! empty( $provider_desc ) ) : ?>
<p class="desc"><?php echo wp_kses_post( $provider_desc ); ?></p>
<?php endif; ?>
</div>
</div>
<?php endif; ?>
<?php $provider->display_options(); ?>
</div>
<?php endforeach; ?>
</div>
<?php
}
/**
* Process connection settings. Should be called before options save.
*
* @since 3.7.0
*
* @param array $data Connection data.
* @param array $old_data Old connection data.
*/
public function process( $data, $old_data ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded, Generic.Metrics.CyclomaticComplexity.TooHigh
// When checkbox is unchecked - it's not submitted at all, so we need to define its default false value.
if ( ! isset( $data['mail']['from_email_force'] ) ) {
$data['mail']['from_email_force'] = false;
}
if ( ! isset( $data['mail']['from_name_force'] ) ) {
$data['mail']['from_name_force'] = false;
}
if ( ! isset( $data['mail']['return_path'] ) ) {
$data['mail']['return_path'] = false;
}
if ( ! isset( $data['smtp']['autotls'] ) ) {
$data['smtp']['autotls'] = false;
}
if ( ! isset( $data['smtp']['auth'] ) ) {
$data['smtp']['auth'] = false;
}
// When switching mailers.
if (
! empty( $old_data['mail']['mailer'] ) &&
! empty( $data['mail']['mailer'] ) &&
$old_data['mail']['mailer'] !== $data['mail']['mailer']
) {
// Remove all debug messages when switching mailers.
Debug::clear();
// Save correct from email address if Zoho mailer is already configured.
if (
in_array( $data['mail']['mailer'], [ 'zoho' ], true ) &&
! empty( $old_data[ $data['mail']['mailer'] ]['user_details']['email'] )
) {
$data['mail']['from_email'] = $old_data[ $data['mail']['mailer'] ]['user_details']['email'];
}
}
// Prevent redirect to setup wizard from settings page after successful auth.
if (
! empty( $data['mail']['mailer'] ) &&
in_array( $data['mail']['mailer'], [ 'gmail', 'outlook', 'zoho' ], true )
) {
$data[ $data['mail']['mailer'] ]['is_setup_wizard_auth'] = false;
}
/**
* Filters connection data.
*
* @since 3.11.0
*
* @param array $data Connection data.
* @param array $old_data Old connection data.
*/
return apply_filters( 'wp_mail_smtp_admin_connection_settings_process_data', $data, $old_data );
}
/**
* Post process connection settings. Should be called after options save.
*
* @since 3.7.0
*
* @param array $data Connection data.
* @param array $old_data Old connection data.
*/
public function post_process( $data, $old_data ) {
// When switching mailers.
if (
! empty( $old_data['mail']['mailer'] ) &&
! empty( $data['mail']['mailer'] ) &&
$old_data['mail']['mailer'] !== $data['mail']['mailer']
) {
// Save correct from email address if Gmail mailer is already configured.
if ( $data['mail']['mailer'] === 'gmail' ) {
$gmail_auth = wp_mail_smtp()->get_providers()->get_auth( 'gmail', $this->connection );
$user_info = ! $gmail_auth->is_auth_required() ? $gmail_auth->get_user_info() : false;
if (
! empty( $user_info['email'] ) &&
is_email( $user_info['email'] ) !== false &&
(
empty( $data['mail']['from_email'] ) ||
$data['mail']['from_email'] !== $user_info['email']
)
) {
$data['mail']['from_email'] = $user_info['email'];
$this->connection->get_options()->set( $data, false, false );
}
}
}
}
/**
* Get connection settings admin page URL.
*
* @since 3.7.0
*
* @return string
*/
public function get_admin_page_url() {
/**
* Filters connection settings admin page URL.
*
* @since 3.7.0
*
* @param string $admin_page_url Connection settings admin page URL.
* @param ConnectionInterface $connection The Connection object.
*/
return apply_filters(
'wp_mail_smtp_admin_connection_settings_get_admin_page_url',
wp_mail_smtp()->get_admin()->get_admin_page_url(),
$this->connection
);
}
/**
* Get after process scroll to anchor. Returns `false` if scroll is not needed.
*
* @since 3.7.0
*/
public function get_scroll_to() {
return $this->scroll_to;
}
}

View File

@@ -0,0 +1,759 @@
<?php
namespace WPMailSMTP\Admin;
use WPMailSMTP\Admin\DebugEvents\DebugEvents;
use WPMailSMTP\Helpers\Helpers;
use WPMailSMTP\Options;
use WPMailSMTP\WP;
use WPMailSMTP\Reports\Reports;
use WPMailSMTP\Reports\Emails\Summary as SummaryReportEmail;
/**
* Dashboard Widget shows the number of sent emails in WP Dashboard.
*
* @since 2.9.0
*/
class DashboardWidget {
/**
* Instance slug.
*
* @since 2.9.0
*
* @const string
*/
const SLUG = 'dash_widget_lite';
/**
* The WP option key for storing the total number of sent emails.
*
* @since 2.9.0
* @since 3.0.0 Constant moved to Reports class.
*
* @const string
*/
const SENT_EMAILS_COUNTER_OPTION_KEY = Reports::SENT_EMAILS_COUNTER_OPTION_KEY;
/**
* Constructor.
*
* @since 2.9.0
*/
public function __construct() {
// Prevent the class initialization, if the dashboard widget hidden setting is enabled.
if ( Options::init()->get( 'general', 'dashboard_widget_hidden' ) ) {
return;
}
add_action( 'admin_init', [ $this, 'init' ] );
}
/**
* Init class.
*
* @since 2.9.0
*/
public function init() {
// This widget should be displayed for certain high-level users only.
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
return;
}
/**
* Filters whether the initialization of the dashboard widget should be allowed.
*
* @since 2.9.0
*
* @param bool $var If the dashboard widget should be initialized.
*/
if ( ! apply_filters( 'wp_mail_smtp_admin_dashboard_widget', '__return_true' ) ) {
return;
}
$this->hooks();
}
/**
* Widget hooks.
*
* @since 2.9.0
*/
public function hooks() {
add_action( 'admin_enqueue_scripts', [ $this, 'widget_scripts' ] );
add_action( 'wp_dashboard_setup', [ $this, 'widget_register' ] );
add_action( 'wp_ajax_wp_mail_smtp_' . static::SLUG . '_save_widget_meta', [ $this, 'save_widget_meta_ajax' ] );
add_action(
'wp_ajax_wp_mail_smtp_' . static::SLUG . '_enable_summary_report_email',
[
$this,
'enable_summary_report_email_ajax',
]
);
}
/**
* Load widget-specific scripts.
* Load them only on the admin dashboard page.
*
* @since 2.9.0
*/
public function widget_scripts() {
$screen = get_current_screen();
if ( ! isset( $screen->id ) || 'dashboard' !== $screen->id ) {
return;
}
$min = WP::asset_min();
wp_enqueue_style(
'wp-mail-smtp-dashboard-widget',
wp_mail_smtp()->assets_url . '/css/dashboard-widget.min.css',
[],
WPMS_PLUGIN_VER
);
wp_enqueue_script(
'wp-mail-smtp-chart',
wp_mail_smtp()->assets_url . '/js/vendor/chart.min.js',
[ 'moment' ],
'2.9.4.1',
true
);
wp_enqueue_script(
'wp-mail-smtp-dashboard-widget',
wp_mail_smtp()->assets_url . "/js/smtp-dashboard-widget{$min}.js",
[ 'jquery', 'wp-mail-smtp-chart' ],
WPMS_PLUGIN_VER,
true
);
wp_localize_script(
'wp-mail-smtp-dashboard-widget',
'wp_mail_smtp_dashboard_widget',
[
'slug' => static::SLUG,
'nonce' => wp_create_nonce( 'wp_mail_smtp_' . static::SLUG . '_nonce' ),
]
);
}
/**
* Register the widget.
*
* @since 2.9.0
*/
public function widget_register() {
global $wp_meta_boxes;
$widget_key = 'wp_mail_smtp_reports_widget_lite';
wp_add_dashboard_widget(
$widget_key,
esc_html__( 'WP Mail SMTP', 'wp-mail-smtp' ),
[ $this, 'widget_content' ]
);
// Attempt to place the widget at the top.
$normal_dashboard = $wp_meta_boxes['dashboard']['normal']['core'];
$widget_instance = [ $widget_key => $normal_dashboard[ $widget_key ] ];
unset( $normal_dashboard[ $widget_key ] );
$sorted_dashboard = array_merge( $widget_instance, $normal_dashboard );
//phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
$wp_meta_boxes['dashboard']['normal']['core'] = $sorted_dashboard;
}
/**
* Save a widget meta for a current user using AJAX.
*
* @since 2.9.0
*/
public function save_widget_meta_ajax() {
check_admin_referer( 'wp_mail_smtp_' . static::SLUG . '_nonce' );
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error();
}
$meta = ! empty( $_POST['meta'] ) ? sanitize_key( $_POST['meta'] ) : '';
$value = ! empty( $_POST['value'] ) ? sanitize_key( $_POST['value'] ) : 0;
$this->widget_meta( 'set', $meta, $value );
wp_send_json_success();
}
/**
* Enable summary report email using AJAX.
*
* @since 3.0.0
*/
public function enable_summary_report_email_ajax() {
check_admin_referer( 'wp_mail_smtp_' . static::SLUG . '_nonce' );
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error();
}
$options = Options::init();
$data = [
'general' => [
SummaryReportEmail::SETTINGS_SLUG => false,
],
];
$options->set( $data, false, false );
wp_send_json_success();
}
/**
* Load widget content.
*
* @since 2.9.0
*/
public function widget_content() {
echo '<div class="wp-mail-smtp-dash-widget wp-mail-smtp-dash-widget--lite">';
$this->widget_content_html();
echo '</div>';
}
/**
* Increment the number of total emails sent by 1.
*
* @deprecated 3.0.0
*
* @since 2.9.0
*/
public function increment_sent_email_counter() {
_deprecated_function( __METHOD__, '3.0.0' );
}
/**
* Widget content HTML.
*
* @since 2.9.0
*/
private function widget_content_html() {
$hide_graph = (bool) $this->widget_meta( 'get', 'hide_graph' );
?>
<?php if ( ! $hide_graph ) : ?>
<div class="wp-mail-smtp-dash-widget-chart-block-container">
<div class="wp-mail-smtp-dash-widget-block wp-mail-smtp-dash-widget-chart-block">
<canvas id="wp-mail-smtp-dash-widget-chart" width="554" height="291"></canvas>
<div class="wp-mail-smtp-dash-widget-chart-upgrade">
<div class="wp-mail-smtp-dash-widget-modal">
<a href="#" class="wp-mail-smtp-dash-widget-dismiss-chart-upgrade">
<span class="dashicons dashicons-no-alt"></span>
</a>
<h2><?php esc_html_e( 'View Detailed Email Stats', 'wp-mail-smtp' ); ?></h2>
<p><?php esc_html_e( 'Automatically keep track of every email sent from your WordPress site and view valuable statistics right here in your dashboard.', 'wp-mail-smtp' ); ?></p>
<p>
<a href="<?php echo esc_url( wp_mail_smtp()->get_upgrade_link( [ 'medium' => 'dashboard-widget', 'content' => 'upgrade-to-wp-mail-smtp-pro' ] ) ); // phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound ?>" target="_blank" rel="noopener noreferrer" class="button button-primary button-hero">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</p>
</div>
</div>
<div class="wp-mail-smtp-dash-widget-overlay"></div>
</div>
</div>
<?php endif; ?>
<div class="wp-mail-smtp-dash-widget-block wp-mail-smtp-dash-widget-block-settings">
<div>
<?php $this->email_types_select_html(); ?>
</div>
<div>
<?php
$this->timespan_select_html();
$this->widget_settings_html();
?>
</div>
</div>
<div id="wp-mail-smtp-dash-widget-email-stats-block" class="wp-mail-smtp-dash-widget-block wp-mail-smtp-dash-widget-email-stats-block">
<?php $this->email_stats_block(); ?>
</div>
<?php
$this->display_after_email_stats_block_content();
}
/**
* Display the content after the email stats block.
*
* @since 3.9.0
*
* @return void
*/
private function display_after_email_stats_block_content() {
if ( empty( $this->widget_meta( 'get', 'hide_email_alerts_banner' ) ) ) {
// Check if we have error debug events.
$error_debug_events_count = DebugEvents::get_error_debug_events_count();
if ( ! is_wp_error( $error_debug_events_count ) && ! empty( $error_debug_events_count ) ) {
$this->show_email_alerts_banner( $error_debug_events_count );
return;
}
}
$hide_summary_report_email_block = (bool) $this->widget_meta( 'get', 'hide_summary_report_email_block' );
if ( SummaryReportEmail::is_disabled() && ! $hide_summary_report_email_block ) {
$this->show_summary_report_email_block();
}
$this->show_upgrade_footer();
}
/**
* Display the email alerts banner.
*
* @since 3.9.0
*
* @param int $error_count The number of debug events error.
*
* @return void
*/
private function show_email_alerts_banner( $error_count ) {
?>
<div id="wp-mail-smtp-dash-widget-email-alerts-education" class="wp-mail-smtp-dash-widget-block wp-mail-smtp-dash-widget-email-alerts-education">
<div class="wp-mail-smtp-dash-widget-email-alerts-education-error-icon">
<?php
printf(
'<img src="%s" alt="%s"/>',
esc_url( wp_mail_smtp()->assets_url . '/images/dash-widget/error-icon.svg' ),
esc_attr__( 'Error icon', 'wp-mail-smtp' )
);
?>
</div>
<div class="wp-mail-smtp-dash-widget-email-alerts-education-content">
<?php
$error_title = sprintf(
/* translators: %d - number of failed emails. */
_n(
'We detected %d failed email in the last 30 days.',
'We detected %d failed emails in the last 30 days.',
$error_count,
'wp-mail-smtp'
),
$error_count
);
$error_content = sprintf(
/* translators: %s - URL to WPMailSMTP.com. */
__( '<a href="%s" target="_blank" rel="noopener noreferrer">Upgrade to Pro</a> and get instant alert notifications when they fail.', 'wp-mail-smtp' ),
esc_url( wp_mail_smtp()->get_upgrade_link( [ 'medium' => 'dashboard-widget', 'content' => 'alerts-promo-upgrade-to-pro' ] ) ) // phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
);
?>
<p>
<strong><?php echo esc_html( $error_title ); ?></strong><br />
<?php
echo wp_kses(
$error_content,
[
'a' => [
'href' => [],
'target' => [],
'rel' => [],
],
]
);
?>
</p>
</div>
<button type="button" id="wp-mail-smtp-dash-widget-dismiss-email-alert-block" class="wp-mail-smtp-dash-widget-dismiss-email-alert-block" title="<?php esc_attr_e( 'Dismiss email alert block', 'wp-mail-smtp' ); ?>">
<span class="dashicons dashicons-no-alt"></span>
</button>
</div>
<?php
}
/**
* Show the summary report email block.
*
* @since 3.9.0
*
* @return void
*/
private function show_summary_report_email_block() {
?>
<div id="wp-mail-smtp-dash-widget-summary-report-email-block" class="wp-mail-smtp-dash-widget-block wp-mail-smtp-dash-widget-summary-report-email-block">
<div>
<div class="wp-mail-smtp-dash-widget-summary-report-email-block-setting">
<label for="wp-mail-smtp-dash-widget-summary-report-email-enable">
<input type="checkbox" id="wp-mail-smtp-dash-widget-summary-report-email-enable">
<i class="wp-mail-smtp-dash-widget-loader"></i>
<span>
<?php
echo wp_kses(
__( '<b>NEW!</b> Enable Weekly Email Summaries', 'wp-mail-smtp' ),
[
'b' => [],
]
);
?>
</span>
</label>
<a href="<?php echo esc_url( SummaryReportEmail::get_preview_link() ); ?>" target="_blank">
<?php esc_html_e( 'View Example', 'wp-mail-smtp' ); ?>
</a>
<i class="dashicons dashicons-dismiss wp-mail-smtp-dash-widget-summary-report-email-dismiss"></i>
</div>
<div class="wp-mail-smtp-dash-widget-summary-report-email-block-applied hidden">
<i class="wp-mail-smtp-dashicons-yes-alt-green"></i>
<span><?php esc_attr_e( 'Weekly Email Summaries have been enabled', 'wp-mail-smtp' ); ?></span>
</div>
</div>
</div>
<?php
}
/**
* Show the upgrade footer.
*
* @since 3.9.0
*
* @return void
*/
private function show_upgrade_footer() {
$hide_graph = (bool) $this->widget_meta( 'get', 'hide_graph' );
?>
<div id="wp-mail-smtp-dash-widget-upgrade-footer" class="wp-mail-smtp-dash-widget-block wp-mail-smtp-dash-widget-upgrade-footer wp-mail-smtp-dash-widget-upgrade-footer--<?php echo ! $hide_graph ? 'hide' : 'show'; ?>">
<p>
<?php
printf(
wp_kses( /* translators: %s - URL to WPMailSMTP.com. */
__( '<a href="%s" target="_blank" rel="noopener noreferrer">Upgrade to Pro</a> for detailed stats, email logs, and more!', 'wp-mail-smtp' ),
[
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
// phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
esc_url( wp_mail_smtp()->get_upgrade_link( [ 'medium' => 'dashboard-widget', 'content' => 'upgrade-to-pro' ] ) )
);
?>
</p>
</div>
<?php
}
/**
* Timespan select HTML.
*
* @since 2.9.0
*/
private function timespan_select_html() {
?>
<select id="wp-mail-smtp-dash-widget-timespan" class="wp-mail-smtp-dash-widget-select-timespan" title="<?php esc_attr_e( 'Select timespan', 'wp-mail-smtp' ); ?>">
<option value="all">
<?php esc_html_e( 'All Time', 'wp-mail-smtp' ); ?>
</option>
<?php foreach ( [ 7, 14, 30 ] as $option ) : ?>
<option value="<?php echo absint( $option ); ?>" disabled>
<?php /* translators: %d - Number of days. */ ?>
<?php echo esc_html( sprintf( _n( 'Last %d day', 'Last %d days', absint( $option ), 'wp-mail-smtp' ), absint( $option ) ) ); ?>
</option>
<?php endforeach; ?>
</select>
<?php
}
/**
* Email types select HTML.
*
* @since 2.9.0
*/
private function email_types_select_html() {
$options = [
'delivered' => esc_html__( 'Confirmed Emails', 'wp-mail-smtp' ),
'sent' => esc_html__( 'Unconfirmed Emails', 'wp-mail-smtp' ),
'unsent' => esc_html__( 'Failed Emails', 'wp-mail-smtp' ),
];
if ( Helpers::mailer_without_send_confirmation() ) {
unset( $options['sent'] );
$options['delivered'] = esc_html__( 'Sent Emails', 'wp-mail-smtp' );
}
?>
<select id="wp-mail-smtp-dash-widget-email-type" class="wp-mail-smtp-dash-widget-select-email-type" title="<?php esc_attr_e( 'Select email type', 'wp-mail-smtp' ); ?>">
<option value="all">
<?php esc_html_e( 'All Emails', 'wp-mail-smtp' ); ?>
</option>
<?php foreach ( $options as $key => $title ) : ?>
<option value="<?php echo sanitize_key( $key ); ?>" disabled>
<?php echo esc_html( $title ); ?>
</option>
<?php endforeach; ?>
</select>
<?php
}
/**
* Widget settings HTML.
*
* @since 2.9.0
*/
private function widget_settings_html() {
?>
<div class="wp-mail-smtp-dash-widget-settings-container">
<button id="wp-mail-smtp-dash-widget-settings-button" class="wp-mail-smtp-dash-widget-settings-button button" type="button">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 19 19">
<path d="M18,11l-2.18,0c-0.17,0.7 -0.44,1.35 -0.81,1.93l1.54,1.54l-2.1,2.1l-1.54,-1.54c-0.58,0.36 -1.23,0.63 -1.91,0.79l0,2.18l-3,0l0,-2.18c-0.68,-0.16 -1.33,-0.43 -1.91,-0.79l-1.54,1.54l-2.12,-2.12l1.54,-1.54c-0.36,-0.58 -0.63,-1.23 -0.79,-1.91l-2.18,0l0,-2.97l2.17,0c0.16,-0.7 0.44,-1.35 0.8,-1.94l-1.54,-1.54l2.1,-2.1l1.54,1.54c0.58,-0.37 1.24,-0.64 1.93,-0.81l0,-2.18l3,0l0,2.18c0.68,0.16 1.33,0.43 1.91,0.79l1.54,-1.54l2.12,2.12l-1.54,1.54c0.36,0.59 0.64,1.24 0.8,1.94l2.17,0l0,2.97Zm-8.5,1.5c1.66,0 3,-1.34 3,-3c0,-1.66 -1.34,-3 -3,-3c-1.66,0 -3,1.34 -3,3c0,1.66 1.34,3 3,3Z"></path>
</svg>
</button>
<div class="wp-mail-smtp-dash-widget-settings-menu">
<div class="wp-mail-smtp-dash-widget-settings-menu--style">
<h4><?php esc_html_e( 'Graph Style', 'wp-mail-smtp' ); ?></h4>
<div>
<div class="wp-mail-smtp-dash-widget-settings-menu-item">
<input type="radio" id="wp-mail-smtp-dash-widget-settings-style-bar" name="style" value="bar" disabled>
<label for="wp-mail-smtp-dash-widget-settings-style-bar"><?php esc_html_e( 'Bar', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-dash-widget-settings-menu-item">
<input type="radio" id="wp-mail-smtp-dash-widget-settings-style-line" name="style" value="line" checked disabled>
<label for="wp-mail-smtp-dash-widget-settings-style-line"><?php esc_html_e( 'Line', 'wp-mail-smtp' ); ?></label>
</div>
</div>
</div>
<div class="wp-mail-smtp-dash-widget-settings-menu--color">
<h4><?php esc_html_e( 'Color Scheme', 'wp-mail-smtp' ); ?></h4>
<div>
<div class="wp-mail-smtp-dash-widget-settings-menu-item">
<input type="radio" id="wp-mail-smtp-dash-widget-settings-color-smtp" name="color" value="smtp" disabled>
<label for="wp-mail-smtp-dash-widget-settings-color-smtp"><?php esc_html_e( 'WP Mail SMTP', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-dash-widget-settings-menu-item">
<input type="radio" id="wp-mail-smtp-dash-widget-settings-color-wp" name="color" value="wp" checked disabled>
<label for="wp-mail-smtp-dash-widget-settings-color-wp"><?php esc_html_e( 'WordPress', 'wp-mail-smtp' ); ?></label>
</div>
</div>
</div>
<button type="button" class="button wp-mail-smtp-dash-widget-settings-menu-save" disabled><?php esc_html_e( 'Save Changes', 'wp-mail-smtp' ); ?></button>
</div>
</div>
<?php
}
/**
* Email statistics block.
*
* @since 2.9.0
*/
private function email_stats_block() {
$output_data = $this->get_email_stats_data();
?>
<table id="wp-mail-smtp-dash-widget-email-stats-table" cellspacing="0">
<tr>
<?php
$count = 0;
$per_row = 2;
foreach ( array_values( $output_data ) as $stats ) :
if ( ! is_array( $stats ) ) {
continue;
}
if ( ! isset( $stats['icon'], $stats['title'] ) ) {
continue;
}
// Make some exceptions for mailers without send confirmation functionality.
if ( Helpers::mailer_without_send_confirmation() ) {
$per_row = 3;
}
// Create new row after every $per_row cells.
if ( $count !== 0 && $count % $per_row === 0 ) {
echo '</tr><tr>';
}
$count++;
?>
<td class="wp-mail-smtp-dash-widget-email-stats-table-cell wp-mail-smtp-dash-widget-email-stats-table-cell--<?php echo esc_attr( $stats['type'] ); ?> wp-mail-smtp-dash-widget-email-stats-table-cell--3">
<div class="wp-mail-smtp-dash-widget-email-stats-table-cell-container">
<img src="<?php echo esc_url( $stats['icon'] ); ?>" alt="<?php esc_attr_e( 'Table cell icon', 'wp-mail-smtp' ); ?>">
<span>
<?php echo esc_html( $stats['title'] ); ?>
</span>
</div>
</td>
<?php endforeach; ?>
</tr>
</table>
<?php
}
/**
* Prepare the email stats data.
* The text and counts of the email stats.
*
* @since 2.9.0
*
* @return array[]
*/
private function get_email_stats_data() {
$reports = new Reports();
$total_sent = $reports->get_total_emails_sent();
$output_data = [
'all' => [
'type' => 'all',
'icon' => wp_mail_smtp()->assets_url . '/images/dash-widget/wp/total.svg',
/* translators: %d number of total emails sent. */
'title' => esc_html( sprintf( esc_html__( '%d total', 'wp-mail-smtp' ), $total_sent ) ),
],
'delivered' => [
'type' => 'delivered',
'icon' => wp_mail_smtp()->assets_url . '/images/dash-widget/wp/delivered.svg',
/* translators: %s fixed string of 'N/A'. */
'title' => esc_html( sprintf( esc_html__( 'Confirmed %s', 'wp-mail-smtp' ), 'N/A' ) ),
],
'sent' => [
'type' => 'sent',
'icon' => wp_mail_smtp()->assets_url . '/images/dash-widget/wp/sent.svg',
/* translators: %s fixed string of 'N/A'. */
'title' => esc_html( sprintf( esc_html__( 'Unconfirmed %s', 'wp-mail-smtp' ), 'N/A' ) ),
],
'unsent' => [
'type' => 'unsent',
'icon' => wp_mail_smtp()->assets_url . '/images/dash-widget/wp/unsent.svg',
/* translators: %s fixed string of 'N/A'. */
'title' => esc_html( sprintf( esc_html__( 'Failed %s', 'wp-mail-smtp' ), 'N/A' ) ),
],
];
if ( Helpers::mailer_without_send_confirmation() ) {
// Skip the 'unconfirmed sent' section.
unset( $output_data['sent'] );
// Change the 'confirmed sent' section into a general 'sent' section.
$output_data['delivered']['title'] = esc_html( /* translators: %s fixed string of 'N/A'. */
sprintf( esc_html__( 'Sent %s', 'wp-mail-smtp' ), 'N/A' )
);
}
return $output_data;
}
/**
* Get/set a widget meta.
*
* @since 2.9.0
*
* @param string $action Possible value: 'get' or 'set'.
* @param string $meta Meta name.
* @param int $value Value to set.
*
* @return mixed
*/
protected function widget_meta( $action, $meta, $value = 0 ) {
$allowed_actions = [ 'get', 'set' ];
if ( ! in_array( $action, $allowed_actions, true ) ) {
return false;
}
if ( $action === 'get' ) {
return $this->get_widget_meta( $meta );
}
$meta_key = $this->get_widget_meta_key( $meta );
$value = sanitize_key( $value );
if ( 'set' === $action && ! empty( $value ) ) {
return update_user_meta( get_current_user_id(), $meta_key, $value );
}
if ( 'set' === $action && empty( $value ) ) {
return delete_user_meta( get_current_user_id(), $meta_key );
}
return false;
}
/**
* Get the widget meta value.
*
* @since 3.9.0
*
* @param string $meta Meta name.
*
* @return mixed
*/
private function get_widget_meta( $meta ) {
$defaults = [
'hide_graph' => 0,
'hide_summary_report_email_block' => 0,
'hide_email_alerts_banner' => 0,
];
$meta_value = get_user_meta( get_current_user_id(), $this->get_widget_meta_key( $meta ), true );
if ( ! empty( $meta_value ) ) {
return $meta_value;
}
if ( isset( $defaults[ $meta ] ) ) {
return $defaults[ $meta ];
}
return null;
}
/**
* Retrieve the meta key.
*
* @since 3.9.0
*
* @param string $meta Meta name.
*
* @return string
*/
private function get_widget_meta_key( $meta ) {
return 'wp_mail_smtp_' . static::SLUG . '_' . $meta;
}
}

View File

@@ -0,0 +1,422 @@
<?php
namespace WPMailSMTP\Admin\DebugEvents;
use WP_Error;
use WPMailSMTP\Admin\Area;
use WPMailSMTP\Options;
use WPMailSMTP\Tasks\DebugEventsCleanupTask;
use WPMailSMTP\WP;
/**
* Debug Events class.
*
* @since 3.0.0
*/
class DebugEvents {
/**
* Transient name for the error debug events.
*
* @since 3.9.0
*
* @var string
*/
const ERROR_DEBUG_EVENTS_TRANSIENT = 'wp_mail_smtp_error_debug_events_transient';
/**
* Register hooks.
*
* @since 3.0.0
*/
public function hooks() {
// Process AJAX requests.
add_action( 'wp_ajax_wp_mail_smtp_debug_event_preview', [ $this, 'process_ajax_debug_event_preview' ] );
add_action( 'wp_ajax_wp_mail_smtp_delete_all_debug_events', [ $this, 'process_ajax_delete_all_debug_events' ] );
// Initialize screen options for the Debug Events page.
add_action( 'load-wp-mail-smtp_page_wp-mail-smtp-tools', [ $this, 'screen_options' ] );
add_filter( 'set-screen-option', [ $this, 'set_screen_options' ], 10, 3 );
add_filter( 'set_screen_option_wp_mail_smtp_debug_events_per_page', [ $this, 'set_screen_options' ], 10, 3 );
// Cancel previous debug events cleanup task if retention period option was changed.
add_filter( 'wp_mail_smtp_options_set', [ $this, 'maybe_cancel_debug_events_cleanup_task' ] );
// Detect debug events log retention period constant change.
if ( Options::init()->is_const_defined( 'debug_events', 'retention_period' ) ) {
add_action( 'admin_init', [ $this, 'detect_debug_events_retention_period_constant_change' ] );
}
}
/**
* Detect debug events retention period constant change.
*
* @since 3.6.0
*/
public function detect_debug_events_retention_period_constant_change() {
if ( ! WP::in_wp_admin() ) {
return;
}
if ( Options::init()->is_const_changed( 'debug_events', 'retention_period' ) ) {
( new DebugEventsCleanupTask() )->cancel();
}
}
/**
* Cancel previous debug events cleanup task if retention period option was changed.
*
* @since 3.6.0
*
* @param array $options Currently processed options passed to a filter hook.
*
* @return array
*/
public function maybe_cancel_debug_events_cleanup_task( $options ) {
if ( isset( $options['debug_events']['retention_period'] ) ) {
// If this option has changed, cancel the recurring cleanup task and init again.
if ( Options::init()->is_option_changed( $options['debug_events']['retention_period'], 'debug_events', 'retention_period' ) ) {
( new DebugEventsCleanupTask() )->cancel();
}
}
return $options;
}
/**
* Process AJAX request for deleting all debug event entries.
*
* @since 3.0.0
*/
public function process_ajax_delete_all_debug_events() {
if (
empty( $_POST['nonce'] ) ||
! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'wp_mail_smtp_debug_events' )
) {
wp_send_json_error( esc_html__( 'Access rejected.', 'wp-mail-smtp' ) );
}
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error( esc_html__( 'You don\'t have the capability to perform this action.', 'wp-mail-smtp' ) );
}
global $wpdb;
$table = self::get_table_name();
$sql = "TRUNCATE TABLE `$table`;";
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$result = $wpdb->query( $sql );
if ( $result !== false ) {
wp_send_json_success( esc_html__( 'All debug event entries were deleted successfully.', 'wp-mail-smtp' ) );
}
wp_send_json_error(
sprintf( /* translators: %s - WPDB error message. */
esc_html__( 'There was an issue while trying to delete all debug event entries. Error message: %s', 'wp-mail-smtp' ),
$wpdb->last_error
)
);
}
/**
* Process AJAX request for debug event preview.
*
* @since 3.0.0
*/
public function process_ajax_debug_event_preview() {
if (
empty( $_POST['nonce'] ) ||
! wp_verify_nonce( sanitize_key( $_POST['nonce'] ), 'wp_mail_smtp_debug_events' )
) {
wp_send_json_error( esc_html__( 'Access rejected.', 'wp-mail-smtp' ) );
}
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error( esc_html__( 'You don\'t have the capability to perform this action.', 'wp-mail-smtp' ) );
}
$event_id = isset( $_POST['id'] ) ? intval( $_POST['id'] ) : false;
if ( empty( $event_id ) ) {
wp_send_json_error( esc_html__( 'No Debug Event ID provided!', 'wp-mail-smtp' ) );
}
$event = new Event( $event_id );
wp_send_json_success(
[
'title' => $event->get_title(),
'content' => $event->get_details_html(),
]
);
}
/**
* Add the debug event to the DB.
*
* @since 3.0.0
*
* @param string $message The event's message.
* @param int $type The event's type.
*
* @return bool|int
*/
public static function add( $message = '', $type = 0 ) {
if ( ! in_array( $type, array_keys( Event::get_types() ), true ) ) {
return false;
}
if ( $type === Event::TYPE_DEBUG && ! self::is_debug_enabled() ) {
return false;
}
try {
$event = new Event();
$event->set_type( $type );
$event->set_content( $message );
$event->set_initiator();
return $event->save()->get_id();
} catch ( \Exception $exception ) {
return false;
}
}
/**
* Save the debug message.
*
* @since 3.0.0
* @since 3.5.0 Returns Event ID.
*
* @param string $message The debug message.
*
* @return bool|int
*/
public static function add_debug( $message = '' ) {
return self::add( $message, Event::TYPE_DEBUG );
}
/**
* Get the debug message from the provided debug event IDs.
*
* @since 3.0.0
*
* @param array|string|int $ids A single or a list of debug event IDs.
*
* @return array
*/
public static function get_debug_messages( $ids ) {
global $wpdb;
if ( empty( $ids ) ) {
return [];
}
if ( ! self::is_valid_db() ) {
return [];
}
// Convert to a string.
if ( is_array( $ids ) ) {
$ids = implode( ',', $ids );
}
$ids = explode( ',', (string) $ids );
$ids = array_map( 'intval', $ids );
$placeholders = implode( ', ', array_fill( 0, count( $ids ), '%d' ) );
$table = self::get_table_name();
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQLPlaceholders.UnfinishedPrepare
$events_data = $wpdb->get_results(
$wpdb->prepare( "SELECT id, content, initiator, event_type, created_at FROM {$table} WHERE id IN ( {$placeholders} )", $ids )
);
// phpcs:enable
if ( empty( $events_data ) ) {
return [];
}
return array_map(
function ( $event_item ) {
$event = new Event( $event_item );
return $event->get_short_details();
},
$events_data
);
}
/**
* Returns the number of error debug events in a given time span.
*
* By default it returns the number of error debug events in the last 30 days.
*
* @since 3.9.0
*
* @param string $span_of_time The time span to count the events for. Default '-30 days'.
*
* @return int|WP_Error The number of error debug events or WP_Error on failure.
*/
public static function get_error_debug_events_count( $span_of_time = '-30 days' ) {
$timestamp = strtotime( $span_of_time );
if ( ! $timestamp || $timestamp > time() ) {
return new WP_Error( 'wp_mail_smtp_admin_debug_events_get_error_debug_events_count_invalid_time', 'Invalid time span.' );
}
$transient_key = self::ERROR_DEBUG_EVENTS_TRANSIENT . '_' . sanitize_title_with_dashes( $span_of_time );
$cached_error_events_count = get_transient( $transient_key );
if ( $cached_error_events_count !== false ) {
return (int) $cached_error_events_count;
}
global $wpdb;
// phpcs:disable WordPress.DB.PreparedSQLPlaceholders.UnquotedComplexPlaceholder
$sql = $wpdb->prepare(
'SELECT COUNT(*) FROM `%1$s` WHERE event_type = %2$d AND created_at >= "%3$s"',
self::get_table_name(),
Event::TYPE_ERROR,
gmdate( WP::datetime_mysql_format(), $timestamp )
);
// phpcs:enable WordPress.DB.PreparedSQLPlaceholders.UnquotedComplexPlaceholder
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
$error_events_count = (int) $wpdb->get_var( $sql );
set_transient( $transient_key, $error_events_count, HOUR_IN_SECONDS );
return $error_events_count;
}
/**
* Register the screen options for the debug events page.
*
* @since 3.0.0
*/
public function screen_options() {
$screen = get_current_screen();
if (
! is_object( $screen ) ||
strpos( $screen->id, 'wp-mail-smtp_page_wp-mail-smtp-tools' ) === false ||
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
! isset( $_GET['tab'] ) || $_GET['tab'] !== 'debug-events'
) {
return;
}
add_screen_option(
'per_page',
[
'label' => esc_html__( 'Number of events per page:', 'wp-mail-smtp' ),
'option' => 'wp_mail_smtp_debug_events_per_page',
'default' => EventsCollection::PER_PAGE,
]
);
}
/**
* Set the screen options for the debug events page.
*
* @since 3.0.0
*
* @param bool $keep Whether to save or skip saving the screen option value.
* @param string $option The option name.
* @param int $value The number of items to use.
*
* @return bool|int
*/
public function set_screen_options( $keep, $option, $value ) {
if ( 'wp_mail_smtp_debug_events_per_page' === $option ) {
return (int) $value;
}
return $keep;
}
/**
* Whether the email debug for debug events is enabled or not.
*
* @since 3.0.0
*
* @return bool
*/
public static function is_debug_enabled() {
return (bool) Options::init()->get( 'debug_events', 'email_debug' );
}
/**
* Get the debug events page URL.
*
* @since 3.0.0
*
* @return string
*/
public static function get_page_url() {
return add_query_arg(
[
'tab' => 'debug-events',
],
wp_mail_smtp()->get_admin()->get_admin_page_url( Area::SLUG . '-tools' )
);
}
/**
* Get the DB table name.
*
* @since 3.0.0
*
* @return string Table name, prefixed.
*/
public static function get_table_name() {
global $wpdb;
return $wpdb->prefix . 'wpmailsmtp_debug_events';
}
/**
* Whether the DB table exists.
*
* @since 3.0.0
*
* @return bool
*/
public static function is_valid_db() {
global $wpdb;
static $is_valid = null;
// Return cached value only if table already exists.
if ( $is_valid === true ) {
return true;
}
$table = self::get_table_name();
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
$is_valid = (bool) $wpdb->get_var( $wpdb->prepare( 'SHOW TABLES LIKE %s;', $table ) );
return $is_valid;
}
}

View File

@@ -0,0 +1,597 @@
<?php
namespace WPMailSMTP\Admin\DebugEvents;
use WPMailSMTP\WP;
/**
* Debug Event class.
*
* @since 3.0.0
*/
class Event {
/**
* This is an error event.
*
* @since 3.0.0
*/
const TYPE_ERROR = 0;
/**
* This is a debug event.
*
* @since 3.0.0
*/
const TYPE_DEBUG = 1;
/**
* The event's ID.
*
* @since 3.0.0
*
* @var int
*/
protected $id = 0;
/**
* The event's content.
*
* @since 3.0.0
*
* @var string
*/
protected $content = '';
/**
* The event's initiator - who called the `wp_mail` function?
* JSON encoded string.
*
* @since 3.0.0
*
* @var string
*/
protected $initiator = '';
/**
* The event's type.
*
* @since 3.0.0
*
* @var int
*/
protected $event_type = 0;
/**
* The date and time when this event was created.
*
* @since 3.0.0
*
* @var \DateTime
*/
protected $created_at;
/**
* Retrieve a particular event when constructing the object.
*
* @since 3.0.0
*
* @param int|object $id_or_row The event ID or object with event attributes.
*/
public function __construct( $id_or_row = null ) {
$this->populate_event( $id_or_row );
}
/**
* Get and prepare the event data.
*
* @since 3.0.0
*
* @param int|object $id_or_row The event ID or object with event attributes.
*/
private function populate_event( $id_or_row ) {
$event = null;
if ( is_numeric( $id_or_row ) ) {
// Get by ID.
$collection = new EventsCollection( [ 'id' => (int) $id_or_row ] );
$events = $collection->get();
if ( $events->valid() ) {
$event = $events->current();
}
} elseif (
is_object( $id_or_row ) &&
isset(
$id_or_row->id,
$id_or_row->content,
$id_or_row->initiator,
$id_or_row->event_type,
$id_or_row->created_at
)
) {
$event = $id_or_row;
}
if ( $event !== null ) {
foreach ( get_object_vars( $event ) as $key => $value ) {
$this->{$key} = $value;
}
}
}
/**
* Event ID as per our DB table.
*
* @since 3.0.0
*
* @return int
*/
public function get_id() {
return (int) $this->id;
}
/**
* Get the event title.
*
* @since 3.0.0
*
* @return string
*/
public function get_title() {
/* translators: %d the event ID. */
return sprintf( esc_html__( 'Event #%d', 'wp-mail-smtp' ), $this->get_id() );
}
/**
* Get the content of the event.
*
* @since 3.0.0
*
* @return string
*/
public function get_content() {
return $this->content;
}
/**
* Get the event's type.
*
* @since 3.0.0
*
* @return int
*/
public function get_type() {
return (int) $this->event_type;
}
/**
* Get the list of all event types.
*
* @since 3.0.0
*
* @return array
*/
public static function get_types() {
return [
self::TYPE_ERROR => esc_html__( 'Error', 'wp-mail-smtp' ),
self::TYPE_DEBUG => esc_html__( 'Debug', 'wp-mail-smtp' ),
];
}
/**
* Get human readable type name.
*
* @since 3.0.0
*
* @return string
*/
public function get_type_name() {
$types = self::get_types();
return isset( $types[ $this->get_type() ] ) ? $types[ $this->get_type() ] : '';
}
/**
* Get the date/time when this event was created.
*
* @since 3.0.0
*
* @throws \Exception Emits exception on incorrect date.
*
* @return \DateTime
*/
public function get_created_at() {
$timezone = new \DateTimeZone( 'UTC' );
$date = false;
if ( ! empty( $this->created_at ) ) {
$date = \DateTime::createFromFormat( WP::datetime_mysql_format(), $this->created_at, $timezone );
}
if ( $date === false ) {
$date = new \DateTime( 'now', $timezone );
}
return $date;
}
/**
* Get the date/time when this event was created in a nicely formatted string.
*
* @since 3.0.0
*
* @return string
*/
public function get_created_at_formatted() {
try {
$date = $this->get_created_at();
} catch ( \Exception $e ) {
$date = null;
}
if ( empty( $date ) ) {
return esc_html__( 'N/A', 'wp-mail-smtp' );
}
return esc_html(
date_i18n(
WP::datetime_format(),
strtotime( get_date_from_gmt( $date->format( WP::datetime_mysql_format() ) ) )
)
);
}
/**
* Get the event's initiator raw data.
* Who called the `wp_mail` function?
*
* @since 3.0.0
*
* @return array
*/
public function get_initiator_raw() {
return json_decode( $this->initiator, true );
}
/**
* Get the event's initiator name.
* Which plugin/theme (or WP core) called the `wp_mail` function?
*
* @since 3.0.0
*
* @return string
*/
public function get_initiator() {
$initiator = (array) $this->get_initiator_raw();
if ( empty( $initiator['file'] ) ) {
return '';
}
return WP::get_initiator_name( $initiator['file'] );
}
/**
* Get the event's initiator file path.
*
* @since 3.0.0
*
* @return string
*/
public function get_initiator_file_path() {
$initiator = (array) $this->get_initiator_raw();
if ( empty( $initiator['file'] ) ) {
return '';
}
return $initiator['file'];
}
/**
* Get the event's initiator file line.
*
* @since 3.0.0
*
* @return string
*/
public function get_initiator_file_line() {
$initiator = (array) $this->get_initiator_raw();
if ( empty( $initiator['line'] ) ) {
return '';
}
return $initiator['line'];
}
/**
* Get the event's initiator backtrace.
*
* @since 3.6.0
*
* @return array
*/
private function get_initiator_backtrace() {
$initiator = (array) $this->get_initiator_raw();
if ( empty( $initiator['backtrace'] ) ) {
return [];
}
return $initiator['backtrace'];
}
/**
* Get the event preview HTML.
*
* @since 3.0.0
*
* @return string
*/
public function get_details_html() {
$initiator = $this->get_initiator();
$initiator_backtrace = $this->get_initiator_backtrace();
ob_start();
?>
<div class="wp-mail-smtp-debug-event-preview">
<div class="wp-mail-smtp-debug-event-preview-subtitle">
<span><?php esc_html_e( 'Debug Event Details', 'wp-mail-smtp' ); ?></span>
</div>
<div class="wp-mail-smtp-debug-event-row wp-mail-smtp-debug-event-preview-type">
<span class="debug-event-label"><?php esc_html_e( 'Type', 'wp-mail-smtp' ); ?></span>
<span class="debug-event-value"><?php echo esc_html( $this->get_type_name() ); ?></span>
</div>
<div class="wp-mail-smtp-debug-event-row wp-mail-smtp-debug-event-preview-date">
<span class="debug-event-label"><?php esc_html_e( 'Date', 'wp-mail-smtp' ); ?></span>
<span class="debug-event-value"><?php echo esc_html( $this->get_created_at_formatted() ); ?></span>
</div>
<div class="wp-mail-smtp-debug-event-row wp-mail-smtp-debug-event-preview-content">
<span class="debug-event-label"><?php esc_html_e( 'Content', 'wp-mail-smtp' ); ?></span>
<div class="debug-event-value">
<?php echo wp_kses( str_replace( [ "\r\n", "\r", "\n" ], '<br>', $this->get_content() ), [ 'br' => [] ] ); ?>
</div>
</div>
<?php if ( ! empty( $initiator ) ) : ?>
<div class="wp-mail-smtp-debug-event-row wp-mail-smtp-debug-event-preview-caller">
<span class="debug-event-label"><?php esc_html_e( 'Source', 'wp-mail-smtp' ); ?></span>
<div class="debug-event-value">
<span class="debug-event-initiator"><?php echo esc_html( $initiator ); ?></span>
<p class="debug-event-code">
<?php
printf( /* Translators: %1$s the path of a file, %2$s the line number in the file. */
esc_html__( '%1$s (line: %2$s)', 'wp-mail-smtp' ),
esc_html( $this->get_initiator_file_path() ),
esc_html( $this->get_initiator_file_line() )
);
?>
<?php if ( ! empty( $initiator_backtrace ) ) : ?>
<br><br>
<b><?php esc_html_e( 'Backtrace:', 'wp-mail-smtp' ); ?></b>
<br>
<?php
foreach ( $initiator_backtrace as $i => $item ) {
printf(
/* translators: %1$d - index number; %2$s - function name; %3$s - file path; %4$s - line number. */
esc_html__( '[%1$d] %2$s called at [%3$s:%4$s]', 'wp-mail-smtp' ),
$i,
isset( $item['class'] ) ? esc_html( $item['class'] . $item['type'] . $item['function'] ) : esc_html( $item['function'] ),
isset( $item['file'] ) ? esc_html( $item['file'] ) : '', // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
isset( $item['line'] ) ? esc_html( $item['line'] ) : '' // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
);
echo '<br>';
}
?>
<?php endif; ?>
</p>
</div>
</div>
<?php endif; ?>
</div>
<?php
return ob_get_clean();
}
/**
* Get the short details about this event (event content and the initiator's name).
*
* @since 3.0.0
*
* @return string
*/
public function get_short_details() {
$result = [];
if ( ! empty( $this->get_initiator() ) ) {
$result[] = sprintf(
/* Translators: %s - Email initiator/source name. */
esc_html__( 'Email Source: %s', 'wp-mail-smtp' ),
esc_html( $this->get_initiator() )
);
}
$result[] = esc_html( $this->get_content() );
return implode( WP::EOL, $result );
}
/**
* Save a new or modified event in DB.
*
* @since 3.0.0
*
* @throws \Exception When event init fails.
*
* @return Event New or updated event class instance.
*/
public function save() {
global $wpdb;
$table = DebugEvents::get_table_name();
if ( (bool) $this->get_id() ) {
// Update the existing DB table record.
$wpdb->update( // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching
$table,
[
'content' => $this->content,
'initiator' => $this->initiator,
'event_type' => $this->event_type,
'created_at' => $this->get_created_at()->format( WP::datetime_mysql_format() ),
],
[
'id' => $this->get_id(),
],
[
'%s', // content.
'%s', // initiator.
'%s', // type.
'%s', // created_at.
],
[
'%d',
]
);
$event_id = $this->get_id();
} else {
// Create a new DB table record.
$wpdb->insert(
$table,
[
'content' => $this->content,
'initiator' => $this->initiator,
'event_type' => $this->event_type,
'created_at' => $this->get_created_at()->format( WP::datetime_mysql_format() ),
],
[
'%s', // content.
'%s', // initiator.
'%s', // type.
'%s', // created_at.
]
);
$event_id = $wpdb->insert_id;
}
try {
$event = new Event( $event_id );
} catch ( \Exception $e ) {
$event = new Event();
}
return $event;
}
/**
* Set the content of this event.
*
* @since 3.0.0
*
* @param string|array $content The event's content.
*/
public function set_content( $content ) {
if ( ! is_string( $content ) ) {
$this->content = wp_json_encode( $content );
} else {
$this->content = wp_strip_all_tags( str_replace( '<br>', "\r\n", $content ), false );
}
}
/**
* Set the initiator by checking the backtrace for the wp_mail function call.
*
* @since 3.0.0
*/
public function set_initiator() {
$initiator = wp_mail_smtp()->get_wp_mail_initiator();
if ( empty( $initiator->get_file() ) ) {
return;
}
$data['file'] = $initiator->get_file();
if ( ! empty( $initiator->get_line() ) ) {
$data['line'] = $initiator->get_line();
}
if ( DebugEvents::is_debug_enabled() ) {
$data['backtrace'] = $initiator->get_backtrace();
}
$this->initiator = wp_json_encode( $data );
}
/**
* Set the type of this event.
*
* @since 3.0.0
*
* @param int $type The event's type.
*/
public function set_type( $type ) {
$this->event_type = (int) $type;
}
/**
* Whether the event instance is a valid entity to work with.
*
* @since 3.0.0
*/
public function is_valid() {
return ! ( empty( $this->id ) || empty( $this->created_at ) );
}
/**
* Whether this is an error event.
*
* @since 3.0.0
*
* @return bool
*/
public function is_error() {
return self::TYPE_ERROR === $this->get_type();
}
/**
* Whether this is a debug event.
*
* @since 3.0.0
*
* @return bool
*/
public function is_debug() {
return self::TYPE_DEBUG === $this->get_type();
}
}

View File

@@ -0,0 +1,421 @@
<?php
namespace WPMailSMTP\Admin\DebugEvents;
use WPMailSMTP\WP;
/**
* Debug Events Collection.
*
* @since 3.0.0
*/
class EventsCollection implements \Countable, \Iterator {
/**
* Default number of log entries per page.
*
* @since 3.0.0
*
* @var int
*/
const PER_PAGE = 10;
/**
* Number of log entries per page.
*
* @since 3.0.0
*
* @var int
*/
public static $per_page;
/**
* List of all Event instances.
*
* @since 3.0.0
*
* @var array
*/
private $list = [];
/**
* List of current collection instance parameters.
*
* @since 3.0.0
*
* @var array
*/
private $params;
/**
* Used for \Iterator when iterating through Queue in loops.
*
* @since 3.0.0
*
* @var int
*/
private $iterator_position = 0;
/**
* Collection constructor.
* $events = new EventsCollection( [ 'type' => 0 ] );
*
* @since 3.0.0
*
* @param array $params The events collection parameters.
*/
public function __construct( array $params = [] ) {
$this->set_per_page();
$this->params = $this->process_params( $params );
}
/**
* Set the per page attribute to the screen options value.
*
* @since 3.0.0
*/
protected function set_per_page() {
$per_page = (int) get_user_meta(
get_current_user_id(),
'wp_mail_smtp_debug_events_per_page',
true
);
if ( $per_page < 1 ) {
$per_page = self::PER_PAGE;
}
self::$per_page = $per_page;
}
/**
* Verify, sanitize, and populate with default values
* all the passed parameters, which participate in DB queries.
*
* @since 3.0.0
*
* @param array $params The events collection parameters.
*
* @return array
*/
public function process_params( $params ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
$params = (array) $params;
$processed = [];
/*
* WHERE.
*/
// Single ID.
if ( ! empty( $params['id'] ) ) {
$processed['id'] = (int) $params['id'];
}
// Multiple IDs.
if (
! empty( $params['ids'] ) &&
is_array( $params['ids'] )
) {
$processed['ids'] = array_unique( array_filter( array_map( 'intval', array_values( $params['ids'] ) ) ) );
}
// Type.
if (
isset( $params['type'] ) &&
in_array( $params['type'], array_keys( Event::get_types() ), true )
) {
$processed['type'] = (int) $params['type'];
}
// Search.
if ( ! empty( $params['search'] ) ) {
$processed['search'] = sanitize_text_field( $params['search'] );
}
/*
* LIMIT.
*/
if ( ! empty( $params['offset'] ) ) {
$processed['offset'] = (int) $params['offset'];
}
if ( ! empty( $params['per_page'] ) ) {
$processed['per_page'] = (int) $params['per_page'];
}
/*
* Sent date.
*/
if ( ! empty( $params['date'] ) ) {
if ( is_string( $params['date'] ) ) {
$params['date'] = array_fill( 0, 2, $params['date'] );
} elseif ( is_array( $params['date'] ) && count( $params['date'] ) === 1 ) {
$params['date'] = array_fill( 0, 2, $params['date'][0] );
}
// We pass array and treat it as a range from:to.
if ( is_array( $params['date'] ) && count( $params['date'] ) === 2 ) {
$date_start = WP::get_day_period_date( 'start_of_day', strtotime( $params['date'][0] ), 'Y-m-d H:i:s', true );
$date_end = WP::get_day_period_date( 'end_of_day', strtotime( $params['date'][1] ), 'Y-m-d H:i:s', true );
if ( ! empty( $date_start ) && ! empty( $date_end ) ) {
$processed['date'] = [ $date_start, $date_end ];
}
}
}
// Merge missing values with defaults.
return wp_parse_args(
$processed,
$this->get_default_params()
);
}
/**
* Get the list of default params for a usual query.
*
* @since 3.0.0
*
* @return array
*/
protected function get_default_params() {
return [
'offset' => 0,
'per_page' => self::$per_page,
'order' => 'DESC',
'orderby' => 'id',
'search' => '',
];
}
/**
* Get the SQL-ready string of WHERE part for a query.
*
* @since 3.0.0
*
* @return string
*/
private function build_where() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
global $wpdb;
$where = [ '1=1' ];
// Shortcut single ID or multiple IDs.
if ( ! empty( $this->params['id'] ) || ! empty( $this->params['ids'] ) ) {
if ( ! empty( $this->params['id'] ) ) {
$where[] = $wpdb->prepare( 'id = %d', $this->params['id'] );
} elseif ( ! empty( $this->params['ids'] ) ) {
$where[] = 'id IN (' . implode( ',', $this->params['ids'] ) . ')';
}
// When some ID(s) defined - we should ignore all other possible filtering options.
return implode( ' AND ', $where );
}
// Type.
if ( isset( $this->params['type'] ) ) {
$where[] = $wpdb->prepare( 'event_type = %d', $this->params['type'] );
}
// Search.
if ( ! empty( $this->params['search'] ) ) {
$where[] = '(' .
$wpdb->prepare(
'content LIKE %s',
'%' . $wpdb->esc_like( $this->params['search'] ) . '%'
)
. ' OR ' .
$wpdb->prepare(
'initiator LIKE %s',
'%' . $wpdb->esc_like( $this->params['search'] ) . '%'
)
. ')';
}
// Sent date.
if (
! empty( $this->params['date'] ) &&
is_array( $this->params['date'] ) &&
count( $this->params['date'] ) === 2
) {
$where[] = $wpdb->prepare(
'( created_at >= %s AND created_at <= %s )',
$this->params['date'][0],
$this->params['date'][1]
);
}
return implode( ' AND ', $where );
}
/**
* Get the SQL-ready string of ORDER part for a query.
* Order is always in the params, as per our defaults.
*
* @since 3.0.0
*
* @return string
*/
private function build_order() {
return 'ORDER BY ' . $this->params['orderby'] . ' ' . $this->params['order'];
}
/**
* Get the SQL-ready string of LIMIT part for a query.
* Limit is always in the params, as per our defaults.
*
* @since 3.0.0
*
* @return string
*/
private function build_limit() {
return 'LIMIT ' . $this->params['offset'] . ', ' . $this->params['per_page'];
}
/**
* Count the number of DB records according to filters.
* Do not retrieve actual records.
*
* @since 3.0.0
*
* @return int
*/
public function get_count() {
$table = DebugEvents::get_table_name();
$where = $this->build_where();
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
return (int) WP::wpdb()->get_var(
"SELECT COUNT(id) FROM $table
WHERE {$where}"
);
// phpcs:enable
}
/**
* Get the list of DB records.
* You can either use array returned there OR iterate over the whole object,
* as it implements Iterator interface.
*
* @since 3.0.0
*
* @return EventsCollection
*/
public function get() {
$table = DebugEvents::get_table_name();
$where = $this->build_where();
$limit = $this->build_limit();
$order = $this->build_order();
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared
$data = WP::wpdb()->get_results(
"SELECT * FROM $table
WHERE {$where}
{$order}
{$limit}"
);
// phpcs:enable
if ( ! empty( $data ) ) {
// As we got raw data we need to convert each row to Event.
foreach ( $data as $row ) {
$this->list[] = new Event( $row );
}
}
return $this;
}
/*********************************************************************************************
* ****************************** \Counter interface method. *********************************
*********************************************************************************************/
/**
* Count number of Record in a Queue.
*
* @since 3.0.0
*
* @return int
*/
#[\ReturnTypeWillChange]
public function count() {
return count( $this->list );
}
/*********************************************************************************************
* ****************************** \Iterator interface methods. *******************************
*********************************************************************************************/
/**
* Rewind the Iterator to the first element.
*
* @since 3.0.0
*/
#[\ReturnTypeWillChange]
public function rewind() {
$this->iterator_position = 0;
}
/**
* Return the current element.
*
* @since 3.0.0
*
* @return Event|null Return null when no items in collection.
*/
#[\ReturnTypeWillChange]
public function current() {
return $this->valid() ? $this->list[ $this->iterator_position ] : null;
}
/**
* Return the key of the current element.
*
* @since 3.0.0
*
* @return int
*/
#[\ReturnTypeWillChange]
public function key() {
return $this->iterator_position;
}
/**
* Move forward to next element.
*
* @since 3.0.0
*/
#[\ReturnTypeWillChange]
public function next() {
++ $this->iterator_position;
}
/**
* Checks if current position is valid.
*
* @since 3.0.0
*
* @return bool
*/
#[\ReturnTypeWillChange]
public function valid() {
return isset( $this->list[ $this->iterator_position ] );
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace WPMailSMTP\Admin\DebugEvents;
use WPMailSMTP\MigrationAbstract;
/**
* Debug Events Migration Class
*
* @since 3.0.0
*/
class Migration extends MigrationAbstract {
/**
* Version of the debug events database table.
*
* @since 3.0.0
*/
const DB_VERSION = 1;
/**
* Option key where we save the current debug events DB version.
*
* @since 3.0.0
*/
const OPTION_NAME = 'wp_mail_smtp_debug_events_db_version';
/**
* Option key where we save any errors while creating the debug events DB table.
*
* @since 3.0.0
*/
const ERROR_OPTION_NAME = 'wp_mail_smtp_debug_events_db_error';
/**
* Create the debug events DB table structure.
*
* @since 3.0.0
*/
protected function migrate_to_1() {
global $wpdb;
$table = DebugEvents::get_table_name();
$charset_collate = $wpdb->get_charset_collate();
$sql = "CREATE TABLE IF NOT EXISTS `$table` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`content` TEXT DEFAULT NULL,
`initiator` TEXT DEFAULT NULL,
`event_type` TINYINT UNSIGNED NOT NULL DEFAULT '0',
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
PRIMARY KEY (id)
)
ENGINE='InnoDB'
{$charset_collate};";
$result = $wpdb->query( $sql ); // phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
if ( ! empty( $wpdb->last_error ) ) {
update_option( self::ERROR_OPTION_NAME, $wpdb->last_error, false );
}
// Save the current version to DB.
if ( $result !== false ) {
$this->update_db_ver( 1 );
}
}
}

View File

@@ -0,0 +1,582 @@
<?php
namespace WPMailSMTP\Admin\DebugEvents;
use WPMailSMTP\Helpers\Helpers;
if ( ! class_exists( 'WP_List_Table', false ) ) {
require_once ABSPATH . 'wp-admin/includes/class-wp-list-table.php';
}
/**
* Class Table that displays the list of debug events.
*
* @since 3.0.0
*/
class Table extends \WP_List_Table {
/**
* Number of debug events by different types.
*
* @since 3.0.0
*
* @var array
*/
public $counts;
/**
* Set up a constructor that references the parent constructor.
* Using the parent reference to set some default configs.
*
* @since 3.0.0
*/
public function __construct() {
// Set parent defaults.
parent::__construct(
[
'singular' => 'event',
'plural' => 'events',
'ajax' => false,
]
);
// Include polyfill if mbstring PHP extension is not enabled.
if ( ! function_exists( 'mb_substr' ) || ! function_exists( 'mb_strlen' ) ) {
Helpers::include_mbstring_polyfill();
}
}
/**
* Get the debug event types for filtering purpose.
*
* @since 3.0.0
*
* @return array Associative array of debug event types StatusCode=>Name.
*/
public function get_types() {
return Event::get_types();
}
/**
* Get the items counts for various types of debug logs.
*
* @since 3.0.0
*/
public function get_counts() {
$this->counts = [];
// Base params with applied filters.
$base_params = $this->get_filters_query_params();
$total_params = $base_params;
unset( $total_params['type'] );
$this->counts['total'] = ( new EventsCollection( $total_params ) )->get_count();
foreach ( $this->get_types() as $type => $name ) {
$collection = new EventsCollection( array_merge( $base_params, [ 'type' => $type ] ) );
$this->counts[ 'type_' . $type ] = $collection->get_count();
}
/**
* Filters items counts by various types of debug events.
*
* @since 3.0.0
*
* @param array $counts {
* Items counts by types.
*
* @type integer $total Total items count.
* @type integer $status_{$type_key} Items count by type.
* }
*/
$this->counts = apply_filters( 'wp_mail_smtp_admin_debug_events_table_get_counts', $this->counts );
}
/**
* Retrieve the view types.
*
* @since 3.0.0
*/
public function get_views() {
$base_url = $this->get_filters_base_url();
$current_type = $this->get_filtered_types();
$views = [];
$views['all'] = sprintf(
'<a href="%1$s" %2$s>%3$s&nbsp;<span class="count">(%4$d)</span></a>',
esc_url( remove_query_arg( 'type', $base_url ) ),
$current_type === false ? 'class="current"' : '',
esc_html__( 'All', 'wp-mail-smtp' ),
intval( $this->counts['total'] )
);
foreach ( $this->get_types() as $type => $type_label ) {
$count = intval( $this->counts[ 'type_' . $type ] );
// Skipping types with no events.
if ( $count === 0 && $current_type !== $type ) {
continue;
}
$views[ $type ] = sprintf(
'<a href="%1$s" %2$s>%3$s&nbsp;<span class="count">(%4$d)</span></a>',
esc_url( add_query_arg( 'type', $type, $base_url ) ),
$current_type === $type ? 'class="current"' : '',
esc_html( $type_label ),
$count
);
}
/**
* Filters debug event item views.
*
* @since 3.0.0
*
* @param array $views {
* Debug event items views by types.
*
* @type string $all Total items view.
* @type integer $status_key Items views by type.
* }
* @param array $counts {
* Items counts by types.
*
* @type integer $total Total items count.
* @type integer $status_{$status_key} Items count by types.
* }
*/
return apply_filters( 'wp_mail_smtp_admin_debug_events_table_get_views', $views, $this->counts );
}
/**
* Define the table columns.
*
* @since 3.0.0
*
* @return array Associative array of slug=>Name columns data.
*/
public function get_columns() {
return [
'event' => esc_html__( 'Event', 'wp-mail-smtp' ),
'type' => esc_html__( 'Type', 'wp-mail-smtp' ),
'content' => esc_html__( 'Content', 'wp-mail-smtp' ),
'initiator' => esc_html__( 'Source', 'wp-mail-smtp' ),
'created_at' => esc_html__( 'Date', 'wp-mail-smtp' ),
];
}
/**
* Display the main event title with a link to open event details.
*
* @since 3.0.0
*
* @param Event $item Event object.
*
* @return string
*/
public function column_event( $item ) {
return '<strong>' .
'<a href="#" data-event-id="' . esc_attr( $item->get_id() ) . '"' .
' class="js-wp-mail-smtp-debug-event-preview row-title event-preview" title="' . esc_attr( $item->get_title() ) . '">' .
esc_html( $item->get_title() ) .
'</a>' .
'</strong>';
}
/**
* Display event's type.
*
* @since 3.0.0
*
* @param Event $item Event object.
*
* @return string
*/
public function column_type( $item ) {
return esc_html( $item->get_type_name() );
}
/**
* Display event's content.
*
* @since 3.0.0
*
* @param Event $item Event object.
*
* @return string
*/
public function column_content( $item ) {
$content = $item->get_content();
if ( mb_strlen( $content ) > 100 ) {
$content = mb_substr( $content, 0, 100 ) . '...';
}
return wp_kses_post( $content );
}
/**
* Display event's wp_mail initiator.
*
* @since 3.0.0
*
* @param Event $item Event object.
*
* @return string
*/
public function column_initiator( $item ) {
return esc_html( $item->get_initiator() );
}
/**
* Display event's created date.
*
* @since 3.0.0
*
* @param Event $item Event object.
*
* @return string
*/
public function column_created_at( $item ) {
return $item->get_created_at_formatted();
}
/**
* Return type filter value or FALSE.
*
* @since 3.0.0
*
* @return bool|integer
*/
public function get_filtered_types() {
if ( ! isset( $_REQUEST['type'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return false;
}
return intval( $_REQUEST['type'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
/**
* Return date filter value or FALSE.
*
* @since 3.0.0
*
* @return bool|array
*/
public function get_filtered_dates() {
if ( empty( $_REQUEST['date'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return false;
}
$dates = (array) explode( ' - ', sanitize_text_field( wp_unslash( $_REQUEST['date'] ) ) ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return array_map( 'sanitize_text_field', $dates );
}
/**
* Return search filter values or FALSE.
*
* @since 3.0.0
*
* @return bool|array
*/
public function get_filtered_search() {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( empty( $_REQUEST['search'] ) ) {
return false;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
return sanitize_text_field( wp_unslash( $_REQUEST['search'] ) );
}
/**
* Whether the event log is filtered or not.
*
* @since 3.0.0
*
* @return bool
*/
public function is_filtered() {
$is_filtered = false;
if (
$this->get_filtered_search() !== false ||
$this->get_filtered_dates() !== false ||
$this->get_filtered_types() !== false
) {
$is_filtered = true;
}
return $is_filtered;
}
/**
* Get current filters query parameters.
*
* @since 3.0.0
*
* @return array
*/
public function get_filters_query_params() {
$params = [
'search' => $this->get_filtered_search(),
'type' => $this->get_filtered_types(),
'date' => $this->get_filtered_dates(),
];
return array_filter(
$params,
function ( $v ) {
return $v !== false;
}
);
}
/**
* Get current filters base url.
*
* @since 3.0.0
*
* @return string
*/
public function get_filters_base_url() {
$base_url = DebugEvents::get_page_url();
$filters_params = $this->get_filters_query_params();
if ( isset( $filters_params['search'] ) ) {
$base_url = add_query_arg( 'search', $filters_params['search'], $base_url );
}
if ( isset( $filters_params['type'] ) ) {
$base_url = add_query_arg( 'type', $filters_params['type'], $base_url );
}
if ( isset( $filters_params['date'] ) ) {
$base_url = add_query_arg( 'date', implode( ' - ', $filters_params['date'] ), $base_url );
}
return $base_url;
}
/**
* Get the data, prepare pagination, process bulk actions.
* Prepare columns for display.
*
* @since 3.0.0
*/
public function prepare_items() {
// Retrieve count.
$this->get_counts();
// Prepare all the params to pass to our Collection. All sanitization is done in that class.
$params = $this->get_filters_query_params();
// Total amount for pagination with WHERE clause - super quick count DB request.
$total_items = ( new EventsCollection( $params ) )->get_count();
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! empty( $_REQUEST['orderby'] ) && in_array( $_REQUEST['orderby'], [ 'event', 'type', 'content', 'initiator', 'created_at' ], true ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$params['orderby'] = sanitize_key( $_REQUEST['orderby'] );
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! empty( $_REQUEST['order'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$params['order'] = strtoupper( sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ) ) === 'DESC' ? 'DESC' : 'ASC';
}
$params['offset'] = ( $this->get_pagenum() - 1 ) * EventsCollection::$per_page;
// Get the data from the DB using parameters defined above.
$collection = new EventsCollection( $params );
$this->items = $collection->get();
/*
* Register our pagination options & calculations.
*/
$this->set_pagination_args(
[
'total_items' => $total_items,
'per_page' => EventsCollection::$per_page,
]
);
}
/**
* Display the search box.
*
* @since 1.7.0
*
* @param string $text The 'submit' button label.
* @param string $input_id ID attribute value for the search input field.
*/
public function search_box( $text, $input_id ) {
if ( ! $this->is_filtered() && ! $this->has_items() ) {
return;
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$search = ! empty( $_REQUEST['search'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['search'] ) ) : '';
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! empty( $_REQUEST['orderby'] ) && in_array( $_REQUEST['orderby'], [ 'event', 'type', 'content', 'initiator', 'created_at' ], true ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$order_by = sanitize_text_field( wp_unslash( $_REQUEST['orderby'] ) );
echo '<input type="hidden" name="orderby" value="' . esc_attr( $order_by ) . '" />';
}
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( ! empty( $_REQUEST['order'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
$order = strtoupper( sanitize_text_field( wp_unslash( $_REQUEST['order'] ) ) ) === 'DESC' ? 'DESC' : 'ASC';
echo '<input type="hidden" name="order" value="' . esc_attr( $order ) . '" />';
}
?>
<p class="search-box">
<label class="screen-reader-text" for="<?php echo esc_attr( $input_id ); ?>"><?php echo esc_html( $text ); ?>:</label>
<input type="search" id="<?php echo esc_attr( $input_id ); ?>" name="search" value="<?php echo esc_attr( $search ); ?>" />
<?php submit_button( $text, '', '', false, [ 'id' => 'search-submit' ] ); ?>
</p>
<?php
}
/**
* Whether the table has items to display or not.
*
* @since 3.0.0
*
* @return bool
*/
public function has_items() {
return count( $this->items ) > 0;
}
/**
* Message to be displayed when there are no items.
*
* @since 3.0.0
*/
public function no_items() {
if ( $this->is_filtered() ) {
esc_html_e( 'No events found.', 'wp-mail-smtp' );
} else {
esc_html_e( 'No events have been logged for now.', 'wp-mail-smtp' );
}
}
/**
* Displays the table.
*
* @since 3.0.0
*/
public function display() {
$this->_column_headers = [ $this->get_columns(), [], [] ];
parent::display();
}
/**
* Hide the tablenav if there are no items in the table.
* And remove the bulk action nonce and code.
*
* @since 3.0.0
*
* @param string $which Which tablenav: top or bottom.
*/
protected function display_tablenav( $which ) {
if ( ! $this->has_items() ) {
return;
}
?>
<div class="tablenav <?php echo esc_attr( $which ); ?>">
<?php
$this->extra_tablenav( $which );
$this->pagination( $which );
?>
<br class="clear" />
</div>
<?php
}
/**
* Extra controls to be displayed between bulk actions and pagination.
*
* @since 3.0.0
*
* @param string $which Which tablenav: top or bottom.
*/
protected function extra_tablenav( $which ) {
if ( $which !== 'top' || ! $this->has_items() ) {
return;
}
$date = $this->get_filtered_dates() !== false ? implode( ' - ', $this->get_filtered_dates() ) : '';
?>
<div class="alignleft actions wp-mail-smtp-filter-date">
<input type="text" name="date" class="regular-text wp-mail-smtp-filter-date-selector wp-mail-smtp-filter-date__control"
placeholder="<?php esc_attr_e( 'Select a date range', 'wp-mail-smtp' ); ?>"
value="<?php echo esc_attr( $date ); ?>">
<button type="submit" name="action" value="filter_date" class="button wp-mail-smtp-filter-date__btn">
<?php esc_html_e( 'Filter', 'wp-mail-smtp' ); ?>
</button>
</div>
<?php
if ( current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_nonce_field( 'wp_mail_smtp_debug_events', 'wp-mail-smtp-debug-events-nonce', false );
printf(
'<button id="wp-mail-smtp-delete-all-debug-events-button" type="button" class="button">%s</button>',
esc_html__( 'Delete All Events', 'wp-mail-smtp' )
);
}
}
/**
* Get the name of the primary column.
* Important for the mobile view.
*
* @since 3.0.0
*
* @return string The name of the primary column.
*/
protected function get_primary_column_name() {
return 'event';
}
}

View File

@@ -0,0 +1,203 @@
<?php
namespace WPMailSMTP\Admin;
use WPMailSMTP\Helpers\Helpers;
/**
* Class for interacting with the Domain Checker API.
*
* @since 2.6.0
*/
class DomainChecker {
/**
* The domain checker API endpoint.
*
* @since 2.6.0
*/
const ENDPOINT = 'https://connect.wpmailsmtp.com/domain-check/';
/**
* The API results.
*
* @since 2.6.0
*
* @var array
*/
private $results;
/**
* The plugin mailer slug.
*
* @since 2.7.0
*
* @var string
*/
protected $mailer;
/**
* Verify the domain for the provided mailer and email address and save the API results.
*
* @since 2.6.0
*
* @param string $mailer The plugin mailer.
* @param string $email The email address from which the domain will be extracted.
* @param string $sending_domain The optional sending domain to check the domain records for.
*/
public function __construct( $mailer, $email, $sending_domain = '' ) {
$this->mailer = $mailer;
$params = [
'mailer' => $mailer,
'email' => base64_encode( $email ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
'domain' => $sending_domain,
];
$response = wp_remote_get(
add_query_arg( $params, self::ENDPOINT ),
[
'user-agent' => Helpers::get_default_user_agent(),
]
);
if ( is_wp_error( $response ) ) {
$this->results = [
'success' => false,
'message' => method_exists( $response, 'get_error_message' ) ?
$response->get_error_message() :
esc_html__( 'Something went wrong. Please try again later.', 'wp-mail-smtp' ),
'checks' => [],
];
} else {
$this->results = json_decode( wp_remote_retrieve_body( $response ), true );
}
}
/**
* Simple getter for the API results.
*
* @since 2.6.0
*
* @return array
*/
public function get_results() {
return $this->results;
}
/**
* Check if the domain checker has found any errors.
*
* @since 2.6.0
*
* @return bool
*/
public function has_errors() {
if ( empty( $this->results['success'] ) ) {
return true;
}
if ( empty( $this->results['checks'] ) ) {
return false;
}
$has_error = false;
foreach ( $this->results['checks'] as $check ) {
if ( $check['state'] === 'error' ) {
$has_error = true;
break;
}
}
return $has_error;
}
/**
* Check if the domain checker has not found any errors or warnings.
*
* @since 2.6.0
*
* @return bool
*/
public function no_issues() {
if ( empty( $this->results['success'] ) ) {
return false;
}
$no_issues = true;
foreach ( $this->results['checks'] as $check ) {
if ( in_array( $check['state'], [ 'error', 'warning' ], true ) ) {
$no_issues = false;
break;
}
}
return $no_issues;
}
/**
* Check if the domain checker support mailer.
*
* @since 2.7.0
*
* @return bool
*/
public function is_supported_mailer() {
return ! in_array( $this->mailer, [ 'mail', 'pepipostapi' ], true );
}
/**
* Get the domain checker results html.
*
* @since 2.8.0
*
* @return string
*/
public function get_results_html() {
$results = $this->get_results();
$allowed_html = [
'b' => [],
'i' => [],
'a' => [
'href' => [],
'target' => [],
'rel' => [],
],
];
ob_start();
?>
<div id="wp-mail-smtp-domain-check-details">
<h2><?php esc_html_e( 'Domain Check Results', 'wp-mail-smtp' ); ?></h2>
<?php if ( empty( $results['success'] ) ) : ?>
<div class="notice-inline <?php echo $this->is_supported_mailer() ? 'notice-error' : 'notice-warning'; ?>">
<p><?php echo wp_kses( $results['message'], $allowed_html ); ?></p>
</div>
<?php endif; ?>
<?php if ( ! empty( $results['checks'] ) ) : ?>
<div class="wp-mail-smtp-domain-check-details-check-list">
<?php foreach ( $results['checks'] as $check ) : ?>
<div class="wp-mail-smtp-domain-check-details-check-list-item">
<img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/icons/' . esc_attr( $check['state'] ) . '.svg' ); ?>" class="wp-mail-smtp-domain-check-details-check-list-item-icon" alt="<?php printf( /* translators: %s - item state name. */ esc_attr__( '%s icon', 'wp-mail-smtp' ), esc_attr( $check['state'] ) ); ?>">
<div class="wp-mail-smtp-domain-check-details-check-list-item-content">
<h3><?php echo esc_html( $check['type'] ); ?></h3>
<p><?php echo wp_kses( $check['message'], $allowed_html ); ?></p>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endif; ?>
</div>
<?php
return ob_get_clean();
}
}

View File

@@ -0,0 +1,102 @@
<?php
namespace WPMailSMTP\Admin;
/**
* WP Mail SMTP enhancements to admin pages to educate Lite users on what is available in WP Mail SMTP Pro.
*
* @since 2.3.0
*/
class Education {
/**
* The dismissed notice bar user meta key.
*
* @since 2.3.0
*/
const DISMISS_NOTICE_BAR_KEY = 'wp_mail_smtp_edu_notice_bar_dismissed';
/**
* Hooks.
*
* @since 2.3.0
*/
public function hooks() {
if ( apply_filters( 'wp_mail_smtp_admin_education_notice_bar', true ) ) {
add_action( 'admin_init', [ $this, 'notice_bar_init' ] );
}
}
/**
* Notice bar init.
*
* @since 2.3.0
*/
public function notice_bar_init() {
add_action( 'wp_mail_smtp_admin_header_before', [ $this, 'notice_bar_display' ] );
add_action( 'wp_ajax_wp_mail_smtp_notice_bar_dismiss', [ $this, 'notice_bar_ajax_dismiss' ] );
}
/**
* Notice bar display message.
*
* @since 2.3.0
*/
public function notice_bar_display() {
// Bail if we're not on a plugin admin page.
if ( ! wp_mail_smtp()->get_admin()->is_admin_page() ) {
return;
}
$dismissed = get_user_meta( get_current_user_id(), self::DISMISS_NOTICE_BAR_KEY, true );
if ( ! empty( $dismissed ) ) {
return;
}
printf(
'<div id="wp-mail-smtp-notice-bar">
<div class="wp-mail-smtp-notice-bar-container">
<span class="wp-mail-smtp-notice-bar-message">%s</span>
<button type="button" class="dismiss" title="%s" />
</div>
</div>',
wp_kses(
sprintf( /* translators: %s - WPMailSMTP.com Upgrade page URL. */
__( 'Youre using WP Mail SMTP Lite. To unlock more features, consider <a href="%s" target="_blank" rel="noopener noreferrer">upgrading to Pro</a>.', 'wp-mail-smtp' ),
wp_mail_smtp()->get_upgrade_link( [ 'medium' => 'notice-bar' ] )
),
[
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
esc_attr__( 'Dismiss this message.', 'wp-mail-smtp' )
);
}
/**
* Ajax handler for dismissing notices.
*
* @since 2.3.0
*/
public function notice_bar_ajax_dismiss() {
// Run a security check.
check_ajax_referer( 'wp-mail-smtp-admin', 'nonce' );
// Check for permissions.
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
wp_send_json_error();
}
update_user_meta( get_current_user_id(), self::DISMISS_NOTICE_BAR_KEY, time() );
wp_send_json_success();
}
}

View File

@@ -0,0 +1,146 @@
<?php
namespace WPMailSMTP\Admin;
/**
* Admin Flyout Menu.
*
* @since 3.0.0
*/
class FlyoutMenu {
/**
* Hooks.
*
* @since 3.0.0
*/
public function hooks() {
/**
* Filter for enabling/disabling the quick links (flyout menu).
*
* @since 3.0.0
*
* @param bool $enabled Whether quick links are enabled.
*/
if ( apply_filters( 'wp_mail_smtp_admin_flyout_menu', true ) ) {
add_action( 'admin_footer', [ $this, 'output' ] );
}
}
/**
* Output menu.
*
* @since 3.0.0
*/
public function output() {
// Bail if we're not on a plugin admin page.
if ( ! wp_mail_smtp()->get_admin()->is_admin_page() ) {
return;
}
printf(
'<div id="wp-mail-smtp-flyout">
<div id="wp-mail-smtp-flyout-items">%1$s</div>
<a href="#" class="wp-mail-smtp-flyout-button wp-mail-smtp-flyout-head">
<div class="wp-mail-smtp-flyout-label">%2$s</div>
<figure><img src="%3$s" alt="%2$s"/></figure>
</a>
</div>',
$this->get_items_html(), // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
esc_html__( 'See Quick Links', 'wp-mail-smtp' ),
esc_url( wp_mail_smtp()->assets_url . '/images/flyout-menu/mascot.svg' )
);
}
/**
* Generate menu items HTML.
*
* @since 3.0.0
*
* @return string Menu items HTML.
*/
private function get_items_html() {
$items = array_reverse( $this->menu_items() );
$items_html = '';
foreach ( $items as $item_key => $item ) {
$items_html .= sprintf(
'<a href="%1$s" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-flyout-button wp-mail-smtp-flyout-item wp-mail-smtp-flyout-item-%2$d"%5$s%6$s>
<div class="wp-mail-smtp-flyout-label">%3$s</div>
<img src="%4$s" alt="%3$s">
</a>',
esc_url( $item['url'] ),
(int) $item_key,
esc_html( $item['title'] ),
esc_url( $item['icon'] ),
! empty( $item['bgcolor'] ) ? ' style="background-color: ' . esc_attr( $item['bgcolor'] ) . '"' : '',
! empty( $item['hover_bgcolor'] ) ? ' onMouseOver="this.style.backgroundColor=\'' . esc_attr( $item['hover_bgcolor'] ) . '\'" onMouseOut="this.style.backgroundColor=\'' . esc_attr( $item['bgcolor'] ) . '\'"' : ''
);
}
return $items_html;
}
/**
* Menu items data.
*
* @since 3.0.0
*
* @return array Menu items data.
*/
private function menu_items() {
$icons_url = wp_mail_smtp()->assets_url . '/images/flyout-menu';
$items = [
[
'title' => esc_html__( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ),
'url' => wp_mail_smtp()->get_upgrade_link( [ 'medium' => 'quick-link-menu' ] ),
'icon' => $icons_url . '/star.svg',
'bgcolor' => '#E27730',
'hover_bgcolor' => '#B85A1B',
],
[
'title' => esc_html__( 'Support & Docs', 'wp-mail-smtp' ),
// phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
'url' => esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/', [ 'medium' => 'quick-link-menu', 'content' => 'Support' ] ) ),
'icon' => $icons_url . '/life-ring.svg',
],
[
'title' => esc_html__( 'Follow on Facebook', 'wp-mail-smtp' ),
'url' => 'https://www.facebook.com/wpmailsmtp',
'icon' => $icons_url . '/facebook.svg',
],
[
'title' => esc_html__( 'Suggest a Feature', 'wp-mail-smtp' ),
// phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
'url' => esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/suggest-a-feature/', [ 'medium' => 'quick-link-menu', 'content' => 'Feature' ] ) ),
'icon' => $icons_url . '/lightbulb.svg',
],
];
if ( wp_mail_smtp()->is_pro() ) {
array_shift( $items );
}
/**
* Filters quick links items.
*
* @since 3.0.0
*
* @param array $items {
* Quick links items.
*
* @type string $title Item title.
* @type string $url Item link.
* @type string $icon Item icon url.
* @type string $bgcolor Item background color (optional).
* @type string $hover_bgcolor Item background color on hover (optional).
* }
*/
return apply_filters( 'wp_mail_smtp_admin_flyout_menu_menu_items', $items );
}
}

View File

@@ -0,0 +1,540 @@
<?php
namespace WPMailSMTP\Admin;
use WPMailSMTP\Helpers\Helpers;
use WPMailSMTP\Options;
use WPMailSMTP\Tasks\Tasks;
use WPMailSMTP\WP;
/**
* Notifications.
*
* @since 2.3.0
*/
class Notifications {
/**
* Source of notifications content.
*
* @since 2.3.0
*
* @var string
*/
const SOURCE_URL = 'https://plugin.wpmailsmtp.com/wp-content/notifications.json';
/**
* The WP option key for storing the notification options.
*
* @since 2.3.0
*
* @var string
*/
const OPTION_KEY = 'wp_mail_smtp_notifications';
/**
* Option value.
*
* @since 2.3.0
*
* @var bool|array
*/
public $option = false;
/**
* Initialize class.
*
* @since 2.3.0
*/
public function init() {
$this->hooks();
}
/**
* Register hooks.
*
* @since 2.3.0
*/
public function hooks() {
add_action( 'admin_enqueue_scripts', [ $this, 'enqueue_assets' ] );
add_action( 'wp_mail_smtp_admin_pages_before_content', [ $this, 'output' ] );
add_action( 'wp_mail_smtp_admin_notifications_update', [ $this, 'update' ] );
add_action( 'wp_ajax_wp_mail_smtp_notification_dismiss', [ $this, 'dismiss' ] );
}
/**
* Check if user has access and is enabled.
*
* @since 2.3.0
*
* @return bool
*/
public function has_access() {
$access = false;
if (
current_user_can( wp_mail_smtp()->get_capability_manage_options() ) &&
! Options::init()->get( 'general', 'am_notifications_hidden' )
) {
$access = true;
}
return apply_filters( 'wp_mail_smtp_admin_notifications_has_access', $access );
}
/**
* Get option value.
*
* @since 2.3.0
*
* @param bool $cache Reference property cache if available.
*
* @return array
*/
public function get_option( $cache = true ) {
if ( $this->option && $cache ) {
return $this->option;
}
$option = get_option( self::OPTION_KEY, [] );
$this->option = [
'update' => ! empty( $option['update'] ) ? $option['update'] : 0,
'events' => ! empty( $option['events'] ) ? $option['events'] : [],
'feed' => ! empty( $option['feed'] ) ? $option['feed'] : [],
'dismissed' => ! empty( $option['dismissed'] ) ? $option['dismissed'] : [],
];
return $this->option;
}
/**
* Fetch notifications from feed.
*
* @since 2.3.0
*
* @return array
*/
protected function fetch_feed() {
$response = wp_remote_get(
self::SOURCE_URL,
[
'user-agent' => Helpers::get_default_user_agent(),
]
);
if ( is_wp_error( $response ) ) {
return [];
}
$body = wp_remote_retrieve_body( $response );
if ( empty( $body ) ) {
return [];
}
return $this->verify( json_decode( $body, true ) );
}
/**
* Verify notification data before it is saved.
*
* @since 2.3.0
*
* @param array $notifications Array of notification items to verify.
*
* @return array
*/
protected function verify( $notifications ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
$data = [];
if ( ! is_array( $notifications ) || empty( $notifications ) ) {
return $data;
}
$option = $this->get_option();
foreach ( $notifications as $notification ) {
// The message and license should never be empty, if they are, ignore.
if ( empty( $notification['content'] ) || empty( $notification['type'] ) ) {
continue;
}
// Ignore if license type does not match.
if ( ! in_array( wp_mail_smtp()->get_license_type(), $notification['type'], true ) ) {
continue;
}
// Ignore if expired.
if ( ! empty( $notification['end'] ) && time() > strtotime( $notification['end'] ) ) {
continue;
}
// Ignore if notification has already been dismissed.
if ( ! empty( $option['dismissed'] ) && in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
continue;
}
// Ignore if notification existed before installing WPForms.
// Prevents bombarding the user with notifications after activation.
$activated = get_option( 'wp_mail_smtp_activated_time' );
if (
! empty( $activated ) &&
! empty( $notification['start'] ) &&
$activated > strtotime( $notification['start'] )
) {
continue;
}
$data[] = $notification;
}
return $data;
}
/**
* Verify saved notification data for active notifications.
*
* @since 2.3.0
*
* @param array $notifications Array of notification items to verify.
*
* @return array
*/
protected function verify_active( $notifications ) {
if ( ! is_array( $notifications ) || empty( $notifications ) ) {
return [];
}
// Remove notifications that are not active.
foreach ( $notifications as $key => $notification ) {
if (
( ! empty( $notification['start'] ) && time() < strtotime( $notification['start'] ) ) ||
( ! empty( $notification['end'] ) && time() > strtotime( $notification['end'] ) )
) {
unset( $notifications[ $key ] );
}
}
return $notifications;
}
/**
* Get notification data.
*
* @since 2.3.0
* @since 3.9.0 Make the AS a recurring task.
*
* @return array
*/
public function get() {
if ( ! $this->has_access() ) {
return [];
}
$option = $this->get_option();
// Update notifications a recurring task.
if ( Tasks::is_scheduled( 'wp_mail_smtp_admin_notifications_update' ) === false ) {
wp_mail_smtp()->get_tasks()
->create( 'wp_mail_smtp_admin_notifications_update' )
->recurring(
strtotime( '+1 minute' ),
$this->get_notification_update_task_interval()
)
->params()
->register();
}
$events = ! empty( $option['events'] ) ? $this->verify_active( $option['events'] ) : [];
$feed = ! empty( $option['feed'] ) ? $this->verify_active( $option['feed'] ) : [];
return array_merge( $events, $feed );
}
/**
* Get the update notifications interval.
*
* @since 3.9.0
*
* @return int
*/
private function get_notification_update_task_interval() {
/**
* Filters the interval for the notifications update task.
*
* @since 3.9.0
*
* @param int $interval The interval in seconds. Default to a day (in seconds).
*/
return (int) apply_filters( 'wp_mail_smtp_admin_notifications_get_notification_update_task_interval', DAY_IN_SECONDS );
}
/**
* Get notification count.
*
* @since 2.3.0
*
* @return int
*/
public function get_count() {
return count( $this->get() );
}
/**
* Add a manual notification event.
*
* @since 2.3.0
*
* @param array $notification Notification data.
*/
public function add( $notification ) {
if ( empty( $notification['id'] ) ) {
return;
}
$option = $this->get_option();
if ( in_array( $notification['id'], $option['dismissed'] ) ) { // phpcs:ignore WordPress.PHP.StrictInArray.MissingTrueStrict
return;
}
foreach ( $option['events'] as $item ) {
if ( $item['id'] === $notification['id'] ) {
return;
}
}
$notification = $this->verify( [ $notification ] );
update_option(
self::OPTION_KEY,
[
'update' => $option['update'],
'feed' => $option['feed'],
'events' => array_merge( $notification, $option['events'] ),
'dismissed' => $option['dismissed'],
]
);
}
/**
* Update notification data from feed.
*
* @since 2.3.0
*/
public function update() {
$feed = $this->fetch_feed();
$option = $this->get_option();
update_option(
self::OPTION_KEY,
[
'update' => time(),
'feed' => $feed,
'events' => $option['events'],
'dismissed' => $option['dismissed'],
]
);
}
/**
* Admin area assets.
*
* @since 2.3.0
*
* @param string $hook Hook suffix for the current admin page.
*/
public function enqueue_assets( $hook ) {
if ( strpos( $hook, Area::SLUG ) === false ) {
return;
}
if ( ! $this->has_access() ) {
return;
}
$notifications = $this->get();
if ( empty( $notifications ) ) {
return;
}
wp_enqueue_style(
'wp-mail-smtp-admin-notifications',
wp_mail_smtp()->assets_url . '/css/admin-notifications.min.css',
[],
WPMS_PLUGIN_VER
);
wp_enqueue_script(
'wp-mail-smtp-admin-notifications',
wp_mail_smtp()->assets_url . '/js/smtp-notifications' . WP::asset_min() . '.js',
[ 'jquery' ],
WPMS_PLUGIN_VER,
true
);
}
/**
* Output notifications.
*
* @since 2.3.0
*/
public function output() { // phpcs:ignore Generic.Metrics.NestingLevel.MaxExceeded
$notifications = $this->get();
if ( empty( $notifications ) ) {
return;
}
$notifications_html = '';
$current_class = ' current';
$content_allowed_tags = [
'em' => [],
'i' => [],
'strong' => [],
'span' => [
'style' => [],
],
'a' => [
'href' => [],
'target' => [],
'rel' => [],
],
'br' => [],
'p' => [
'id' => [],
'class' => [],
],
];
foreach ( $notifications as $notification ) {
// Buttons HTML.
$buttons_html = '';
if ( ! empty( $notification['btns'] ) && is_array( $notification['btns'] ) ) {
foreach ( $notification['btns'] as $btn_type => $btn ) {
if ( empty( $btn['text'] ) ) {
continue;
}
$buttons_html .= sprintf(
'<a href="%1$s" class="button button-%2$s"%3$s>%4$s</a>',
! empty( $btn['url'] ) ? esc_url( $btn['url'] ) : '',
$btn_type === 'main' ? 'primary' : 'secondary',
! empty( $btn['target'] ) && $btn['target'] === '_blank' ? ' target="_blank" rel="noopener noreferrer"' : '',
sanitize_text_field( $btn['text'] )
);
}
$buttons_html = ! empty( $buttons_html ) ? '<div class="wp-mail-smtp-notifications-buttons">' . $buttons_html . '</div>' : '';
}
// Notification HTML.
$notifications_html .= sprintf(
'<div class="wp-mail-smtp-notifications-message%5$s" data-message-id="%4$s">
<h3 class="wp-mail-smtp-notifications-title">%1$s</h3>
<div class="wp-mail-smtp-notifications-content">%2$s</div>
%3$s
</div>',
! empty( $notification['title'] ) ? sanitize_text_field( $notification['title'] ) : '',
! empty( $notification['content'] ) ? wp_kses( wpautop( $notification['content'] ), $content_allowed_tags ) : '',
$buttons_html,
! empty( $notification['id'] ) ? esc_attr( sanitize_text_field( $notification['id'] ) ) : 0,
$current_class
);
// Only first notification is current.
$current_class = '';
}
?>
<div id="wp-mail-smtp-notifications">
<div class="wp-mail-smtp-notifications-header">
<div class="wp-mail-smtp-notifications-bell">
<svg width="16" height="20" viewBox="0 0 16 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<path fill-rule="evenodd" clip-rule="evenodd" d="M12.8173 8.92686C12.4476 9.01261 12.0624 9.05794 11.6666 9.05794C8.86542 9.05794 6.59455 6.78729 6.59419 3.98616C4.22974 4.54931 2.51043 6.64293 2.51043 9.23824C2.51043 12.4695 1.48985 13.6147 0.849845 14.3328C0.796894 14.3922 0.746548 14.4487 0.699601 14.5032C0.505584 14.707 0.408575 14.9787 0.440912 15.2165C0.440912 15.7939 0.828946 16.3034 1.47567 16.3034H13.8604C14.5071 16.3034 14.8952 15.7939 14.9275 15.2165C14.9275 14.9787 14.8305 14.707 14.6365 14.5032C14.5895 14.4487 14.5392 14.3922 14.4862 14.3328C13.8462 13.6147 12.8257 12.4695 12.8257 9.23824C12.8257 9.13361 12.8229 9.02979 12.8173 8.92686ZM9.72139 17.3904C9.72139 18.6132 8.81598 19.5643 7.68421 19.5643C6.52011 19.5643 5.6147 18.6132 5.6147 17.3904H9.72139Z" fill="#777777"/>
<path d="M11.6666 7.60868C13.6677 7.60868 15.2898 5.98653 15.2898 3.9855C15.2898 1.98447 13.6677 0.36232 11.6666 0.36232C9.66561 0.36232 8.04346 1.98447 8.04346 3.9855C8.04346 5.98653 9.66561 7.60868 11.6666 7.60868Z" fill="#d63638"/>
</svg>
</div>
<div class="wp-mail-smtp-notifications-title"><?php esc_html_e( 'Notifications', 'wp-mail-smtp' ); ?></div>
</div>
<div class="wp-mail-smtp-notifications-body">
<a class="dismiss" title="<?php echo esc_attr__( 'Dismiss this message', 'wp-mail-smtp' ); ?>"><i class="dashicons dashicons-dismiss" aria-hidden="true"></i></a>
<?php if ( count( $notifications ) > 1 ) : ?>
<div class="navigation">
<a class="prev">
<span class="screen-reader-text"><?php esc_attr_e( 'Previous message', 'wp-mail-smtp' ); ?></span>
<span aria-hidden="true"></span>
</a>
<a class="next">
<span class="screen-reader-text"><?php esc_attr_e( 'Next message', 'wp-mail-smtp' ); ?>"></span>
<span aria-hidden="true"></span>
</a>
</div>
<?php endif; ?>
<div class="wp-mail-smtp-notifications-messages">
<?php echo $notifications_html; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</div>
</div>
</div>
<?php
}
/**
* Dismiss notification via AJAX.
*
* @since 2.3.0
*/
public function dismiss() {
// Run a security check.
check_ajax_referer( 'wp-mail-smtp-admin', 'nonce' );
// Check for access and required param.
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) || empty( $_POST['id'] ) ) {
wp_send_json_error();
}
$id = sanitize_text_field( wp_unslash( $_POST['id'] ) );
$option = $this->get_option();
$type = is_numeric( $id ) ? 'feed' : 'events';
$option['dismissed'][] = $id;
$option['dismissed'] = array_unique( $option['dismissed'] );
// Remove notification.
if ( is_array( $option[ $type ] ) && ! empty( $option[ $type ] ) ) {
foreach ( $option[ $type ] as $key => $notification ) {
if ( $notification['id'] == $id ) { // phpcs:ignore WordPress.PHP.StrictComparisons
unset( $option[ $type ][ $key ] );
break;
}
}
}
update_option( self::OPTION_KEY, $option );
wp_send_json_success();
}
}

View File

@@ -0,0 +1,208 @@
<?php
namespace WPMailSMTP\Admin;
use WPMailSMTP\WP;
/**
* Class PageAbstract.
*
* @since 1.0.0
*/
abstract class PageAbstract implements PageInterface {
/**
* @var string Slug of a tab.
*/
protected $slug;
/**
* Tab priority.
*
* @since 2.8.0
*
* @var int
*/
protected $priority = 999;
/**
* Tab parent page.
*
* @since 2.8.0
*
* @var ParentPageAbstract
*/
protected $parent_page = null;
/**
* Constructor.
*
* @since 2.8.0
*
* @param ParentPageAbstract $parent_page Tab parent page.
*/
public function __construct( $parent_page = null ) {
$this->parent_page = $parent_page;
}
/**
* @inheritdoc
*/
public function get_link() {
$page = Area::SLUG;
if ( $this->parent_page !== null ) {
$page .= '-' . $this->parent_page->get_slug();
}
return add_query_arg(
'tab',
$this->slug,
WP::admin_url( 'admin.php?page=' . $page )
);
}
/**
* Title of a tab.
*
* @since 3.7.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
/**
* Get tab slug.
*
* @since 2.8.0
*
* @return string
*/
public function get_slug() {
return $this->slug;
}
/**
* Get tab priority.
*
* @since 2.8.0
*
* @return int
*/
public function get_priority() {
return $this->priority;
}
/**
* Get parent page.
*
* @since 2.8.0
*
* @return ParentPageAbstract
*/
public function get_parent_page() {
return $this->parent_page;
}
/**
* Get parent page slug.
*
* @since 3.0.0
*
* @return string
*/
public function get_parent_slug() {
if ( is_null( $this->parent_page ) ) {
return '';
}
return $this->parent_page->get_slug();
}
/**
* Register tab related hooks.
*
* @since 2.8.0
*/
public function hooks() {}
/**
* Register tab related ajax hooks.
*
* @since 3.0.0
*/
public function ajax() {}
/**
* Process tab form submission ($_POST ).
*
* @since 1.0.0
*
* @param array $data $_POST data specific for the plugin.
*/
public function process_post( $data ) {}
/**
* Process tab & mailer specific Auth actions.
*
* @since 1.0.0
*/
public function process_auth() {}
/**
* Print the nonce field for a specific tab.
*
* @since 1.0.0
*/
public function wp_nonce_field() {
wp_nonce_field( Area::SLUG . '-' . $this->slug );
}
/**
* Make sure that a user was referred from plugin admin page.
* To avoid security problems.
*
* @since 1.0.0
*/
public function check_admin_referer() {
check_admin_referer( Area::SLUG . '-' . $this->slug );
}
/**
* Save button to be reused on other tabs.
*
* @since 1.5.0
*/
public function display_save_btn() {
?>
<p class="wp-mail-smtp-submit">
<button type="submit" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Save Settings', 'wp-mail-smtp' ); ?>
</button>
</p>
<?php
$this->post_form_hidden_field();
}
/**
* Form hidden field for identifying plugin POST requests.
*
* @since 2.9.0
*/
public function post_form_hidden_field() {
echo '<input type="hidden" name="wp-mail-smtp-post" value="1">';
}
}

View File

@@ -0,0 +1,45 @@
<?php
namespace WPMailSMTP\Admin;
/**
* Class PageInterface defines what should be in each page class.
*
* @since 1.0.0
*/
interface PageInterface {
/**
* URL to a tab.
*
* @since 1.0.0
*
* @return string
*/
public function get_link();
/**
* Title of a tab.
*
* @since 1.0.0
*
* @return string
*/
public function get_title();
/**
* Link label of a tab.
*
* @since 1.0.0
*
* @return string
*/
public function get_label();
/**
* Tab content.
*
* @since 1.0.0
*/
public function display();
}

View File

@@ -0,0 +1,92 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\ParentPageAbstract;
/**
* About parent page.
*
* @since 1.5.0
* @since 2.9.0 changed parent class from PageAbstract to ParentPageAbstract.
*/
class About extends ParentPageAbstract {
/**
* Slug of a page.
*
* @since 1.5.0
*
* @var string Slug of a page.
*/
protected $slug = 'about';
/**
* Page default tab slug.
*
* @since 2.9.0
*
* @var string
*/
protected $default_tab = 'about';
/**
* Get label for a tab.
* Process only those that exists.
* Defaults to "About Us".
*
* @since 1.5.0
*
* @param string $tab Tab to get label for.
*
* @return string
*/
public function get_label( $tab = '' ) {
if ( ! empty( $tab ) ) {
return $this->get_tab_label( $tab );
}
return esc_html__( 'About Us', 'wp-mail-smtp' );
}
/**
* Title of a page.
*
* @since 1.5.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
/**
* Active the given plugin.
*
* @deprecated 2.9.0
*
* @since 1.5.0
*/
public static function ajax_plugin_activate() {
_deprecated_function( __METHOD__, '2.9.0', '\WPMailSMTP\Admin\Pages\AboutTab::ajax_plugin_activate' );
AboutTab::ajax_plugin_activate();
}
/**
* Install & activate the given plugin.
*
* @deprecated 2.9.0
*
* @since 1.5.0
*/
public static function ajax_plugin_install() {
_deprecated_function( __METHOD__, '2.9.0', '\WPMailSMTP\Admin\Pages\AboutTab::ajax_plugin_install' );
AboutTab::ajax_plugin_install();
}
}

View File

@@ -0,0 +1,672 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use Plugin_Upgrader;
use WPMailSMTP\Admin\PageAbstract;
use WPMailSMTP\Admin\PluginsInstallSkin;
use WPMailSMTP\Helpers\Helpers;
/**
* About tab.
*
* @since 2.9.0
*/
class AboutTab extends PageAbstract {
/**
* Part of the slug of a tab.
*
* @since 2.9.0
*
* @var string
*/
protected $slug = 'about';
/**
* Tab priority.
*
* @since 2.9.0
*
* @var int
*/
protected $priority = 20;
/**
* Link label of a tab.
*
* @since 2.9.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'About Us', 'wp-mail-smtp' );
}
/**
* Title of a tab.
*
* @since 2.9.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
/**
* Tab content.
*
* @since 2.9.0
*/
public function display() {
?>
<div class="wp-mail-smtp-admin-about-section wp-mail-smtp-admin-columns">
<div class="wp-mail-smtp-admin-column-60">
<h3>
<?php esc_html_e( 'Hello and welcome to WP Mail SMTP, the easiest and most popular WordPress SMTP plugin. We build software that helps your site reliably deliver emails every time.', 'wp-mail-smtp' ); ?>
</h3>
<p>
<?php esc_html_e( 'Email deliverability has been a well-documented problem for all WordPress websites. However as WPForms grew, we became more aware of this painful issue that affects our users and the larger WordPress community. So we decided to solve this problem and make a solution that\'s beginner friendly.', 'wp-mail-smtp' ); ?>
</p>
<p>
<?php esc_html_e( 'Our goal is to make reliable email deliverability easy for WordPress.', 'wp-mail-smtp' ); ?>
</p>
<p>
<?php
printf(
wp_kses(
/* translators: %1$s - WPForms URL, %2$s - WPBeginner URL, %3$s - OptinMonster URL, %4$s - MonsterInsights URL, %5$s - Awesome Motive URL */
__( 'WP Mail SMTP is brought to you by the same team that\'s behind the most user friendly WordPress forms, <a href="%1$s" target="_blank" rel="noopener noreferrer">WPForms</a>, the largest WordPress resource site, <a href="%2$s" target="_blank" rel="noopener noreferrer">WPBeginner</a>, the most popular lead-generation software, <a href="%3$s" target="_blank" rel="noopener noreferrer">OptinMonster</a>, the best WordPress analytics plugin, <a href="%4$s" target="_blank" rel="noopener noreferrer">MonsterInsights</a>, and <a href="%5$s" target="_blank" rel="noopener noreferrer">more</a>.', 'wp-mail-smtp' ),
[
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
'https://wpforms.com/?utm_source=wpmailsmtpplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpmailsmtp',
'https://www.wpbeginner.com/?utm_source=wpmailsmtpplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpmailsmtp',
'https://optinmonster.com/?utm_source=wpmailsmtpplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpmailsmtp',
'https://www.monsterinsights.com/?utm_source=wpmailsmtpplugin&utm_medium=pluginaboutpage&utm_campaign=aboutwpmailsmtp',
// phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
esc_url( wp_mail_smtp()->get_utm_url( 'https://awesomemotive.com/', [ 'medium' => 'pluginaboutpage', 'content' => 'aboutwpmailsmtp' ] ) )
);
?>
</p>
<p>
<?php esc_html_e( 'Yup, we know a thing or two about building awesome products that customers love.', 'wp-mail-smtp' ); ?>
</p>
</div>
<div class="wp-mail-smtp-admin-column-40 wp-mail-smtp-admin-column-last">
<figure>
<img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/about/team.jpg' ); ?>" alt="<?php esc_attr_e( 'The WPForms Team photo', 'wp-mail-smtp' ); ?>">
<figcaption>
<?php esc_html_e( 'The WPForms Team', 'wp-mail-smtp' ); ?>
</figcaption>
</figure>
</div>
</div>
<?php
// Do not display the plugin section if the user can't install or activate them.
if ( ! current_user_can( 'install_plugins' ) && ! current_user_can( 'activate_plugins' ) ) {
return;
}
$this->display_plugins();
}
/**
* Display the plugins section.
*
* @since 2.9.0
*/
protected function display_plugins() {
?>
<div class="wp-mail-smtp-admin-about-plugins">
<div class="plugins-container">
<?php
foreach ( self::get_am_plugins() as $key => $plugin ) :
$is_url_external = false;
$data = $this->get_about_plugins_data( $plugin );
if ( isset( $plugin['pro'] ) && array_key_exists( $plugin['pro']['path'], get_plugins() ) ) {
$is_url_external = true;
$plugin = $plugin['pro'];
$data = array_merge( $data, $this->get_about_plugins_data( $plugin, true ) );
}
// Do not display a plugin which has to be installed and the user can't install it.
if ( ! current_user_can( 'install_plugins' ) && $data['status_class'] === 'status-download' ) {
continue;
}
?>
<div class="plugin-container">
<div class="plugin-item">
<div class="details wp-mail-smtp-clear">
<img src="<?php echo esc_url( $plugin['icon'] ); ?>" alt="<?php esc_attr_e( 'Plugin icon', 'wp-mail-smtp' ); ?>">
<h5 class="plugin-name">
<?php echo esc_html( $plugin['name'] ); ?>
</h5>
<p class="plugin-desc">
<?php echo esc_html( $plugin['desc'] ); ?>
</p>
</div>
<div class="actions wp-mail-smtp-clear">
<div class="status">
<strong>
<?php
printf(
/* translators: %s - status HTML text. */
esc_html__( 'Status: %s', 'wp-mail-smtp' ),
'<span class="status-label ' . esc_attr( $data['status_class'] ) . '">' . esc_html( $data['status_text'] ) . '</span>'
);
?>
</strong>
</div>
<div class="action-button">
<?php
$go_to_class = '';
if ( $is_url_external && $data['status_class'] === 'status-download' ) {
$go_to_class = ' go_to';
}
?>
<a href="<?php echo esc_url( $plugin['url'] ); ?>"
class="<?php echo esc_attr( $data['action_class'] . $go_to_class ); ?>"
data-plugin="<?php echo esc_attr( $data['plugin_src'] ); ?>">
<?php echo esc_html( $data['action_text'] ); ?>
</a>
</div>
</div>
</div>
</div>
<?php endforeach; ?>
</div>
</div>
<?php
}
/**
* Generate all the required CSS classed and labels to be used in rendering.
*
* @since 2.9.0
*
* @param array $plugin Plugin slug.
* @param bool $is_pro License type.
*
* @return mixed
*/
protected function get_about_plugins_data( $plugin, $is_pro = false ) {
$data = [];
if ( array_key_exists( $plugin['path'], get_plugins() ) ) {
if ( is_plugin_active( $plugin['path'] ) ) {
// Status text/status.
$data['status_class'] = 'status-active';
$data['status_text'] = esc_html__( 'Active', 'wp-mail-smtp' );
// Button text/status.
$data['action_class'] = $data['status_class'] . ' button button-secondary disabled';
$data['action_text'] = esc_html__( 'Activated', 'wp-mail-smtp' );
$data['plugin_src'] = esc_attr( $plugin['path'] );
} else {
// Status text/status.
$data['status_class'] = 'status-inactive';
$data['status_text'] = esc_html__( 'Inactive', 'wp-mail-smtp' );
// Button text/status.
$data['action_class'] = $data['status_class'] . ' button button-secondary';
$data['action_text'] = esc_html__( 'Activate', 'wp-mail-smtp' );
$data['plugin_src'] = esc_attr( $plugin['path'] );
}
} else {
if ( ! $is_pro ) {
// Doesn't exist, install.
// Status text/status.
$data['status_class'] = 'status-download';
$data['status_text'] = esc_html__( 'Not Installed', 'wp-mail-smtp' );
// Button text/status.
$data['action_class'] = $data['status_class'] . ' button button-primary';
$data['action_text'] = esc_html__( 'Install Plugin', 'wp-mail-smtp' );
$data['plugin_src'] = esc_url( $plugin['url'] );
// If plugin URL is not a zip file, open a new tab with site URL.
if ( preg_match( '/.*\.zip$/', $plugin['url'] ) === 0 ) {
$data['status_class'] = 'status-open';
$data['action_class'] = $data['status_class'] . ' button button-primary';
$data['action_text'] = esc_html__( 'Visit Site', 'wp-mail-smtp' );
}
}
}
return $data;
}
/**
* List of AM plugins that we propose to install.
*
* @since 2.9.0
*
* @return array
*/
private static function get_am_plugins() {
$data = [
'om' => [
'path' => 'optinmonster/optin-monster-wp-api.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-om.png',
'name' => esc_html__( 'OptinMonster', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Instantly get more subscribers, leads, and sales with the #1 conversion optimization toolkit. Create high converting popups, announcement bars, spin a wheel, and more with smart targeting and personalization.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/optinmonster.zip',
],
'wpforms' => [
'path' => 'wpforms-lite/wpforms.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-wpf.png',
'name' => esc_html__( 'WPForms', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The best drag & drop WordPress form builder. Easily create beautiful contact forms, surveys, payment forms, and more with our 600+ form templates. Trusted by over 5 million websites as the best forms plugin.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/wpforms-lite.zip',
'pro' => [
'path' => 'wpforms/wpforms.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-wpf.png',
'name' => esc_html__( 'WPForms Pro', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The best drag & drop WordPress form builder. Easily create beautiful contact forms, surveys, payment forms, and more with our 600+ form templates. Trusted by over 5 million websites as the best forms plugin.', 'wp-mail-smtp' ),
'url' => 'https://wpforms.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'mi' => [
'path' => 'google-analytics-for-wordpress/googleanalytics.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-mi.png',
'name' => esc_html__( 'MonsterInsights', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The leading WordPress analytics plugin that shows you how people find and use your website, so you can make data driven decisions to grow your business. Properly set up Google Analytics without writing code.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/google-analytics-for-wordpress.zip',
'pro' => [
'path' => 'google-analytics-premium/googleanalytics-premium.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-mi.png',
'name' => esc_html__( 'MonsterInsights Pro', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The leading WordPress analytics plugin that shows you how people find and use your website, so you can make data driven decisions to grow your business. Properly set up Google Analytics without writing code.', 'wp-mail-smtp' ),
'url' => 'https://www.monsterinsights.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'aioseo' => [
'path' => 'all-in-one-seo-pack/all_in_one_seo_pack.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-aioseo.png',
'name' => esc_html__( 'AIOSEO', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The original WordPress SEO plugin and toolkit that improves your websites search rankings. Comes with all the SEO features like Local SEO, WooCommerce SEO, sitemaps, SEO optimizer, schema, and more.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/all-in-one-seo-pack.zip',
'pro' => [
'path' => 'all-in-one-seo-pack-pro/all_in_one_seo_pack.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-aioseo.png',
'name' => esc_html__( 'AIOSEO', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The original WordPress SEO plugin and toolkit that improves your websites search rankings. Comes with all the SEO features like Local SEO, WooCommerce SEO, sitemaps, SEO optimizer, schema, and more.', 'wp-mail-smtp' ),
'url' => 'https://aioseo.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'seedprod' => [
'path' => 'coming-soon/coming-soon.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-seedprod.png',
'name' => esc_html__( 'SeedProd', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The fastest drag & drop landing page builder for WordPress. Create custom landing pages without writing code, connect them with your CRM, collect subscribers, and grow your audience. Trusted by 1 million sites.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/coming-soon.zip',
'pro' => [
'path' => 'seedprod-coming-soon-pro-5/seedprod-coming-soon-pro-5.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-seedprod.png',
'name' => esc_html__( 'SeedProd', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The fastest drag & drop landing page builder for WordPress. Create custom landing pages without writing code, connect them with your CRM, collect subscribers, and grow your audience. Trusted by 1 million sites.', 'wp-mail-smtp' ),
'url' => 'https://www.seedprod.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'rafflepress' => [
'path' => 'rafflepress/rafflepress.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-rp.png',
'name' => esc_html__( 'RafflePress', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Turn your website visitors into brand ambassadors! Easily grow your email list, website traffic, and social media followers with the most powerful giveaways & contests plugin for WordPress.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/rafflepress.zip',
'pro' => [
'path' => 'rafflepress-pro/rafflepress-pro.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-rp.png',
'name' => esc_html__( 'RafflePress Pro', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Turn your website visitors into brand ambassadors! Easily grow your email list, website traffic, and social media followers with the most powerful giveaways & contests plugin for WordPress.', 'wp-mail-smtp' ),
'url' => 'https://rafflepress.com/pricing/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'pushengage' => [
'path' => 'pushengage/main.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-pushengage.png',
'name' => esc_html__( 'PushEngage', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Connect with your visitors after they leave your website with the leading web push notification software. Over 10,000+ businesses worldwide use PushEngage to send 15 billion notifications each month.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/pushengage.zip',
],
'smash-balloon-instagram-feeds' => [
'path' => 'instagram-feed/instagram-feed.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-smash-balloon-instagram-feeds.png',
'name' => esc_html__( 'Smash Balloon Instagram Feeds', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Easily display Instagram content on your WordPress site without writing any code. Comes with multiple templates, ability to show content from multiple accounts, hashtags, and more. Trusted by 1 million websites.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/instagram-feed.zip',
'pro' => [
'path' => 'instagram-feed-pro/instagram-feed.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-smash-balloon-instagram-feeds.png',
'name' => esc_html__( 'Smash Balloon Instagram Feeds', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Easily display Instagram content on your WordPress site without writing any code. Comes with multiple templates, ability to show content from multiple accounts, hashtags, and more. Trusted by 1 million websites.', 'wp-mail-smtp' ),
'url' => 'https://smashballoon.com/instagram-feed/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'smash-balloon-facebook-feeds' => [
'path' => 'custom-facebook-feed/custom-facebook-feed.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-smash-balloon-facebook-feeds.png',
'name' => esc_html__( 'Smash Balloon Facebook Feeds', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Easily display Facebook content on your WordPress site without writing any code. Comes with multiple templates, ability to embed albums, group content, reviews, live videos, comments, and reactions.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/custom-facebook-feed.zip',
'pro' => [
'path' => 'custom-facebook-feed-pro/custom-facebook-feed.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-smash-balloon-facebook-feeds.png',
'name' => esc_html__( 'Smash Balloon Facebook Feeds', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Easily display Facebook content on your WordPress site without writing any code. Comes with multiple templates, ability to embed albums, group content, reviews, live videos, comments, and reactions.', 'wp-mail-smtp' ),
'url' => 'https://smashballoon.com/custom-facebook-feed/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'smash-balloon-youtube-feeds' => [
'path' => 'feeds-for-youtube/youtube-feed.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-smash-balloon-youtube-feeds.png',
'name' => esc_html__( 'Smash Balloon YouTube Feeds', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Easily display YouTube videos on your WordPress site without writing any code. Comes with multiple layouts, ability to embed live streams, video filtering, ability to combine multiple channel videos, and more.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/feeds-for-youtube.zip',
'pro' => [
'path' => 'youtube-feed-pro/youtube-feed.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-smash-balloon-youtube-feeds.png',
'name' => esc_html__( 'Smash Balloon YouTube Feeds', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Easily display YouTube videos on your WordPress site without writing any code. Comes with multiple layouts, ability to embed live streams, video filtering, ability to combine multiple channel videos, and more.', 'wp-mail-smtp' ),
'url' => 'https://smashballoon.com/youtube-feed/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'smash-balloon-twitter-feeds' => [
'path' => 'custom-twitter-feeds/custom-twitter-feed.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-smash-balloon-twitter-feeds.png',
'name' => esc_html__( 'Smash Balloon Twitter Feeds', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Easily display Twitter content in WordPress without writing any code. Comes with multiple layouts, ability to combine multiple Twitter feeds, Twitter card support, tweet moderation, and more.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/custom-twitter-feeds.zip',
'pro' => [
'path' => 'custom-twitter-feeds-pro/custom-twitter-feed.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-smash-balloon-twitter-feeds.png',
'name' => esc_html__( 'Smash Balloon Twitter Feeds', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Easily display Twitter content in WordPress without writing any code. Comes with multiple layouts, ability to combine multiple Twitter feeds, Twitter card support, tweet moderation, and more.', 'wp-mail-smtp' ),
'url' => 'https://smashballoon.com/custom-twitter-feeds/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'trustpulse' => [
'path' => 'trustpulse-api/trustpulse.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-trustpulse.png',
'name' => esc_html__( 'TrustPulse', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Boost your sales and conversions by up to 15% with real-time social proof notifications. TrustPulse helps you show live user activity and purchases to help convince other users to purchase.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/trustpulse-api.zip',
],
'searchwp' => [
'path' => '',
'icon' => wp_mail_smtp()->assets_url . '/images/about/searchwp.png',
'name' => esc_html__( 'SearchWP', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The most advanced WordPress search plugin. Customize your WordPress search algorithm, reorder search results, track search metrics, and everything you need to leverage search to grow your business.', 'wp-mail-smtp' ),
'url' => 'https://searchwp.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
'pro' => [
'path' => 'searchwp/index.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/searchwp.png',
'name' => esc_html__( 'SearchWP', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The most advanced WordPress search plugin. Customize your WordPress search algorithm, reorder search results, track search metrics, and everything you need to leverage search to grow your business.', 'wp-mail-smtp' ),
'url' => 'https://searchwp.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'affiliatewp' => [
'path' => '',
'icon' => wp_mail_smtp()->assets_url . '/images/about/affiliatewp.png',
'name' => esc_html__( 'AffiliateWP', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The #1 affiliate management plugin for WordPress. Easily create an affiliate program for your eCommerce store or membership site within minutes and start growing your sales with the power of referral marketing.', 'wp-mail-smtp' ),
'url' => 'https://affiliatewp.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
'pro' => [
'path' => 'affiliate-wp/affiliate-wp.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/affiliatewp.png',
'name' => esc_html__( 'AffiliateWP', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The #1 affiliate management plugin for WordPress. Easily create an affiliate program for your eCommerce store or membership site within minutes and start growing your sales with the power of referral marketing.', 'wp-mail-smtp' ),
'url' => 'https://affiliatewp.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'wp-simple-pay' => [
'path' => 'stripe/stripe-checkout.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/wp-simple-pay.png',
'name' => esc_html__( 'WP Simple Pay', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The #1 Stripe payments plugin for WordPress. Start accepting one-time and recurring payments on your WordPress site without setting up a shopping cart. No code required.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/stripe.zip',
'pro' => [
'path' => 'wp-simple-pay-pro-3/simple-pay.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/wp-simple-pay.png',
'name' => esc_html__( 'WP Simple Pay Pro', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The #1 Stripe payments plugin for WordPress. Start accepting one-time and recurring payments on your WordPress site without setting up a shopping cart. No code required.', 'wp-mail-smtp' ),
'url' => 'https://wpsimplepay.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'easy-digital-downloads' => [
'path' => 'easy-digital-downloads/easy-digital-downloads.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/edd.png',
'name' => esc_html__( 'Easy Digital Downloads', 'wp-mail-smtp' ),
'desc' => esc_html__( 'The best WordPress eCommerce plugin for selling digital downloads. Start selling eBooks, software, music, digital art, and more within minutes. Accept payments, manage subscriptions, advanced access control, and more.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/easy-digital-downloads.zip',
],
'sugar-calendar' => [
'path' => 'sugar-calendar-lite/sugar-calendar-lite.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/sugar-calendar.png',
'name' => esc_html__( 'Sugar Calendar Lite', 'wp-mail-smtp' ),
'desc' => esc_html__( 'A simple & powerful event calendar plugin for WordPress that comes with all the event management features including payments, scheduling, timezones, ticketing, recurring events, and more.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/sugar-calendar-lite.zip',
'pro' => [
'path' => 'sugar-calendar/sugar-calendar.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/sugar-calendar.png',
'name' => esc_html__( 'Sugar Calendar', 'wp-mail-smtp' ),
'desc' => esc_html__( 'A simple & powerful event calendar plugin for WordPress that comes with all the event management features including payments, scheduling, timezones, ticketing, recurring events, and more.', 'wp-mail-smtp' ),
'url' => 'https://sugarcalendar.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'wp-charitable' => [
'path' => 'charitable/charitable.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-charitable.png',
'name' => esc_html__( 'WP Charitable', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Top-rated WordPress donation and fundraising plugin. Over 10,000+ non-profit organizations and website owners use Charitable to create fundraising campaigns and raise more money online.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/charitable.zip',
],
'wpcode' => [
'path' => 'insert-headers-and-footers/ihaf.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-wpcode.png',
'name' => esc_html__( 'WPCode Lite', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Future proof your WordPress customizations with the most popular code snippet management plugin for WordPress. Trusted by over 1,500,000+ websites for easily adding code to WordPress right from the admin area.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/insert-headers-and-footers.zip',
'pro' => [
'path' => 'wpcode-premium/wpcode.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/plugin-wpcode.png',
'name' => esc_html__( 'WPCode Pro', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Future proof your WordPress customizations with the most popular code snippet management plugin for WordPress. Trusted by over 1,500,000+ websites for easily adding code to WordPress right from the admin area.', 'wp-mail-smtp' ),
'url' => 'https://wpcode.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
'duplicator' => [
'path' => 'duplicator/duplicator.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/duplicator-icon-large.png',
'name' => esc_html__( 'Duplicator', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Leading WordPress backup & site migration plugin. Over 1,500,000+ smart website owners use Duplicator to make reliable and secure WordPress backups to protect their websites. It also makes website migration really easy.', 'wp-mail-smtp' ),
'url' => 'https://downloads.wordpress.org/plugin/duplicator.zip',
'pro' => [
'path' => 'duplicator-pro/duplicator-pro.php',
'icon' => wp_mail_smtp()->assets_url . '/images/about/duplicator-icon-large.png',
'name' => esc_html__( 'Duplicator Pro', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Leading WordPress backup & site migration plugin. Over 1,500,000+ smart website owners use Duplicator to make reliable and secure WordPress backups to protect their websites. It also makes website migration really easy.', 'wp-mail-smtp' ),
'url' => 'https://duplicator.com/?utm_source=WordPress&utm_medium=about&utm_campaign=smtp',
],
],
];
return $data;
}
/**
* Active the given plugin.
*
* @since 2.9.0
*/
public static function ajax_plugin_activate() {
// Run a security check.
check_ajax_referer( 'wp-mail-smtp-about', 'nonce' );
$error = esc_html__( 'Could not activate the plugin. Please activate it from the Plugins page.', 'wp-mail-smtp' );
// Check for permissions.
if ( ! current_user_can( 'activate_plugins' ) ) {
wp_send_json_error( $error );
}
if ( empty( $_POST['plugin'] ) ) {
wp_send_json_error( $error );
}
$plugin_slug = sanitize_text_field( wp_unslash( $_POST['plugin'] ) );
$whitelisted_plugins = [];
foreach ( self::get_am_plugins() as $item ) {
if ( ! empty( $item['path'] ) ) {
$whitelisted_plugins[] = $item['path'];
}
if ( ! empty( $item['pro']['path'] ) ) {
$whitelisted_plugins[] = $item['pro']['path'];
}
}
if ( ! in_array( $plugin_slug, $whitelisted_plugins, true ) ) {
wp_send_json_error( esc_html__( 'Could not activate the plugin. Plugin is not whitelisted.', 'wp-mail-smtp' ) );
}
$activate = activate_plugins( $plugin_slug );
if ( ! is_wp_error( $activate ) ) {
wp_send_json_success( esc_html__( 'Plugin activated.', 'wp-mail-smtp' ) );
}
wp_send_json_error( $error );
}
/**
* Install & activate the given plugin.
*
* @since 2.9.0
*/
public static function ajax_plugin_install() { // phpcs:ignore:Generic.Metrics.CyclomaticComplexity.TooHigh
// Run a security check.
check_ajax_referer( 'wp-mail-smtp-about', 'nonce' );
$error = esc_html__( 'Could not install the plugin.', 'wp-mail-smtp' );
// Check for permissions.
if ( ! current_user_can( 'install_plugins' ) ) {
wp_send_json_error( $error );
}
if ( empty( $_POST['plugin'] ) ) {
wp_send_json_error();
}
$plugin_url = esc_url_raw( wp_unslash( $_POST['plugin'] ) );
if ( ! in_array( $plugin_url, wp_list_pluck( array_values( self::get_am_plugins() ), 'url' ) , true ) ) {
wp_send_json_error( esc_html__( 'Could not install the plugin. Plugin is not whitelisted.', 'wp-mail-smtp' ) );
}
// Set the current screen to avoid undefined notices.
set_current_screen( 'wp-mail-smtp_page_wp-mail-smtp-about' );
// Prepare variables.
$url = esc_url_raw(
add_query_arg(
[
'page' => 'wp-mail-smtp-about',
],
admin_url( 'admin.php' )
)
);
/*
* The `request_filesystem_credentials` function will output a credentials form in case of failure.
* We don't want that, since it will break AJAX response. So just hide output with a buffer.
*/
ob_start();
// phpcs:ignore WPForms.Formatting.EmptyLineAfterAssigmentVariables.AddEmptyLine
$creds = request_filesystem_credentials( $url, '', false, false, null );
ob_end_clean();
// Check for file system permissions.
if ( false === $creds ) {
wp_send_json_error( $error );
}
if ( ! WP_Filesystem( $creds ) ) {
wp_send_json_error( $error );
}
// Do not allow WordPress to search/download translations, as this will break JS output.
remove_action( 'upgrader_process_complete', [ 'Language_Pack_Upgrader', 'async_upgrade' ], 20 );
// Import the plugin upgrader.
Helpers::include_plugin_upgrader();
// Create the plugin upgrader with our custom skin.
$installer = new Plugin_Upgrader( new PluginsInstallSkin() );
// Error check.
if ( ! method_exists( $installer, 'install' ) ) {
wp_send_json_error( $error );
}
$installer->install( $plugin_url );
// Flush the cache and return the newly installed plugin basename.
wp_cache_flush();
if ( $installer->plugin_info() ) {
$plugin_basename = $installer->plugin_info();
// Activate the plugin silently.
$activated = activate_plugin( $plugin_basename );
if ( ! is_wp_error( $activated ) ) {
wp_send_json_success(
[
'msg' => esc_html__( 'Plugin installed & activated.', 'wp-mail-smtp' ),
'is_activated' => true,
'basename' => $plugin_basename,
]
);
} else {
wp_send_json_success(
[
'msg' => esc_html__( 'Plugin installed.', 'wp-mail-smtp' ),
'is_activated' => false,
'basename' => $plugin_basename,
]
);
}
}
wp_send_json_error( $error );
}
}

View File

@@ -0,0 +1,157 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\PageAbstract;
/**
* Class ActionScheduler.
*
* @since 2.9.0
*/
class ActionSchedulerTab extends PageAbstract {
/**
* Part of the slug of a tab.
*
* @since 2.9.0
*
* @var string
*/
protected $slug = 'action-scheduler';
/**
* Tab priority.
*
* @since 2.9.0
*
* @var int
*/
protected $priority = 30;
/**
* Link label of a tab.
*
* @since 2.9.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Scheduled Actions', 'wp-mail-smtp' );
}
/**
* Title of a tab.
*
* @since 2.9.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
/**
* URL to a tab.
*
* @since 2.9.0
*
* @return string
*/
public function get_link() {
return add_query_arg( [ 's' => 'wp_mail_smtp' ], parent::get_link() );
}
/**
* Register hooks.
*
* @since 2.9.0
*/
public function hooks() {
add_action( 'current_screen', [ $this, 'init' ], 20 );
}
/**
* Init.
*
* @since 2.9.0
*/
public function init() {
if ( $this->is_applicable() ) {
\ActionScheduler_AdminView::instance()->process_admin_ui();
}
}
/**
* Display scheduled actions table.
*
* @since 2.9.0
*/
public function display() {
if ( ! $this->is_applicable() ) {
return;
}
?>
<h1><?php echo esc_html__( 'Scheduled Actions', 'wp-mail-smtp' ); ?></h1>
<p>
<?php
echo sprintf(
wp_kses( /* translators: %s - Action Scheduler website URL. */
__( 'WP Mail SMTP is using the <a href="%s" target="_blank" rel="noopener noreferrer">Action Scheduler</a> library, which allows it to queue and process bigger tasks in the background without making your site slower for your visitors. Below you can see the list of all tasks and their status. This table can be very useful when debugging certain issues.', 'wp-mail-smtp' ),
[
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
'https://actionscheduler.org/'
);
?>
</p>
<p>
<?php echo esc_html__( 'Action Scheduler library is also used by other plugins, like WPForms and WooCommerce, so you might see tasks that are not related to our plugin in the table below.', 'wp-mail-smtp' ); ?>
</p>
<?php if ( isset( $_GET['s'] ) ) : // phpcs:ignore WordPress.Security.NonceVerification.Recommended ?>
<div id="wp-mail-smtp-reset-filter">
<?php
echo wp_kses(
sprintf( /* translators: %s - search term. */
__( 'Search results for <strong>%s</strong>', 'wp-mail-smtp' ),
sanitize_text_field( wp_unslash( $_GET['s'] ) ) // phpcs:ignore WordPress.Security.NonceVerification.Recommended
),
[ 'strong' => [] ]
);
?>
<a href="<?php echo esc_url( remove_query_arg( 's' ) ); ?>">
<i class="reset dashicons dashicons-dismiss"></i>
</a>
</div>
<?php endif; ?>
<?php
\ActionScheduler_AdminView::instance()->render_admin_ui();
}
/**
* Check if ActionScheduler_AdminView class exists.
*
* @since 2.9.0
*
* @return bool
*/
private function is_applicable() {
return class_exists( 'ActionScheduler_AdminView' );
}
}

View File

@@ -0,0 +1,193 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\PageAbstract;
/**
* Class AdditionalConnectionsTab is a placeholder for Pro additional connections feature.
* Displays product education.
*
* @since 3.7.0
*/
class AdditionalConnectionsTab extends PageAbstract {
/**
* Part of the slug of a tab.
*
* @since 3.7.0
*
* @var string
*/
protected $slug = 'connections';
/**
* Constructor.
*
* @since 3.7.0
*
* @param PageAbstract $parent_page Parent page object.
*/
public function __construct( $parent_page = null ) {
parent::__construct( $parent_page );
if ( wp_mail_smtp()->get_admin()->get_current_tab() === $this->slug && ! wp_mail_smtp()->is_pro() ) {
$this->hooks();
}
}
/**
* Link label of a tab.
*
* @since 3.7.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Additional Connections', 'wp-mail-smtp' );
}
/**
* Register hooks.
*
* @since 3.7.0
*/
public function hooks() {
add_action( 'wp_mail_smtp_admin_area_enqueue_assets', [ $this, 'enqueue_assets' ] );
}
/**
* Enqueue required JS and CSS.
*
* @since 3.7.0
*/
public function enqueue_assets() {
wp_enqueue_style(
'wp-mail-smtp-admin-lity',
wp_mail_smtp()->assets_url . '/css/vendor/lity.min.css',
[],
'2.4.1'
);
wp_enqueue_script(
'wp-mail-smtp-admin-lity',
wp_mail_smtp()->assets_url . '/js/vendor/lity.min.js',
[],
'2.4.1'
);
}
/**
* Output HTML of additional connections' education.
*
* @since 3.7.0
*/
public function display() {
$top_upgrade_button_url = wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'Additional Connections Settings',
'content' => 'Upgrade to WP Mail SMTP Pro Button Top',
]
);
$bottom_upgrade_button_url = wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'Additional Connections Settings',
'content' => 'Upgrade to WP Mail SMTP Pro Button',
]
);
?>
<div id="wp-mail-additional-connections-product-education" class="wp-mail-smtp-product-education">
<div class="wp-mail-smtp-product-education__row">
<h4 class="wp-mail-smtp-product-education__heading">
<?php esc_html_e( 'Additional Connections', 'wp-mail-smtp' ); ?>
</h4>
<p class="wp-mail-smtp-product-education__description">
<?php
esc_html_e( 'Create additional connections to set a backup for your Primary Connection or to configure Smart Routing.', 'wp-mail-smtp' );
?>
</p>
<a href="<?php echo esc_url( $top_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--top wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<?php
$this->display_education_screenshots();
$this->display_education_features_list();
?>
<a href="<?php echo esc_url( $bottom_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--bottom wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<?php
}
/**
* Output HTML of additional connections' education screenshots.
*
* @since 3.7.0
*/
protected function display_education_screenshots() {
$assets_url = wp_mail_smtp()->assets_url . '/images/additional-connections/';
$screenshots = [
[
'url' => $assets_url . 'screenshot-01.png',
'url_thumbnail' => $assets_url . 'thumbnail-01.png',
'title' => __( 'Backup Connection', 'wp-mail-smtp' ),
],
[
'url' => $assets_url . 'screenshot-02.png',
'url_thumbnail' => $assets_url . 'thumbnail-02.png',
'title' => __( 'Smart Routing', 'wp-mail-smtp' ),
],
];
?>
<div class="wp-mail-smtp-product-education__row wp-mail-smtp-product-education__row--full-width">
<div class="wp-mail-smtp-product-education__screenshots wp-mail-smtp-product-education__screenshots--two">
<?php foreach ( $screenshots as $screenshot ) : ?>
<div>
<a href="<?php echo esc_url( $screenshot['url'] ); ?>" data-lity data-lity-desc="<?php echo esc_attr( $screenshot['title'] ); ?>">
<img src="<?php echo esc_url( $screenshot['url_thumbnail'] ); ?>" alt="<?php esc_attr( $screenshot['title'] ); ?>">
</a>
<span><?php echo esc_html( $screenshot['title'] ); ?></span>
</div>
<?php endforeach; ?>
</div>
</div>
<?php
}
/**
* Output HTML of additional connections' education features list.
*
* @since 3.7.0
*/
protected function display_education_features_list() {
?>
<div class="wp-mail-smtp-product-education__row wp-mail-smtp-product-education__row--full-width">
<div class="wp-mail-smtp-product-education__list">
<h4><?php esc_html_e( 'With additional connections you can...', 'wp-mail-smtp' ); ?></h4>
<div>
<ul>
<li><?php esc_html_e( 'Set a Backup Connection', 'wp-mail-smtp' ); ?></li>
</ul>
<ul>
<li><?php esc_html_e( 'Use mailers for different purposes', 'wp-mail-smtp' ); ?></li>
</ul>
<ul>
<li><?php esc_html_e( 'Create advanced routing rules', 'wp-mail-smtp' ); ?></li>
</ul>
</div>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,273 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\PageAbstract;
use WPMailSMTP\Helpers\UI;
/**
* Class AlertsTab is a placeholder for Pro alerts feature.
* Displays product education.
*
* @since 3.5.0
*/
class AlertsTab extends PageAbstract {
/**
* Part of the slug of a tab.
*
* @since 3.5.0
*
* @var string
*/
protected $slug = 'alerts';
/**
* Tab priority.
*
* @since 3.5.0
*
* @var int
*/
protected $priority = 20;
/**
* Link label of a tab.
*
* @since 3.5.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Alerts', 'wp-mail-smtp' );
}
/**
* Title of a tab.
*
* @since 3.5.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
/**
* Output HTML of the alerts settings preview.
*
* @since 3.5.0
*/
public function display() {
$top_upgrade_button_url = wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'Alerts Settings',
'content' => 'Upgrade to WP Mail SMTP Pro Button Top',
]
);
$bottom_upgrade_button_url = wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'Alerts Settings',
'content' => 'Upgrade to WP Mail SMTP Pro Button',
]
);
?>
<div class="wp-mail-smtp-product-education">
<div class="wp-mail-smtp-product-education__row">
<h4 class="wp-mail-smtp-product-education__heading">
<?php esc_html_e( 'Alerts', 'wp-mail-smtp' ); ?>
</h4>
<p class="wp-mail-smtp-product-education__description">
<?php
esc_html_e( 'Configure at least one of these integrations to receive notifications when email fails to send from your site. Alert notifications will contain the following important data: email subject, email Send To address, the error message, and helpful links to help you fix the issue.', 'wp-mail-smtp' );
?>
</p>
<a href="<?php echo esc_url( $top_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--top wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<div class="wp-mail-smtp-product-education__row wp-mail-smtp-product-education__row--inactive">
<div id="wp-mail-smtp-setting-row-alert_event_types" class="wp-mail-smtp-setting-row wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-debug_event_types">
<?php esc_html_e( 'Notify when', 'wp-mail-smtp' ); ?>
</label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'label' => esc_html__( 'The initial email sending request fails', 'wp-mail-smtp' ),
'checked' => true,
'disabled' => true,
]
);
?>
<p class="desc">
<?php esc_html_e( 'This option is always enabled and will notify you about instant email sending failures.', 'wp-mail-smtp' ); ?>
</p>
<hr class="wp-mail-smtp-setting-mid-row-sep">
<?php
UI::toggle(
[
'label' => esc_html__( 'The deliverability verification process detects a hard bounce', 'wp-mail-smtp' ),
'disabled' => true,
]
);
?>
<p class="desc">
<?php esc_html_e( 'Get notified about emails that were successfully sent, but have hard bounced on delivery attempt. A hard bounce is an email that has failed to deliver for permanent reasons, such as the recipient\'s email address being invalid.', 'wp-mail-smtp' ); ?>
</p>
</div>
</div>
</div>
<div class="wp-mail-smtp-product-education__row wp-mail-smtp-product-education__row--inactive">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-alert">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content section-heading">
<div class="wp-mail-smtp-setting-field">
<h3><?php esc_html_e( 'Email', 'wp-mail-smtp' ); ?></h3>
<p class="desc"><?php esc_html_e( 'Enter the email addresses (3 max) youd like to use to receive alerts when email sending fails. Read our documentation on setting up email alerts.', 'wp-mail-smtp' ); ?></p>
</div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'Email Alerts', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle();
?>
</div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-alert-options">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-alert-connection-options">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'Send To', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field"><input type="text"></div>
</div>
</div>
</div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-alert">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content section-heading">
<div class="wp-mail-smtp-setting-field">
<h3><?php esc_html_e( 'Slack', 'wp-mail-smtp' ); ?></h3>
<p class="desc"><?php esc_html_e( 'Paste in the Slack webhook URL youd like to use to receive alerts when email sending fails. Read our documentation on setting up Slack alerts.', 'wp-mail-smtp' ); ?></p>
</div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'Slack Alerts', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle();
?>
</div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-alert-options">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-alert-connection-options">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'Webhook URL', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field"><input type="text"></div>
</div>
</div>
</div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-alert">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content section-heading">
<div class="wp-mail-smtp-setting-field">
<h3><?php esc_html_e( 'SMS via Twilio', 'wp-mail-smtp' ); ?></h3>
<p class="desc"><?php esc_html_e( 'To receive SMS alerts, youll need a Twilio account. Read our documentation to learn how to set up Twilio SMS, then enter your connection details below.', 'wp-mail-smtp' ); ?></p>
</div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'SMS via Twilio Alerts', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle();
?>
</div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-alert-options">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-alert-connection-options">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'Twilio Account ID', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field"><input type="text"></div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'Twilio Auth Token', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field"><input type="text"></div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'From Phone Number', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field"><input type="text"></div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'To Phone Number', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field"><input type="text"></div>
</div>
</div>
</div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-alert">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content section-heading">
<div class="wp-mail-smtp-setting-field">
<h3><?php esc_html_e( 'Webhook', 'wp-mail-smtp' ); ?></h3>
<p class="desc"><?php esc_html_e( 'Paste in the webhook URL youd like to use to receive alerts when email sending fails. Read our documentation on setting up webhook alerts.', 'wp-mail-smtp' ); ?></p>
</div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'Webhook Alerts', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle();
?>
</div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-alert-options">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-alert-connection-options">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'Webhook URL', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field"><input type="text"></div>
</div>
</div>
</div>
</div>
</div>
<a href="<?php echo esc_url( $bottom_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--bottom wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<?php
}
}

View File

@@ -0,0 +1,74 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Providers\AuthAbstract;
/**
* Class AuthTab.
*
* @since 1.0.0
*/
class AuthTab {
/**
* @var string Slug of a tab.
*/
protected $slug = 'auth';
/**
* Launch mailer specific Auth logic.
*
* @since 1.0.0
*/
public function process_auth() {
$connection = wp_mail_smtp()->get_connections_manager()->get_primary_connection();
/**
* Filters auth connection object.
*
* @since 3.7.0
*
* @param ConnectionInterface $connection The Connection object.
*/
$connection = apply_filters( 'wp_mail_smtp_admin_pages_auth_tab_process_auth_connection', $connection );
$auth = wp_mail_smtp()->get_providers()->get_auth( $connection->get_mailer_slug(), $connection );
if (
$auth &&
$auth instanceof AuthAbstract &&
method_exists( $auth, 'process' )
) {
$auth->process();
}
}
/**
* Return nothing, as we don't need this functionality.
*
* @since 1.0.0
*/
public function get_label() {
return '';
}
/**
* Return nothing, as we don't need this functionality.
*
* @since 1.0.0
*/
public function get_title() {
return '';
}
/**
* Do nothing, as we don't need this functionality.
*
* @since 1.0.0
*/
public function display() {
}
}

View File

@@ -0,0 +1,327 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\PageAbstract;
use WPMailSMTP\Helpers\UI;
use WPMailSMTP\WP;
/**
* Class ControlTab is a placeholder for Pro Email Control tab settings.
* Displays an upsell.
*
* @since 1.6.0
*/
class ControlTab extends PageAbstract {
/**
* Slug of a tab.
*
* @since 1.6.0
*
* @var string
*/
protected $slug = 'control';
/**
* Link label of a tab.
*
* @since 1.6.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Email Controls', 'wp-mail-smtp' );
}
/**
* Title of a tab.
*
* @since 1.6.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
/**
* Get the list of all available emails that we can manage.
*
* @see https://github.com/johnbillion/wp_mail Apr 12th 2019.
*
* @since 3.1.0
*
* @return array
*/
public static function get_controls() {
return [
'comments' => [
'title' => esc_html__( 'Comments', 'wp-mail-smtp' ),
'emails' => [
'dis_comments_awaiting_moderation' => [
'label' => esc_html__( 'Awaiting Moderation', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Comment is awaiting moderation. Sent to the site admin and post author if they can edit comments.', 'wp-mail-smtp' ),
],
'dis_comments_published' => [
'label' => esc_html__( 'Published', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Comment has been published. Sent to the post author.', 'wp-mail-smtp' ),
],
],
],
'admin_email' => [
'title' => esc_html__( 'Change of Admin Email', 'wp-mail-smtp' ),
'emails' => [
'dis_admin_email_attempt' => [
'label' => esc_html__( 'Site Admin Email Change Attempt', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Change of site admin email address was attempted. Sent to the proposed new email address.', 'wp-mail-smtp' ),
],
'dis_admin_email_changed' => [
'label' => esc_html__( 'Site Admin Email Changed', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Site admin email address was changed. Sent to the old site admin email address.', 'wp-mail-smtp' ),
],
'dis_admin_email_network_attempt' => [
'label' => esc_html__( 'Network Admin Email Change Attempt', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Change of network admin email address was attempted. Sent to the proposed new email address.', 'wp-mail-smtp' ),
],
'dis_admin_email_network_changed' => [
'label' => esc_html__( 'Network Admin Email Changed', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Network admin email address was changed. Sent to the old network admin email address.', 'wp-mail-smtp' ),
],
],
],
'user_details' => [
'title' => esc_html__( 'Change of User Email or Password', 'wp-mail-smtp' ),
'emails' => [
'dis_user_details_password_reset_request' => [
'label' => esc_html__( 'Reset Password Request', 'wp-mail-smtp' ),
'desc' => esc_html__( 'User requested a password reset via "Lost your password?". Sent to the user.', 'wp-mail-smtp' ),
],
'dis_user_details_password_reset' => [
'label' => esc_html__( 'Password Reset Successfully', 'wp-mail-smtp' ),
'desc' => esc_html__( 'User reset their password from the password reset link. Sent to the site admin.', 'wp-mail-smtp' ),
],
'dis_user_details_password_changed' => [
'label' => esc_html__( 'Password Changed', 'wp-mail-smtp' ),
'desc' => esc_html__( 'User changed their password. Sent to the user.', 'wp-mail-smtp' ),
],
'dis_user_details_email_change_attempt' => [
'label' => esc_html__( 'Email Change Attempt', 'wp-mail-smtp' ),
'desc' => esc_html__( 'User attempted to change their email address. Sent to the proposed new email address.', 'wp-mail-smtp' ),
],
'dis_user_details_email_changed' => [
'label' => esc_html__( 'Email Changed', 'wp-mail-smtp' ),
'desc' => esc_html__( 'User changed their email address. Sent to the user.', 'wp-mail-smtp' ),
],
],
],
'personal_data' => [
'title' => esc_html__( 'Personal Data Requests', 'wp-mail-smtp' ),
'emails' => [
'dis_personal_data_user_confirmed' => [
'label' => esc_html__( 'User Confirmed Export / Erasure Request', 'wp-mail-smtp' ),
'desc' => esc_html__( 'User clicked a confirmation link in personal data export or erasure request email. Sent to the site or network admin.', 'wp-mail-smtp' ),
],
'dis_personal_data_erased_data' => [
'label' => esc_html__( 'Admin Erased Data', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Site admin clicked "Erase Personal Data" button next to a confirmed data erasure request. Sent to the requester email address.', 'wp-mail-smtp' ),
],
'dis_personal_data_sent_export_link' => [
'label' => esc_html__( 'Admin Sent Link to Export Data', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Site admin clicked "Email Data" button next to a confirmed data export request. Sent to the requester email address.', 'wp-mail-smtp' ) . '<br>' .
'<strong>' . esc_html__( 'Disabling this option will block users from being able to export their personal data, as they will not receive an email with a link.', 'wp-mail-smtp' ) . '</strong>',
],
],
],
'auto_updates' => [
'title' => esc_html__( 'Automatic Updates', 'wp-mail-smtp' ),
'emails' => [
'dis_auto_updates_plugin_status' => [
'label' => esc_html__( 'Plugin Status', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Completion or failure of a background automatic plugin update. Sent to the site or network admin.', 'wp-mail-smtp' ),
],
'dis_auto_updates_theme_status' => [
'label' => esc_html__( 'Theme Status', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Completion or failure of a background automatic theme update. Sent to the site or network admin.', 'wp-mail-smtp' ),
],
'dis_auto_updates_status' => [
'label' => esc_html__( 'WP Core Status', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Completion or failure of a background automatic core update. Sent to the site or network admin.', 'wp-mail-smtp' ),
],
'dis_auto_updates_full_log' => [
'label' => esc_html__( 'Full Log', 'wp-mail-smtp' ),
'desc' => esc_html__( 'Full log of background update results which includes information about WordPress core, plugins, themes, and translations updates. Only sent when you are using a development version of WordPress. Sent to the site or network admin.', 'wp-mail-smtp' ),
],
],
],
'new_user' => [
'title' => esc_html__( 'New User', 'wp-mail-smtp' ),
'emails' => [
'dis_new_user_created_to_admin' => [
'label' => esc_html__( 'Created (Admin)', 'wp-mail-smtp' ),
'desc' => esc_html__( 'A new user was created. Sent to the site admin.', 'wp-mail-smtp' ),
],
'dis_new_user_created_to_user' => [
'label' => esc_html__( 'Created (User)', 'wp-mail-smtp' ),
'desc' => esc_html__( 'A new user was created. Sent to the new user.', 'wp-mail-smtp' ),
],
'dis_new_user_invited_to_site_network' => [
'label' => esc_html__( 'Invited To Site', 'wp-mail-smtp' ),
'desc' => esc_html__( 'A new user was invited to a site from Users -> Add New -> Add New User. Sent to the invited user.', 'wp-mail-smtp' ),
],
'dis_new_user_created_network' => [
'label' => esc_html__( 'Created On Site', 'wp-mail-smtp' ),
'desc' => esc_html__( 'A new user account was created. Sent to Network Admin.', 'wp-mail-smtp' ),
],
'dis_new_user_added_activated_network' => [
'label' => esc_html__( 'Added / Activated on Site', 'wp-mail-smtp' ),
'desc' => esc_html__( 'A user has been added, or their account activation has been successful. Sent to the user, that has been added/activated.', 'wp-mail-smtp' ),
],
],
],
'network_new_site' => [
'title' => esc_html__( 'New Site', 'wp-mail-smtp' ),
'emails' => [
'dis_new_site_user_registered_site_network' => [
'label' => esc_html__( 'User Created Site', 'wp-mail-smtp' ),
'desc' => esc_html__( 'User registered for a new site. Sent to the site admin.', 'wp-mail-smtp' ),
],
'dis_new_site_user_added_activated_site_in_network_to_admin' => [
'label' => esc_html__( 'Network Admin: User Activated / Added Site', 'wp-mail-smtp' ),
'desc' => esc_html__( 'User activated their new site, or site was added from Network Admin -> Sites -> Add New. Sent to Network Admin.', 'wp-mail-smtp' ),
],
'dis_new_site_user_added_activated_site_in_network_to_site' => [
'label' => esc_html__( 'Site Admin: Activated / Added Site', 'wp-mail-smtp' ),
'desc' => esc_html__( 'User activated their new site, or site was added from Network Admin -> Sites -> Add New. Sent to Site Admin.', 'wp-mail-smtp' ),
],
],
],
];
}
/**
* Output HTML of the email controls settings preview.
*
* @since 1.6.0
* @since 2.1.0 Replaced images with SVGs.
* @since 3.1.0 Updated layout to inactive settings preview.
*/
public function display() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
$top_upgrade_button_url = add_query_arg(
[ 'discount' => 'LITEUPGRADE' ],
wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'Email Controls',
'content' => 'Upgrade to WP Mail SMTP Pro Button Top',
]
)
);
$bottom_upgrade_button_url = add_query_arg(
[ 'discount' => 'LITEUPGRADE' ],
wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'Email Controls',
'content' => 'Upgrade to WP Mail SMTP Pro Button',
]
)
);
?>
<div id="wp-mail-smtp-email-controls-product-education" class="wp-mail-smtp-product-education">
<div class="wp-mail-smtp-product-education__row">
<h4 class="wp-mail-smtp-product-education__heading">
<?php esc_html_e( 'Email Controls', 'wp-mail-smtp' ); ?>
</h4>
<p class="wp-mail-smtp-product-education__description">
<?php
esc_html_e( 'Email controls allow you to manage the automatic notifications you receive from your WordPress website. With the flick of a switch, you can reduce inbox clutter and focus on the alerts that matter the most. It\'s easy to disable emails about comments, email or password changes, WordPress updates, user registrations, and personal data requests.', 'wp-mail-smtp' );
?>
</p>
<a href="<?php echo esc_url( $top_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--top wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<div class="wp-mail-smtp-product-education__row wp-mail-smtp-product-education__row--inactive">
<?php
foreach ( static::get_controls() as $section_id => $section ) :
if ( empty( $section['emails'] ) ) {
continue;
}
if ( $this->is_it_for_multisite( sanitize_key( $section_id ) ) && ! WP::use_global_plugin_settings() ) {
continue;
}
?>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading no-desc">
<div class="wp-mail-smtp-setting-field">
<h5><?php echo esc_html( $section['title'] ); ?></h5>
</div>
</div>
<?php
foreach ( $section['emails'] as $email_id => $email ) :
$email_id = sanitize_key( $email_id );
if ( empty( $email_id ) || empty( $email['label'] ) ) {
continue;
}
if ( $this->is_it_for_multisite( sanitize_key( $email_id ) ) && ! WP::use_global_plugin_settings() ) {
continue;
}
?>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label><?php echo esc_html( $email['label'] ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle( [ 'checked' => true ] );
?>
<?php if ( ! empty( $email['desc'] ) ) : ?>
<p class="desc">
<?php echo $email['desc']; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</p>
<?php endif; ?>
</div>
</div>
<?php endforeach; ?>
<?php endforeach; ?>
</div>
<a href="<?php echo esc_url( $bottom_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--bottom wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<?php
}
/**
* Whether this key dedicated to MultiSite environment.
*
* @since 1.5.0
*
* @param string $key Email unique key.
*
* @return bool
*/
protected function is_it_for_multisite( $key ) {
return strpos( $key, 'network' ) !== false;
}
/**
* Not used as we display an upsell.
*
* @since 1.6.0
*
* @param array $data Post data specific for the plugin.
*/
public function process_post( $data ) { }
}

View File

@@ -0,0 +1,561 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\Area;
use WPMailSMTP\Admin\DebugEvents\DebugEvents;
use WPMailSMTP\Admin\DebugEvents\Migration;
use WPMailSMTP\Admin\DebugEvents\Table;
use WPMailSMTP\Admin\PageAbstract;
use WPMailSMTP\Admin\ParentPageAbstract;
use WPMailSMTP\Helpers\UI;
use WPMailSMTP\Options;
use WPMailSMTP\WP;
/**
* Debug Events settings page.
*
* @since 3.0.0
*/
class DebugEventsTab extends PageAbstract {
/**
* Part of the slug of a tab.
*
* @since 3.0.0
*
* @var string
*/
protected $slug = 'debug-events';
/**
* Tab priority.
*
* @since 3.0.0
*
* @var int
*/
protected $priority = 40;
/**
* Debug events list table.
*
* @since 3.0.0
*
* @var Table
*/
protected $table = null;
/**
* Plugin options.
*
* @since 3.0.0
*
* @var Options
*/
protected $options;
/**
* Constructor.
*
* @since 3.0.0
*
* @param ParentPageAbstract $parent_page Tab parent page.
*/
public function __construct( $parent_page = null ) {
$this->options = Options::init();
parent::__construct( $parent_page );
// Remove unnecessary $_GET parameters and prevent url duplications in _wp_http_referer input.
$this->remove_get_parameters();
}
/**
* Link label of a tab.
*
* @since 3.0.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Debug Events', 'wp-mail-smtp' );
}
/**
* Title of a tab.
*
* @since 3.0.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
/**
* Register hooks.
*
* @since 3.0.0
*/
public function hooks() {
add_action( 'wp_mail_smtp_admin_area_enqueue_assets', [ $this, 'enqueue_assets' ] );
}
/**
* Enqueue required JS and CSS.
*
* @since 3.0.0
*/
public function enqueue_assets() {
$min = WP::asset_min();
wp_enqueue_style(
'wp-mail-smtp-flatpickr',
wp_mail_smtp()->assets_url . '/css/vendor/flatpickr.min.css',
[],
'4.6.9'
);
wp_enqueue_script(
'wp-mail-smtp-flatpickr',
wp_mail_smtp()->assets_url . '/js/vendor/flatpickr.min.js',
[ 'jquery' ],
'4.6.9',
true
);
wp_enqueue_script(
'wp-mail-smtp-tools-debug-events',
wp_mail_smtp()->assets_url . "/js/smtp-tools-debug-events{$min}.js",
[ 'jquery', 'wp-mail-smtp-flatpickr' ],
WPMS_PLUGIN_VER,
true
);
wp_localize_script(
'wp-mail-smtp-tools-debug-events',
'wp_mail_smtp_tools_debug_events',
[
'lang_code' => sanitize_key( WP::get_language_code() ),
'plugin_url' => wp_mail_smtp()->plugin_url,
'loader' => wp_mail_smtp()->prepare_loader( 'blue' ),
'texts' => [
'delete_all_notice' => esc_html__( 'Are you sure you want to permanently delete all debug events?', 'wp-mail-smtp' ),
'cancel' => esc_html__( 'Cancel', 'wp-mail-smtp' ),
'close' => esc_html__( 'Close', 'wp-mail-smtp' ),
'yes' => esc_html__( 'Yes', 'wp-mail-smtp' ),
'ok' => esc_html__( 'OK', 'wp-mail-smtp' ),
'notice_title' => esc_html__( 'Heads up!', 'wp-mail-smtp' ),
'error_occurred' => esc_html__( 'An error occurred!', 'wp-mail-smtp' ),
],
]
);
}
/**
* Get email logs list table.
*
* @since 3.0.0
*
* @return Table
*/
public function get_table() {
if ( $this->table === null ) {
$this->table = new Table();
}
return $this->table;
}
/**
* Display scheduled actions table.
*
* @since 3.0.0
*/
public function display() {
?>
<?php if( WP::use_global_plugin_settings() && ! current_user_can( 'manage_network_options' ) ) : ?>
<!-- Debug Events Section Title -->
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading" id="wp-mail-smtp-setting-row-email-heading">
<div class="wp-mail-smtp-setting-field">
<h2><?php esc_html_e( 'Debug Events', 'wp-mail-smtp' ); ?></h2>
</div>
<p>
<?php esc_html_e( 'On this page, you can view different plugin debugging events and email sending errors.', 'wp-mail-smtp' ); ?>
</p>
</div>
<?php else: ?>
<form method="POST" action="<?php echo esc_url( $this->get_link() ); ?>">
<?php $this->wp_nonce_field(); ?>
<!-- Debug Events Section Title -->
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading wp-mail-smtp-section-heading--has-divider">
<div class="wp-mail-smtp-setting-field">
<h2><?php esc_html_e( 'Debug Events', 'wp-mail-smtp' ); ?></h2>
</div>
<p>
<?php esc_html_e( 'On this page, you can view and configure different plugin debugging events. View email sending errors and enable debugging events, allowing you to detect email sending issues.', 'wp-mail-smtp' ); ?>
</p>
</div>
<!-- Debug Events -->
<div id="wp-mail-smtp-setting-row-debug_event_types" class="wp-mail-smtp-setting-row wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-debug_event_types">
<?php esc_html_e( 'Event Types', 'wp-mail-smtp' ); ?>
</label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[debug_events][email_errors]',
'id' => 'wp-mail-smtp-setting-debug_events_email_errors',
'value' => 'true',
'checked' => true,
'disabled' => true,
]
);
?>
<p class="desc">
<?php esc_html_e( 'Email Sending Errors', 'wp-mail-smtp' ); ?>
</p>
<p class="desc">
<?php esc_html_e( 'This debug event is always enabled and will record any email sending errors in the table below.', 'wp-mail-smtp' ); ?>
</p>
<hr class="wp-mail-smtp-setting-mid-row-sep">
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[debug_events][email_debug]',
'id' => 'wp-mail-smtp-setting-debug_events_email_debug',
'value' => 'true',
'checked' => (bool) $this->options->get( 'debug_events', 'email_debug' ),
]
);
?>
<p class="desc">
<?php esc_html_e( 'Debug Email Sending', 'wp-mail-smtp' ); ?>
</p>
<p class="desc">
<?php esc_html_e( 'Check this if you would like to debug the email sending process. Once enabled, all debug events will be logged in the table below. This setting should only be enabled for shorter debugging periods and disabled afterwards.', 'wp-mail-smtp' ); ?>
</p>
</div>
</div>
<div id="wp-mail-smtp-setting-row-debug_events_retention_period" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-select wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-debug_events_retention_period">
<?php esc_html_e( 'Events Retention Period', 'wp-mail-smtp' ); ?>
</label>
</div>
<div class="wp-mail-smtp-setting-field">
<select name="wp-mail-smtp[debug_events][retention_period]" id="wp-mail-smtp-setting-debug_events_retention_period"
<?php disabled( $this->options->is_const_defined( 'debug_events', 'retention_period' ) ); ?>>
<option value=""><?php esc_html_e( 'Forever', 'wp-mail-smtp' ); ?></option>
<?php foreach ( $this->get_debug_events_retention_period_options() as $value => $label ) : ?>
<option value="<?php echo esc_attr( $value ); ?>" <?php selected( $this->options->get( 'debug_events', 'retention_period' ), $value ); ?>>
<?php echo esc_html( $label ); ?>
</option>
<?php endforeach; ?>
</select>
<p class="desc">
<?php
esc_html_e( 'Debug events older than the selected period will be permanently deleted from the database.', 'wp-mail-smtp' );
if ( $this->options->is_const_defined( 'debug_events', 'retention_period' ) ) {
//phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
echo '<br>' . $this->options->get_const_set_message( 'WPMS_DEBUG_EVENTS_RETENTION_PERIOD' );
}
?>
</p>
</div>
</div>
<?php $this->display_save_btn(); ?>
</form>
<?php endif; ?>
<?php
if ( ! DebugEvents::is_valid_db() ) {
$this->display_debug_events_not_installed();
} else {
$table = $this->get_table();
$table->prepare_items();
?>
<form action="<?php echo esc_url( $this->get_link() ); ?>" method="get">
<input type="hidden" name="page" value="<?php echo esc_attr( Area::SLUG . '-tools' ); ?>" />
<input type="hidden" name="tab" value="<?php echo esc_attr( $this->get_slug() ); ?>" />
<?php
// State of status filter for submission with other filters.
if ( $table->get_filtered_types() !== false ) {
printf( '<input type="hidden" name="type" value="%s">', esc_attr( $table->get_filtered_types() ) );
}
if ( $this->get_filters_html() ) {
?>
<div id="wp-mail-smtp-reset-filter">
<?php
$type = $table->get_filtered_types();
echo wp_kses(
sprintf( /* translators: %1$s - number of debug events found; %2$s - filtered type. */
_n(
'Found <strong>%1$s %2$s event</strong>',
'Found <strong>%1$s %2$s events</strong>',
absint( $table->get_pagination_arg( 'total_items' ) ),
'wp-mail-smtp'
),
absint( $table->get_pagination_arg( 'total_items' ) ),
$type !== false && isset( $table->get_types()[ $type ] ) ? $table->get_types()[ $type ] : ''
),
[
'strong' => [],
]
);
?>
<?php foreach ( $this->get_filters_html() as $id => $html ) : ?>
<?php
echo wp_kses(
$html,
[ 'em' => [] ]
);
?>
<i class="reset dashicons dashicons-dismiss" data-scope="<?php echo esc_attr( $id ); ?>"></i>
<?php endforeach; ?>
</div>
<?php
}
$table->search_box(
esc_html__( 'Search Events', 'wp-mail-smtp' ),
Area::SLUG . '-debug-events-search-input'
);
$table->views();
$table->display();
?>
</form>
<?php
}
}
/**
* Process tab form submission ($_POST ).
*
* @since 3.0.0
*
* @param array $data Post data specific for the plugin.
*/
public function process_post( $data ) {
$this->check_admin_referer();
if ( WP::use_global_plugin_settings() && ! current_user_can( 'manage_network_options' ) ) {
wp_die( esc_html__( 'You don\'t have the capability to perform this action.', 'wp-mail-smtp' ) );
}
// Unchecked checkboxes doesn't exist in $_POST, so we need to ensure we actually have them in data to save.
if ( empty( $data['debug_events']['email_debug'] ) ) {
$data['debug_events']['email_debug'] = false;
}
// All the sanitization is done there.
$this->options->set( $data, false, false );
WP::add_admin_notice(
esc_html__( 'Settings were successfully saved.', 'wp-mail-smtp' ),
WP::ADMIN_NOTICE_SUCCESS
);
}
/**
* Return an array with information (HTML and id) for each filter for this current view.
*
* @since 3.0.0
*
* @return array
*/
private function get_filters_html() {
$filters = [
'.search-box' => $this->get_filter_search_html(),
'.wp-mail-smtp-filter-date' => $this->get_filter_date_html(),
];
return array_filter( $filters );
}
/**
* Return HTML with information about the search filter.
*
* @since 3.0.0
*
* @return string
*/
private function get_filter_search_html() {
$table = $this->get_table();
$term = $table->get_filtered_search();
if ( $term === false ) {
return '';
}
return sprintf( /* translators: %s The searched term. */
__( 'where event contains "%s"', 'wp-mail-smtp' ),
'<em>' . esc_html( $term ) . '</em>'
);
}
/**
* Return HTML with information about the date filter.
*
* @since 3.0.0
*
* @return string
*/
private function get_filter_date_html() {
$table = $this->get_table();
$dates = $table->get_filtered_dates();
if ( $dates === false ) {
return '';
}
$dates = array_map(
function ( $date ) {
return date_i18n( 'M j, Y', strtotime( $date ) );
},
$dates
);
$html = '';
switch ( count( $dates ) ) {
case 1:
$html = sprintf( /* translators: %s - Date. */
esc_html__( 'on %s', 'wp-mail-smtp' ),
'<em>' . $dates[0] . '</em>'
);
break;
case 2:
$html = sprintf( /* translators: %1$s - Date. %2$s - Date. */
esc_html__( 'between %1$s and %2$s', 'wp-mail-smtp' ),
'<em>' . $dates[0] . '</em>',
'<em>' . $dates[1] . '</em>'
);
break;
}
return $html;
}
/**
* Display a message when debug events DB table is missing.
*
* @since 3.0.0
*/
private function display_debug_events_not_installed() {
$error_message = get_option( Migration::ERROR_OPTION_NAME );
?>
<div class="notice-inline notice-error">
<h3><?php esc_html_e( 'Debug Events are Not Installed Correctly', 'wp-mail-smtp' ); ?></h3>
<p>
<?php
if ( ! empty( $error_message ) ) {
esc_html_e( 'The database table was not installed correctly. Please contact plugin support to diagnose and fix the issue. Provide them the error message below:', 'wp-mail-smtp' );
echo '<br><br>';
echo '<code>' . esc_html( $error_message ) . '</code>';
} else {
esc_html_e( 'For some reason the database table was not installed correctly. Please contact plugin support team to diagnose and fix the issue.', 'wp-mail-smtp' );
}
?>
</p>
</div>
<?php
}
/**
* Remove unnecessary $_GET parameters for shorter URL.
*
* @since 3.0.0
*/
protected function remove_get_parameters() {
if ( isset( $_SERVER['REQUEST_URI'] ) ) {
$_SERVER['REQUEST_URI'] = remove_query_arg(
[
'_wp_http_referer',
'_wpnonce',
'wp-mail-smtp-debug-events-nonce',
],
$_SERVER['REQUEST_URI'] // phpcs:ignore WordPress.Security.ValidatedSanitizedInput
);
}
}
/**
* Get debug events retention period options.
*
* @since 3.6.0
*
* @return array
*/
protected function get_debug_events_retention_period_options() {
$options = [
604800 => esc_html__( '1 Week', 'wp-mail-smtp' ),
2628000 => esc_html__( '1 Month', 'wp-mail-smtp' ),
7885000 => esc_html__( '3 Months', 'wp-mail-smtp' ),
15770000 => esc_html__( '6 Months', 'wp-mail-smtp' ),
31540000 => esc_html__( '1 Year', 'wp-mail-smtp' ),
];
$debug_event_retention_period = $this->options->get( 'debug_events', 'retention_period' );
// Check if defined value already in list and add it if not.
if (
! empty( $debug_event_retention_period ) &&
! isset( $options[ $debug_event_retention_period ] )
) {
$debug_event_retention_period_days = floor( $debug_event_retention_period / DAY_IN_SECONDS );
$options[ $debug_event_retention_period ] = sprintf(
/* translators: %d - days count. */
_n( '%d Day', '%d Days', $debug_event_retention_period_days, 'wp-mail-smtp' ),
$debug_event_retention_period_days
);
ksort( $options );
}
/**
* Filter debug events retention period options.
*
* @since 3.6.0
*
* @param array $options Debug Events retention period options.
* Option key in seconds.
*/
return apply_filters(
'wp_mail_smtp_admin_pages_debug_events_tab_get_debug_events_retention_period_options',
$options
);
}
}

View File

@@ -0,0 +1,55 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\ParentPageAbstract;
/**
* Class EmailReports.
*
* @since 3.0.0
*/
class EmailReports extends ParentPageAbstract {
/**
* Page default tab slug.
*
* @since 3.0.0
*
* @var string
*/
protected $default_tab = 'reports';
/**
* Slug of a page.
*
* @since 3.0.0
*
* @var string
*/
protected $slug = 'reports';
/**
* Link label of a page.
*
* @since 3.0.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Email Reports', 'wp-mail-smtp' );
}
/**
* Title of a page.
*
* @since 3.0.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
}

View File

@@ -0,0 +1,180 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\PageAbstract;
/**
* Class EmailTrackingReportsTab is a placeholder for Pro email tracking reports.
* Displays product education.
*
* @since 3.0.0
*/
class EmailReportsTab extends PageAbstract {
/**
* Part of the slug of a tab.
*
* @since 3.0.0
*
* @var string
*/
protected $slug = 'reports';
/**
* Tab priority.
*
* @since 3.0.0
*
* @var int
*/
protected $priority = 10;
/**
* Link label of a tab.
*
* @since 3.0.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Email Reports', 'wp-mail-smtp' );
}
/**
* Title of a tab.
*
* @since 3.0.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
/**
* Register hooks.
*
* @since 3.0.0
*/
public function hooks() {
add_action( 'wp_mail_smtp_admin_area_enqueue_assets', [ $this, 'enqueue_assets' ] );
}
/**
* Enqueue required JS and CSS.
*
* @since 3.0.0
*/
public function enqueue_assets() {
wp_enqueue_style(
'wp-mail-smtp-admin-lity',
wp_mail_smtp()->assets_url . '/css/vendor/lity.min.css',
[],
'2.4.1'
);
wp_enqueue_script(
'wp-mail-smtp-admin-lity',
wp_mail_smtp()->assets_url . '/js/vendor/lity.min.js',
[],
'2.4.1',
false
);
}
/**
* Output HTML of the email reports education.
*
* @since 3.0.0
*/
public function display() {
$top_upgrade_button_url = wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'email-reports',
'content' => 'upgrade-to-wp-mail-smtp-pro-button-link-top',
]
);
$bottom_upgrade_button_url = wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'email-reports',
'content' => 'upgrade-to-wp-mail-smtp-pro-button-link',
]
);
$assets_url = wp_mail_smtp()->assets_url . '/images/email-reports/';
$screenshots = [
[
'url' => $assets_url . 'screenshot-01.png',
'url_thumbnail' => $assets_url . 'thumbnail-01.png',
'title' => __( 'Stats at a Glance', 'wp-mail-smtp' ),
],
[
'url' => $assets_url . 'screenshot-02.png',
'url_thumbnail' => $assets_url . 'thumbnail-02.png',
'title' => __( 'Detailed Stats by Subject Line', 'wp-mail-smtp' ),
],
[
'url' => $assets_url . 'screenshot-03.png',
'url_thumbnail' => $assets_url . 'thumbnail-03.png',
'title' => __( 'Weekly Email Report', 'wp-mail-smtp' ),
],
];
?>
<div id="wp-mail-smtp-email-reports-product-education" class="wp-mail-smtp-product-education">
<div class="wp-mail-smtp-product-education__row">
<p class="wp-mail-smtp-product-education__description">
<?php
esc_html_e( 'Email reports make it easy to track deliverability and engagement at-a-glance. Your open and click-through rates are grouped by subject line, making it easy to review the performance of campaigns or notifications. The report also displays Sent and Failed emails each week so you spot any issues quickly. When you upgrade, we\'ll also add an email report chart right in your WordPress dashboard.', 'wp-mail-smtp' );
?>
</p>
<a href="<?php echo esc_url( $top_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--top wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<div class="wp-mail-smtp-product-education__row">
<div class="wp-mail-smtp-product-education__screenshots wp-mail-smtp-product-education__screenshots--three">
<?php foreach ( $screenshots as $screenshot ) : ?>
<div>
<a href="<?php echo esc_url( $screenshot['url'] ); ?>" data-lity data-lity-desc="<?php echo esc_attr( $screenshot['title'] ); ?>">
<img src="<?php echo esc_url( $screenshot['url_thumbnail'] ); ?>" alt="<?php esc_attr( $screenshot['title'] ); ?>">
</a>
<span><?php echo esc_html( $screenshot['title'] ); ?></span>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="wp-mail-smtp-product-education__row">
<div class="wp-mail-smtp-product-education__list">
<h4><?php esc_html_e( 'Unlock these awesome reporting features:', 'wp-mail-smtp' ); ?></h4>
<div>
<ul>
<li><?php esc_html_e( 'Get weekly deliverability reports', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'View stats grouped by subject line', 'wp-mail-smtp' ); ?></li>
</ul>
<ul>
<li><?php esc_html_e( 'Track total emails sent each week', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'Measure open rate and click through rates', 'wp-mail-smtp' ); ?></li>
</ul>
<ul>
<li><?php esc_html_e( 'Spot failed emails quickly', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'See email report graphs in WordPress', 'wp-mail-smtp' ); ?></li>
</ul>
</div>
</div>
</div>
<a href="<?php echo esc_url( $bottom_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--bottom wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<?php
}
}

View File

@@ -0,0 +1,151 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\PageAbstract;
/**
* Class ExportTab is a placeholder for Pro email logs export.
* Displays product education.
*
* @since 2.9.0
*/
class ExportTab extends PageAbstract {
/**
* Part of the slug of a tab.
*
* @since 2.9.0
*
* @var string
*/
protected $slug = 'export';
/**
* Tab priority.
*
* @since 2.9.0
*
* @var int
*/
protected $priority = 20;
/**
* Link label of a tab.
*
* @since 2.9.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Export', 'wp-mail-smtp' );
}
/**
* Title of a tab.
*
* @since 2.9.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
/**
* Output HTML of the email logs export form preview.
*
* @since 2.9.0
*/
public function display() {
$top_upgrade_button_url = wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'tools-export',
'content' => 'upgrade-to-wp-mail-smtp-pro-button-top',
]
);
$bottom_upgrade_button_url = wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'tools-export',
'content' => 'upgrade-to-wp-mail-smtp-pro-button',
]
);
?>
<div id="wp-mail-smtp-tools-export-email-logs-product-education" class="wp-mail-smtp-product-education">
<div class="wp-mail-smtp-product-education__row">
<h4 class="wp-mail-smtp-product-education__heading">
<?php esc_html_e( 'Export Email Logs', 'wp-mail-smtp' ); ?>
</h4>
<p class="wp-mail-smtp-product-education__description">
<?php
esc_html_e( 'Easily export your logs to CSV or Excel. Filter the logs before you export and only download the data you need. This feature lets you easily create your own deliverability reports. You can also use the data in 3rd party dashboards to track deliverability along with your other website statistics.', 'wp-mail-smtp' );
?>
</p>
<a href="<?php echo esc_url( $top_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--top wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<div class="wp-mail-smtp-product-education__row wp-mail-smtp-product-education__row--inactive">
<section class="wp-clearfix">
<h5><?php esc_html_e( 'Export Type', 'wp-mail-smtp' ); ?></h5>
<label>
<input type="radio" checked><?php esc_html_e( 'Export in CSV (.csv)', 'wp-mail-smtp' ); ?>
</label>
<label>
<input type="radio"><?php esc_html_e( 'Export in Microsoft Excel (.xlsx)', 'wp-mail-smtp' ); ?>
</label>
<label>
<input type="radio"><?php esc_html_e( 'Export in EML (.eml)', 'wp-mail-smtp' ); ?>
</label>
</section>
<section class="wp-clearfix">
<h5><?php esc_html_e( 'Common Information', 'wp-mail-smtp' ); ?></h5>
<label><input type="checkbox" checked><?php esc_html_e( 'To Address', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox" checked><?php esc_html_e( 'From Address', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox" checked><?php esc_html_e( 'From Name', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox" checked><?php esc_html_e( 'Subject', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox" checked><?php esc_html_e( 'Body', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox" checked><?php esc_html_e( 'Created Date', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox" checked><?php esc_html_e( 'Number of Attachments', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox" checked><?php esc_html_e( 'Attachments', 'wp-mail-smtp' ); ?></label>
</section>
<section class="wp-clearfix">
<h5><?php esc_html_e( 'Additional Information', 'wp-mail-smtp' ); ?></h5>
<label><input type="checkbox"><?php esc_html_e( 'Status', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox"><?php esc_html_e( 'Carbon Copy (CC)', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox"><?php esc_html_e( 'Blind Carbon Copy (BCC)', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox"><?php esc_html_e( 'Headers', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox"><?php esc_html_e( 'Mailer', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox"><?php esc_html_e( 'Error Details', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox"><?php esc_html_e( 'Email log ID', 'wp-mail-smtp' ); ?></label>
<label><input type="checkbox"><?php esc_html_e( 'Source', 'wp-mail-smtp' ); ?></label>
</section>
<section class="wp-clearfix">
<h5><?php esc_html_e( 'Custom Date Range', 'wp-mail-smtp' ); ?></h5>
<input type="text" class="wp-mail-smtp-date-selector" placeholder="<?php esc_html_e( 'Select a date range', 'wp-mail-smtp' ); ?>">
</section>
<section class="wp-clearfix">
<h5><?php esc_html_e( 'Search', 'wp-mail-smtp' ); ?></h5>
<select class="wp-mail-smtp-search-box-field">
<option><?php esc_html_e( 'Email Addresses', 'wp-mail-smtp' ); ?></option>
</select>
<input type="text" class="wp-mail-smtp-search-box-term">
</section>
</div>
<a href="<?php echo esc_url( $bottom_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--bottom wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<?php
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\Area;
use WPMailSMTP\Admin\PageAbstract;
use WPMailSMTP\WP;
/**
* Class Logs
*/
class Logs extends PageAbstract {
/**
* Slug of a page.
*
* @since 1.5.0
*
* @var string
*/
protected $slug = 'logs';
/**
* Get the page/tab link.
*
* @since 1.5.0
* @since 2.1.0 Changed the URL to point to the email log settings tab.
*
* @return string
*/
public function get_link() {
return add_query_arg(
'tab',
$this->slug,
WP::admin_url( 'admin.php?page=' . Area::SLUG )
);
}
/**
* Link label of a tab.
*
* @since 1.5.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Email Log', 'wp-mail-smtp' );
}
/**
* Title of a tab.
*
* @since 1.5.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
/**
* Tab content.
*
* @since 2.1.0 Moved the display content to the email log settings tab.
*/
public function display() {}
}

View File

@@ -0,0 +1,204 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\PageAbstract;
use WPMailSMTP\Admin\ParentPageAbstract;
/**
* Class LogsTab is a placeholder for Lite users and redirects them to Email Log page.
*
* @since 1.6.0
*/
class LogsTab extends PageAbstract {
/**
* Part of the slug of a tab.
*
* @since 1.6.0
*
* @var string
*/
protected $slug = 'logs';
/**
* Constructor.
*
* @since 3.0.0
*
* @param ParentPageAbstract $parent_page Tab parent page.
*/
public function __construct( $parent_page = null ) {
parent::__construct( $parent_page );
$current_tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
if ( wp_mail_smtp()->get_admin()->is_admin_page() && $current_tab === 'logs' ) {
$this->hooks();
}
}
/**
* Link label of a tab.
*
* @since 1.6.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Email Log', 'wp-mail-smtp' );
}
/**
* Title of a tab.
*
* @since 1.6.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
/**
* Register hooks.
*
* @since 3.0.0
*/
public function hooks() {
add_action( 'wp_mail_smtp_admin_area_enqueue_assets', [ $this, 'enqueue_assets' ] );
}
/**
* Enqueue required JS and CSS.
*
* @since 3.0.0
*/
public function enqueue_assets() {
wp_enqueue_style(
'wp-mail-smtp-admin-lity',
wp_mail_smtp()->assets_url . '/css/vendor/lity.min.css',
[],
'2.4.1'
);
wp_enqueue_script(
'wp-mail-smtp-admin-lity',
wp_mail_smtp()->assets_url . '/js/vendor/lity.min.js',
[],
'2.4.1',
false
);
}
/**
* Display the upsell content for the Email Log feature.
*
* @since 1.6.0
* @since 2.1.0 Moved the display content from the email log page (WP admin menu "Email Log" page).
*/
public function display() {
$top_upgrade_button_url = add_query_arg(
[ 'discount' => 'LITEUPGRADE' ],
wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'logs',
'content' => 'Upgrade to Pro Button Top',
]
)
);
$bottom_upgrade_button_url = add_query_arg(
[ 'discount' => 'LITEUPGRADE' ],
wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'logs',
'content' => 'Upgrade to Pro Button',
]
)
);
$assets_url = wp_mail_smtp()->assets_url . '/images/logs/';
$screenshots = [
[
'url' => $assets_url . 'archive.png',
'url_thumbnail' => $assets_url . 'archive-thumbnail.png',
'title' => __( 'Email Log Index', 'wp-mail-smtp' ),
],
[
'url' => $assets_url . 'single.png',
'url_thumbnail' => $assets_url . 'single-thumbnail.png',
'title' => __( 'Individual Email Log', 'wp-mail-smtp' ),
],
];
?>
<div id="wp-mail-smtp-email-logs-product-education" class="wp-mail-smtp-product-education">
<div class="wp-mail-smtp-product-education__row">
<h4 class="wp-mail-smtp-product-education__heading">
<?php esc_html_e( 'Email Log', 'wp-mail-smtp' ); ?>
</h4>
<p class="wp-mail-smtp-product-education__description">
<?php
esc_html_e( 'Email logging makes it easy to save details about all of the emails sent from your WordPress site. You can search and filter the email log to find specific messages and check the color-coded delivery status. Email logging also allows you to resend emails, save attachments, and export your logs in different formats.', 'wp-mail-smtp' );
?>
</p>
<a href="<?php echo esc_url( $top_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--top wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<div class="wp-mail-smtp-product-education__row">
<div class="wp-mail-smtp-product-education__screenshots wp-mail-smtp-product-education__screenshots--two">
<?php foreach ( $screenshots as $screenshot ) : ?>
<div>
<a href="<?php echo esc_url( $screenshot['url'] ); ?>" data-lity data-lity-desc="<?php echo esc_attr( $screenshot['title'] ); ?>">
<img src="<?php echo esc_url( $screenshot['url_thumbnail'] ); ?>" alt="<?php esc_attr( $screenshot['title'] ); ?>">
</a>
<span><?php echo esc_html( $screenshot['title'] ); ?></span>
</div>
<?php endforeach; ?>
</div>
</div>
<div class="wp-mail-smtp-product-education__row">
<div class="wp-mail-smtp-product-education__list">
<h4><?php esc_html_e( 'Unlock these awesome logging features:', 'wp-mail-smtp' ); ?></h4>
<div>
<ul>
<li><?php esc_html_e( 'Save detailed email headers', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'See sent and failed emails', 'wp-mail-smtp' ); ?></li>
</ul>
<ul>
<li><?php esc_html_e( 'Resend emails and attachments', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'Track email opens and clicks', 'wp-mail-smtp' ); ?></li>
</ul>
<ul>
<li><?php esc_html_e( 'Print email logs or save as PDF', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'Export logs to CSV, XLSX, or EML', 'wp-mail-smtp' ); ?></li>
</ul>
</div>
</div>
</div>
<a href="<?php echo esc_url( $bottom_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--bottom wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<?php
}
/**
* Not used as we are simply redirecting users.
*
* @since 1.6.0
*
* @param array $data Post data specific for the plugin.
*/
public function process_post( $data ) { }
}

View File

@@ -0,0 +1,402 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\Area;
use WPMailSMTP\Admin\PageAbstract;
use WPMailSMTP\Helpers\UI;
use WPMailSMTP\Options;
use WPMailSMTP\UsageTracking\UsageTracking;
use WPMailSMTP\Reports\Emails\Summary as SummaryReportEmail;
use WPMailSMTP\Tasks\Reports\SummaryEmailTask as SummaryReportEmailTask;
use WPMailSMTP\WP;
/**
* Class MiscTab is part of Area, displays different plugin-related settings of the plugin (not related to emails).
*
* @since 1.0.0
*/
class MiscTab extends PageAbstract {
/**
* Slug of a tab.
*
* @since 1.0.0
*
* @var string
*/
protected $slug = 'misc';
/**
* Link label of a tab.
*
* @since 1.0.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Misc', 'wp-mail-smtp' );
}
/**
* Title of a tab.
*
* @since 1.0.0
*
* @return string
*/
public function get_title() {
return esc_html__( 'Miscellaneous', 'wp-mail-smtp' );
}
/**
* Output HTML of the misc settings.
*
* @since 1.0.0
*/
public function display() {
$options = Options::init();
?>
<form method="POST" action="">
<?php $this->wp_nonce_field(); ?>
<!-- Section Title -->
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading wp-mail-smtp-section-heading--has-divider no-desc">
<div class="wp-mail-smtp-setting-field">
<h2><?php echo $this->get_title(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></h2>
</div>
</div>
<!-- Do not send -->
<div id="wp-mail-smtp-setting-row-do_not_send" class="wp-mail-smtp-setting-row wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-do_not_send">
<?php esc_html_e( 'Do Not Send', 'wp-mail-smtp' ); ?>
</label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[general][do_not_send]',
'id' => 'wp-mail-smtp-setting-do_not_send',
'value' => 'true',
'checked' => (bool) $options->get( 'general', 'do_not_send' ),
'disabled' => $options->is_const_defined( 'general', 'do_not_send' ),
]
);
?>
<p class="desc">
<?php esc_html_e( 'Stop sending all emails', 'wp-mail-smtp' ); ?>
</p>
<p class="desc">
<?php
printf(
wp_kses(
__( 'Some plugins, like BuddyPress and Events Manager, are using their own email delivery solutions. By default, this option does not block their emails, as those plugins do not use default <code>wp_mail()</code> function to send emails.', 'wp-mail-smtp' ),
[
'code' => [],
]
)
);
?>
<br>
<?php esc_html_e( 'You will need to consult with their documentation to switch them to use default WordPress email delivery.', 'wp-mail-smtp' ); ?>
<br>
<?php esc_html_e( 'Test emails are allowed to be sent, regardless of this option.', 'wp-mail-smtp' ); ?>
<br>
<?php
if ( $options->is_const_defined( 'general', 'do_not_send' ) ) {
echo $options->get_const_set_message( 'WPMS_DO_NOT_SEND' ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
} else {
printf(
wp_kses( /* translators: %s - The URL to the constants support article. */
__( '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' => [],
],
]
),
// phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-secure-smtp-settings-by-using-constants/', [ 'medium' => 'misc-settings', 'content' => 'Do not send setting description - support article' ] ) )
);
}
?>
</p>
</div>
</div>
<!-- Hide Announcements -->
<div id="wp-mail-smtp-setting-row-am_notifications_hidden" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-am_notifications_hidden">
<?php esc_html_e( 'Hide Announcements', 'wp-mail-smtp' ); ?>
</label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[general][am_notifications_hidden]',
'id' => 'wp-mail-smtp-setting-am_notifications_hidden',
'value' => 'true',
'checked' => (bool) $options->get( 'general', 'am_notifications_hidden' ),
]
);
?>
<p class="desc">
<?php esc_html_e( 'Hide plugin announcements and update details.', 'wp-mail-smtp' ); ?>
</p>
</div>
</div>
<!-- Hide Email Delivery Errors -->
<div id="wp-mail-smtp-setting-row-email_delivery_errors_hidden"
class="wp-mail-smtp-setting-row wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-email_delivery_errors_hidden">
<?php esc_html_e( 'Hide Email Delivery Errors', 'wp-mail-smtp' ); ?>
</label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
$is_hard_disabled = has_filter( 'wp_mail_smtp_admin_is_error_delivery_notice_enabled' ) && ! wp_mail_smtp()->get_admin()->is_error_delivery_notice_enabled();
?>
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[general][email_delivery_errors_hidden]',
'id' => 'wp-mail-smtp-setting-email_delivery_errors_hidden',
'value' => 'true',
'checked' => $is_hard_disabled || (bool) $options->get( 'general', 'email_delivery_errors_hidden' ),
'disabled' => $is_hard_disabled,
]
);
?>
<p class="desc">
<?php esc_html_e( 'Hide warnings alerting of email delivery errors.', 'wp-mail-smtp' ); ?>
</p>
<?php if ( $is_hard_disabled ) : ?>
<p class="desc">
<?php
printf( /* translators: %s - filter that was used to disabled. */
esc_html__( 'Email Delivery Errors were disabled using a %s filter.', 'wp-mail-smtp' ),
'<code>wp_mail_smtp_admin_is_error_delivery_notice_enabled</code>'
);
?>
</p>
<?php else : ?>
<p class="desc">
<?php
echo wp_kses(
__( '<strong>This is not recommended</strong> and should only be done for staging or development sites.', 'wp-mail-smtp' ),
[
'strong' => [],
]
);
?>
</p>
<?php endif; ?>
</div>
</div>
<!-- Hide Dashboard Widget -->
<div id="wp-mail-smtp-setting-row-dashboard_widget_hidden" class="wp-mail-smtp-setting-row wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-dashboard_widget_hidden">
<?php esc_html_e( 'Hide Dashboard Widget', 'wp-mail-smtp' ); ?>
</label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[general][dashboard_widget_hidden]',
'id' => 'wp-mail-smtp-setting-dashboard_widget_hidden',
'value' => 'true',
'checked' => (bool) $options->get( 'general', 'dashboard_widget_hidden' ),
]
);
?>
<p class="desc">
<?php esc_html_e( 'Hide the WP Mail SMTP Dashboard Widget.', 'wp-mail-smtp' ); ?>
</p>
</div>
</div>
<?php if ( apply_filters( 'wp_mail_smtp_admin_pages_misc_tab_show_usage_tracking_setting', true ) ) : ?>
<!-- Usage Tracking -->
<div id="wp-mail-smtp-setting-row-usage-tracking" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-usage-tracking">
<?php esc_html_e( 'Allow Usage Tracking', 'wp-mail-smtp' ); ?>
</label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[general][' . UsageTracking::SETTINGS_SLUG . ']',
'id' => 'wp-mail-smtp-setting-usage-tracking',
'value' => 'true',
'checked' => (bool) $options->get( 'general', UsageTracking::SETTINGS_SLUG ),
]
);
?>
<p class="desc">
<?php esc_html_e( 'By allowing us to track usage data we can better help you because we know with which WordPress configurations, themes and plugins we should test.', 'wp-mail-smtp' ); ?>
</p>
</div>
</div>
<?php endif; ?>
<!-- Summary Report Email -->
<div id="wp-mail-smtp-setting-row-summary-report-email" class="wp-mail-smtp-setting-row wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-summary-report-email">
<?php esc_html_e( 'Disable Email Summaries', 'wp-mail-smtp' ); ?>
</label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[general][' . SummaryReportEmail::SETTINGS_SLUG . ']',
'id' => 'wp-mail-smtp-setting-summary-report-email',
'value' => 'true',
'checked' => (bool) SummaryReportEmail::is_disabled(),
'disabled' => (
$options->is_const_defined( 'general', SummaryReportEmail::SETTINGS_SLUG ) ||
( wp_mail_smtp()->is_pro() && empty( Options::init()->get( 'logs', 'enabled' ) ) )
),
]
);
?>
<p class="desc">
<?php esc_html_e( 'Disable Email Summaries weekly delivery.', 'wp-mail-smtp' ); ?>
<?php
if ( wp_mail_smtp()->is_pro() && empty( Options::init()->get( 'logs', 'enabled' ) ) ) {
echo wp_kses(
sprintf( /* translators: %s - Email Log settings url. */
__( 'Please enable <a href="%s">Email Logging</a> first, before this setting can be configured.', 'wp-mail-smtp' ),
esc_url( wp_mail_smtp()->get_admin()->get_admin_page_url( Area::SLUG . '&tab=logs' ) )
),
[
'a' => [
'href' => [],
],
]
);
} else {
printf(
'<a href="%1$s" target="_blank">%2$s</a>',
esc_url( SummaryReportEmail::get_preview_link() ),
esc_html__( 'View Email Summary Example', 'wp-mail-smtp' )
);
}
if ( $options->is_const_defined( 'general', SummaryReportEmail::SETTINGS_SLUG ) ) {
echo '<br>' . $options->get_const_set_message( 'WPMS_SUMMARY_REPORT_EMAIL_DISABLED' ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
?>
</p>
</div>
</div>
<!-- Uninstall -->
<div id="wp-mail-smtp-setting-row-uninstall" class="wp-mail-smtp-setting-row wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-uninstall">
<?php esc_html_e( 'Uninstall WP Mail SMTP', 'wp-mail-smtp' ); ?>
</label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[general][uninstall]',
'id' => 'wp-mail-smtp-setting-uninstall',
'value' => 'true',
'checked' => (bool) $options->get( 'general', 'uninstall' ),
]
);
?>
<p class="desc">
<?php esc_html_e( 'Remove ALL WP Mail SMTP data upon plugin deletion.', 'wp-mail-smtp' ); ?>
</p>
<p class="desc wp-mail-smtp-danger">
<?php esc_html_e( 'All settings will be unrecoverable.', 'wp-mail-smtp' ); ?>
</p>
</div>
</div>
<?php $this->display_save_btn(); ?>
</form>
<?php
}
/**
* Process tab form submission ($_POST).
*
* @since 1.0.0
* @since 2.2.0 Fixed checkbox saving and use the correct merge to prevent breaking other 'general' checkboxes.
*
* @param array $data Tab data specific for the plugin ($_POST).
*/
public function process_post( $data ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
$this->check_admin_referer();
$options = Options::init();
// Unchecked checkboxes doesn't exist in $_POST, so we need to ensure we actually have them in data to save.
if ( empty( $data['general']['do_not_send'] ) ) {
$data['general']['do_not_send'] = false;
}
if ( empty( $data['general']['am_notifications_hidden'] ) ) {
$data['general']['am_notifications_hidden'] = false;
}
if ( empty( $data['general']['email_delivery_errors_hidden'] ) ) {
$data['general']['email_delivery_errors_hidden'] = false;
}
if ( empty( $data['general']['dashboard_widget_hidden'] ) ) {
$data['general']['dashboard_widget_hidden'] = false;
}
if ( empty( $data['general']['uninstall'] ) ) {
$data['general']['uninstall'] = false;
}
if ( empty( $data['general'][ UsageTracking::SETTINGS_SLUG ] ) ) {
$data['general'][ UsageTracking::SETTINGS_SLUG ] = false;
}
if ( empty( $data['general'][ SummaryReportEmail::SETTINGS_SLUG ] ) ) {
$data['general'][ SummaryReportEmail::SETTINGS_SLUG ] = false;
}
$is_summary_report_email_opt_changed = $options->is_option_changed(
$options->parse_boolean( $data['general'][ SummaryReportEmail::SETTINGS_SLUG ] ),
'general',
SummaryReportEmail::SETTINGS_SLUG
);
// If this option was changed, cancel summary report email task.
if ( $is_summary_report_email_opt_changed ) {
( new SummaryReportEmailTask() )->cancel();
}
// All the sanitization is done there.
$options->set( $data, false, false );
WP::add_admin_notice(
esc_html__( 'Settings were successfully saved.', 'wp-mail-smtp' ),
WP::ADMIN_NOTICE_SUCCESS
);
}
}

View File

@@ -0,0 +1,444 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\ConnectionSettings;
use WPMailSMTP\Admin\PageAbstract;
use WPMailSMTP\Admin\SetupWizard;
use WPMailSMTP\Options;
use WPMailSMTP\WP;
/**
* Class SettingsTab is part of Area, displays general settings of the plugin.
*
* @since 1.0.0
*/
class SettingsTab extends PageAbstract {
/**
* Settings constructor.
*
* @since 1.5.0
*/
public function __construct() {
parent::__construct();
add_action( 'wp_mail_smtp_admin_pages_settings_license_key', array( __CLASS__, 'display_license_key_field_content' ) );
}
/**
* @var string Slug of a tab.
*/
protected $slug = 'settings';
/**
* @inheritdoc
*/
public function get_label() {
return esc_html__( 'General', 'wp-mail-smtp' );
}
/**
* @inheritdoc
*/
public function get_title() {
return $this->get_label();
}
/**
* @inheritdoc
*/
public function display() {
$options = Options::init();
?>
<form method="POST" action="" autocomplete="off" class="wp-mail-smtp-connection-settings-form">
<?php $this->wp_nonce_field(); ?>
<?php ob_start(); ?>
<!-- License Section Title -->
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading" id="wp-mail-smtp-setting-row-license-heading">
<div class="wp-mail-smtp-setting-field">
<h2><?php esc_html_e( 'License', 'wp-mail-smtp' ); ?></h2>
<p class="desc">
<?php esc_html_e( 'Your license key provides access to updates and support.', 'wp-mail-smtp' ); ?>
</p>
</div>
</div>
<!-- License Key -->
<div id="wp-mail-smtp-setting-row-license_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-license_key wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-license_key"><?php esc_html_e( 'License Key', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php do_action( 'wp_mail_smtp_admin_pages_settings_license_key', $options ); ?>
</div>
</div>
<!-- Mail Section Title -->
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading no-desc">
<div class="wp-mail-smtp-setting-field">
<h2><?php esc_html_e( 'Primary Connection', 'wp-mail-smtp' ); ?></h2>
</div>
</div>
<?php if ( ! is_network_admin() ) : ?>
<!-- Setup Wizard button -->
<div id="wp-mail-smtp-setting-row-setup-wizard-button" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-email wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-from_email"><?php esc_html_e( 'Setup Wizard', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<a href="<?php echo esc_url( SetupWizard::get_site_url() ); ?>" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-blueish">
<?php esc_html_e( 'Launch Setup Wizard', 'wp-mail-smtp' ); ?>
</a>
<p class="desc">
<?php esc_html_e( 'We\'ll guide you through each step needed to get WP Mail SMTP fully set up on your site.', 'wp-mail-smtp' ); ?>
</p>
</div>
</div>
<?php endif; ?>
<?php
$connection = wp_mail_smtp()->get_connections_manager()->get_primary_connection();
$connection_settings = new ConnectionSettings( $connection );
// Display connection settings.
$connection_settings->display();
?>
<?php $this->display_backup_connection_education(); ?>
<?php
$settings_content = apply_filters( 'wp_mail_smtp_admin_settings_tab_display', ob_get_clean() );
echo $settings_content; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
?>
<?php $this->display_save_btn(); ?>
</form>
<?php
$this->display_wpforms();
$this->display_pro_banner();
}
/**
* License key text for a Lite version of the plugin.
*
* @since 1.5.0
*
* @param Options $options
*/
public static function display_license_key_field_content( $options ) {
?>
<p><?php esc_html_e( 'You\'re using WP Mail SMTP Lite - no license needed. Enjoy!', 'wp-mail-smtp' ); ?> 🙂</p>
<p>
<?php
printf(
wp_kses( /* translators: %s - WPMailSMTP.com upgrade URL. */
__( 'To unlock more features, consider <strong><a href="%s" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-upgrade-modal">upgrading to PRO</a></strong>.', 'wp-mail-smtp' ),
array(
'a' => array(
'href' => array(),
'class' => array(),
'target' => array(),
'rel' => array(),
),
'strong' => array(),
)
),
esc_url( wp_mail_smtp()->get_upgrade_link( 'general-license-key' ) )
);
?>
</p>
<p class="desc">
<?php
printf(
wp_kses( /* Translators: %s - discount value $50 */
__( 'As a valued WP Mail SMTP Lite user you receive <strong>%s off</strong>, automatically applied at checkout!', 'wp-mail-smtp' ),
array(
'strong' => array(),
'br' => array(),
)
),
'$50'
);
?>
</p>
<hr>
<p>
<?php esc_html_e( 'Already purchased? Simply enter your license key below to connect with WP Mail SMTP Pro!', 'wp-mail-smtp' ); ?>
</p>
<p>
<input type="password" id="wp-mail-smtp-setting-upgrade-license-key" class="wp-mail-smtp-not-form-input" placeholder="<?php esc_attr_e( 'Paste license key here', 'wp-mail-smtp' ); ?>" value="" />
<button type="button" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange" id="wp-mail-smtp-setting-upgrade-license-button">
<?php esc_attr_e( 'Connect', 'wp-mail-smtp' ); ?>
</button>
</p>
<?php
}
/**
* Display a WPForms related message.
*
* @since 1.3.0
* @since 1.4.0 Display only to site admins.
* @since 1.5.0 Do nothing.
*/
protected function display_wpforms() {
/*
* Used to have this check:
*
* $is_dismissed = get_user_meta( get_current_user_id(), 'wp_mail_smtp_wpforms_dismissed', true );
*/
}
/**
* Display WP Mail SMTP Pro upgrade banner.
*
* @since 1.5.0
*/
protected function display_pro_banner() {
// Display only to site admins. Only site admins can install plugins.
if ( ! is_super_admin() ) {
return;
}
// Do not display if WP Mail SMTP Pro already installed.
if ( wp_mail_smtp()->is_pro() ) {
return;
}
$is_dismissed = get_user_meta( get_current_user_id(), 'wp_mail_smtp_pro_banner_dismissed', true );
// Do not display if user dismissed.
if ( (bool) $is_dismissed === true ) {
return;
}
?>
<div id="wp-mail-smtp-pro-banner">
<span class="wp-mail-smtp-pro-banner-dismiss">
<button id="wp-mail-smtp-pro-banner-dismiss">
<span class="dashicons dashicons-dismiss"></span>
</button>
</span>
<h2>
<?php esc_html_e( 'Get WP Mail SMTP Pro and Unlock all the Powerful Features', 'wp-mail-smtp' ); ?>
</h2>
<p>
<?php esc_html_e( 'Thanks for being a loyal WP Mail SMTP user. Upgrade to WP Mail SMTP Pro to unlock more awesome features and experience why WP Mail SMTP is the most popular SMTP plugin.', 'wp-mail-smtp' ); ?>
</p>
<p>
<?php esc_html_e( 'We know that you will truly love WP Mail SMTP. It\'s used by over 3,000,000 websites.', 'wp-mail-smtp' ); ?>
</p>
<p><strong><?php esc_html_e( 'Pro Features:', 'wp-mail-smtp' ); ?></strong></p>
<div class="benefits">
<ul>
<li><?php esc_html_e( 'Email Logging - keep track of every email sent from your site', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'Alerts - get notified when your emails fail (via email, slack or SMS)', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'Backup Connection - send emails even if your primary connection fails', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'Smart Routing - define conditions for your email sending', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'Amazon SES - harness the power of AWS', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'Outlook - send emails using your Outlook or Microsoft 365 account', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'Zoho Mail - use your Zoho Mail account to send emails', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'Multisite Support - network settings for easy management', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'Manage Notifications - control which emails your site sends', 'wp-mail-smtp' ); ?></li>
<li><?php esc_html_e( 'Access to our world class support team', 'wp-mail-smtp' ); ?></li>
</ul>
<ul>
<li><?php esc_html_e( 'White Glove Setup - sit back and relax while we handle everything for you', 'wp-mail-smtp' ); ?></li>
<li class="arrow-right"><?php esc_html_e( 'Install & Setup WP Mail SMTP Pro plugin', 'wp-mail-smtp' ); ?></li>
<li class="arrow-right"><?php esc_html_e( 'Configure SendLayer, SMTP.com or Brevo service', 'wp-mail-smtp' ); ?></li>
<li class="arrow-right"><?php esc_html_e( 'Set up domain name verification (DNS)', 'wp-mail-smtp' ); ?></li>
<li class="arrow-right"><?php esc_html_e( 'Test and verify email delivery', 'wp-mail-smtp' ); ?></li>
</ul>
</div>
<p>
<?php
printf(
wp_kses( /* translators: %s - WPMailSMTP.com URL. */
__( '<a href="%s" target="_blank" rel="noopener noreferrer">Get WP Mail SMTP Pro Today and Unlock all the Powerful Features &raquo;</a>', 'wp-mail-smtp' ),
array(
'a' => array(
'href' => array(),
'target' => array(),
'rel' => array(),
),
'strong' => array(),
)
),
esc_url( wp_mail_smtp()->get_upgrade_link( 'general-cta' ) )
);
?>
</p>
<p>
<?php
printf(
wp_kses( /* Translators: %s - discount value $50. */
__( '<strong>Bonus:</strong> WP Mail SMTP users get <span class="price-off">%s off regular price</span>, automatically applied at checkout.', 'wp-mail-smtp' ),
array(
'strong' => array(),
'span' => array(
'class' => array(),
),
)
),
'$50'
);
?>
</p>
</div>
<?php
}
/**
* Display backup connection education section.
*
* @since 3.7.0
*/
private function display_backup_connection_education() {
if ( wp_mail_smtp()->is_pro() ) {
return;
}
$upgrade_link_url = wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'Backup Connection Settings',
'content' => 'Upgrade to WP Mail SMTP Pro Link',
]
);
?>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading">
<div class="wp-mail-smtp-setting-field">
<h4 class="wp-mail-smtp-product-education__heading">
<?php esc_html_e( 'Backup Connection', 'wp-mail-smtp' ); ?>
</h4>
<p class="wp-mail-smtp-product-education__description">
<?php
echo wp_kses(
sprintf( /* translators: %s - WPMailSMTP.com Upgrade page URL. */
__( 'Dont worry about losing emails. Add an additional connection, then set it as your Backup Connection. Emails that fail to send with the Primary Connection will be sent via the selected Backup Connection. <a href="%s" target="_blank" rel="noopener noreferrer">Upgrade to WP Mail SMTP Pro!</a>', 'wp-mail-smtp' ),
esc_url( $upgrade_link_url )
),
[
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
);
?>
</p>
</div>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label>
<?php esc_html_e( 'Backup Connection', 'wp-mail-smtp' ); ?>
</label>
</div>
<div class="wp-mail-smtp-setting-field">
<div class="wp-mail-smtp-connection-selector">
<label>
<input type="radio" checked/>
<span><?php esc_attr_e( 'None', 'wp-mail-smtp' ); ?></span>
</label>
</div>
<p class="desc">
<?php
echo wp_kses(
sprintf( /* translators: %s - Smart routing settings page url. */
__( 'Once you add an <a href="%s">additional connection</a>, you can select it here.', 'wp-mail-smtp' ),
add_query_arg(
[
'tab' => 'connections',
],
wp_mail_smtp()->get_admin()->get_admin_page_url()
)
),
[
'a' => [
'href' => [],
'target' => [],
'rel' => [],
],
]
);
?>
</p>
</div>
</div>
<?php
}
/**
* Process tab form submission ($_POST ).
*
* @since 1.0.0
*
* @param array $data Post data specific for the plugin.
*/
public function process_post( $data ) {
$this->check_admin_referer();
$connection = wp_mail_smtp()->get_connections_manager()->get_primary_connection();
$connection_settings = new ConnectionSettings( $connection );
$old_data = $connection->get_options()->get_all();
$data = $connection_settings->process( $data, $old_data );
/**
* Filters mail settings before save.
*
* @since 2.2.1
*
* @param array $data Settings data.
*/
$data = apply_filters( 'wp_mail_smtp_settings_tab_process_post', $data );
// All the sanitization is done in Options class.
Options::init()->set( $data, false, false );
$connection_settings->post_process( $data, $old_data );
if ( $connection_settings->get_scroll_to() !== false ) {
// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotValidated
wp_safe_redirect( sanitize_text_field( wp_unslash( $_POST['_wp_http_referer'] ) ) . $connection_settings->get_scroll_to() );
exit;
}
WP::add_admin_notice(
esc_html__( 'Settings were successfully saved.', 'wp-mail-smtp' ),
WP::ADMIN_NOTICE_SUCCESS
);
}
}

View File

@@ -0,0 +1,313 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\PageAbstract;
use WPMailSMTP\Helpers\UI;
use WPMailSMTP\WP;
/**
* Class SmartRoutingTab is a placeholder for Pro smart routing feature.
* Displays product education.
*
* @since 3.7.0
*/
class SmartRoutingTab extends PageAbstract {
/**
* Part of the slug of a tab.
*
* @since 3.7.0
*
* @var string
*/
protected $slug = 'routing';
/**
* Constructor.
*
* @since 3.7.0
*
* @param PageAbstract $parent_page Parent page object.
*/
public function __construct( $parent_page = null ) {
parent::__construct( $parent_page );
if ( wp_mail_smtp()->get_admin()->get_current_tab() === $this->slug && ! wp_mail_smtp()->is_pro() ) {
$this->hooks();
}
}
/**
* Link label of a tab.
*
* @since 3.7.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Smart Routing', 'wp-mail-smtp' );
}
/**
* Register hooks.
*
* @since 3.7.0
*/
public function hooks() {
add_action( 'wp_mail_smtp_admin_area_enqueue_assets', [ $this, 'enqueue_assets' ] );
}
/**
* Enqueue required JS and CSS.
*
* @since 3.7.0
*/
public function enqueue_assets() {
wp_enqueue_style(
'wp-mail-smtp-smart-routing',
wp_mail_smtp()->plugin_url . '/assets/css/smtp-smart-routing.min.css',
[],
WPMS_PLUGIN_VER
);
}
/**
* Output HTML of smart routing education.
*
* @since 3.7.0
*/
public function display() {
$top_upgrade_button_url = wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'Smart Routing Settings',
'content' => 'Upgrade to WP Mail SMTP Pro Button Top',
]
);
$bottom_upgrade_button_url = wp_mail_smtp()->get_upgrade_link(
[
'medium' => 'Smart Routing Settings',
'content' => 'Upgrade to WP Mail SMTP Pro Button',
]
);
?>
<div id="wp-mail-smtp-smart-routing-product-education" class="wp-mail-smtp-product-education">
<div class="wp-mail-smtp-product-education__row wp-mail-smtp-product-education__row--no-border">
<h4 class="wp-mail-smtp-product-education__heading">
<?php esc_html_e( 'Smart Routing', 'wp-mail-smtp' ); ?>
</h4>
<p class="wp-mail-smtp-product-education__description">
<?php
esc_html_e( 'Send emails from different additional connections based on your configured conditions. Emails that do not match any of the conditions below will be sent via your Primary Connection.', 'wp-mail-smtp' );
?>
</p>
<a href="<?php echo esc_url( $top_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--top wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<div class="wp-mail-smtp-product-education__row wp-mail-smtp-product-education__row--inactive wp-mail-smtp-product-education__row--no-border wp-mail-smtp-product-education__row--no-padding wp-mail-smtp-product-education__row--full-width">
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-no-border">
<?php
UI::toggle(
[
'label' => esc_html__( 'Enable Smart Routing', 'wp-mail-smtp' ),
'class' => 'wp-mail-smtp-smart-routing-toggle',
'checked' => true,
]
);
?>
</div>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-no-border wp-mail-smtp-setting-row-no-padding">
<div class="wp-mail-smtp-smart-routing-routes">
<div class="wp-mail-smtp-smart-routing-route">
<div class="wp-mail-smtp-smart-routing-route__header">
<span><?php esc_html_e( 'Send with', 'wp-mail-smtp' ); ?></span>
<select class="wp-mail-smtp-smart-routing-route__connection">
<option><?php esc_html_e( 'WooCommerce Emails (SendLayer)', 'wp-mail-smtp' ); ?></option>
</select>
<span><?php esc_html_e( 'if the following conditions are met...', 'wp-mail-smtp' ); ?></span>
<div class="wp-mail-smtp-smart-routing-route__actions">
<div class="wp-mail-smtp-smart-routing-route__order">
<button class="wp-mail-smtp-smart-routing-route__order-btn wp-mail-smtp-smart-routing-route__order-btn--up">
<img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/icons/arrow-up.svg' ); ?>" alt="<?php esc_attr_e( 'Arrow Up', 'wp-mail-smtp' ); ?>">
</button>
<button class="wp-mail-smtp-smart-routing-route__order-btn wp-mail-smtp-smart-routing-route__order-btn--down">
<img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/icons/arrow-up.svg' ); ?>" alt="<?php esc_attr_e( 'Arrow Down', 'wp-mail-smtp' ); ?>">
</button>
</div>
<button class="wp-mail-smtp-smart-routing-route__delete">
<i class="dashicons dashicons-trash"></i>
</button>
</div>
</div>
<div class="wp-mail-smtp-smart-routing-route__main">
<div class="wp-mail-smtp-conditional">
<div class="wp-mail-smtp-conditional__group">
<table>
<tbody>
<tr class="wp-mail-smtp-conditional__row">
<td class="wp-mail-smtp-conditional__property-col">
<select>
<option><?php esc_html_e( 'Subject', 'wp-mail-smtp' ); ?></option>
</select>
</td>
<td class="wp-mail-smtp-conditional__operator-col">
<select class="wp-mail-smtp-conditional__operator">
<option><?php esc_html_e( 'Contains', 'wp-mail-smtp' ); ?></option>
</select>
</td>
<td class="wp-mail-smtp-conditional__value-col">
<input type="text" value="<?php esc_html_e( 'Order', 'wp-mail-smtp' ); ?>" class="wp-mail-smtp-conditional__value">
</td>
<td class="wp-mail-smtp-conditional__actions">
<button class="wp-mail-smtp-conditional__add-rule wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-grey">
<?php esc_html_e( 'And', 'wp-mail-smtp' ); ?>
</button>
<button class="wp-mail-smtp-conditional__delete-rule">
<i class="dashicons dashicons-trash" aria-hidden="true"></i>
</button>
</td>
</tr>
<tr class="wp-mail-smtp-conditional__row">
<td class="wp-mail-smtp-conditional__property-col">
<select class="wp-mail-smtp-conditional__property">
<option><?php esc_html_e( 'From Email', 'wp-mail-smtp' ); ?></option>
</select>
</td>
<td class="wp-mail-smtp-conditional__operator-col">
<select class="wp-mail-smtp-conditional__operator">
<option><?php esc_html_e( 'Is', 'wp-mail-smtp' ); ?></option>
</select>
</td>
<td class="wp-mail-smtp-conditional__value-col">
<input type="text" value="shop@wpmailsmtp.com" class="wp-mail-smtp-conditional__value">
</td>
<td class="wp-mail-smtp-conditional__actions">
<button class="wp-mail-smtp-conditional__add-rule wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-grey">
<?php esc_html_e( 'And', 'wp-mail-smtp' ); ?>
</button>
<button class="wp-mail-smtp-conditional__delete-rule">
<i class="dashicons dashicons-trash" aria-hidden="true"></i>
</button>
</td>
</tr>
</tbody>
</table>
<div class="wp-mail-smtp-conditional__group-delimiter"><?php esc_html_e( 'or', 'wp-mail-smtp' ); ?></div>
</div>
<div class="wp-mail-smtp-conditional__group">
<table>
<tbody>
<tr class="wp-mail-smtp-conditional__row">
<td class="wp-mail-smtp-conditional__property-col">
<select class="wp-mail-smtp-conditional__property">
<option><?php esc_html_e( 'From Email', 'wp-mail-smtp' ); ?></option>
</select>
</td>
<td class="wp-mail-smtp-conditional__operator-col">
<select class="wp-mail-smtp-conditional__operator">
<option><?php esc_html_e( 'Is', 'wp-mail-smtp' ); ?></option>
</select>
</td>
<td class="wp-mail-smtp-conditional__value-col">
<input type="text" value="returns@wpmailsmtp.com" class="wp-mail-smtp-conditional__value">
</td>
<td class="wp-mail-smtp-conditional__actions">
<button class="wp-mail-smtp-conditional__add-rule wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-grey">
<?php esc_html_e( 'And', 'wp-mail-smtp' ); ?>
</button>
<button class="wp-mail-smtp-conditional__delete-rule">
<i class="dashicons dashicons-trash" aria-hidden="true"></i>
</button>
</td>
</tr>
</tbody>
</table>
<div class="wp-mail-smtp-conditional__group-delimiter"><?php esc_html_e( 'or', 'wp-mail-smtp' ); ?></div>
</div>
<button class="wp-mail-smtp-conditional__add-group wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-grey">
<?php esc_html_e( 'Add New Group', 'wp-mail-smtp' ); ?>
</button>
</div>
</div>
</div>
<div class="wp-mail-smtp-smart-routing-route">
<div class="wp-mail-smtp-smart-routing-route__header">
<span><?php esc_html_e( 'Send with', 'wp-mail-smtp' ); ?></span>
<select class="wp-mail-smtp-smart-routing-route__connection">
<option><?php esc_html_e( 'Contact Emails (SMTP.com)', 'wp-mail-smtp' ); ?></option>
</select>
<span><?php esc_html_e( 'if the following conditions are met...', 'wp-mail-smtp' ); ?></span>
<div class="wp-mail-smtp-smart-routing-route__actions">
<div class="wp-mail-smtp-smart-routing-route__order">
<button class="wp-mail-smtp-smart-routing-route__order-btn wp-mail-smtp-smart-routing-route__order-btn--up">
<img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/icons/arrow-up.svg' ); ?>" alt="<?php esc_attr_e( 'Arrow Up', 'wp-mail-smtp' ); ?>">
</button>
<button class="wp-mail-smtp-smart-routing-route__order-btn wp-mail-smtp-smart-routing-route__order-btn--down">
<img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/icons/arrow-up.svg' ); ?>" alt="<?php esc_attr_e( 'Arrow Down', 'wp-mail-smtp' ); ?>">
</button>
</div>
<button class="wp-mail-smtp-smart-routing-route__delete">
<i class="dashicons dashicons-trash"></i>
</button>
</div>
</div>
<div class="wp-mail-smtp-smart-routing-route__main">
<div class="wp-mail-smtp-conditional">
<div class="wp-mail-smtp-conditional__group">
<table>
<tbody>
<tr class="wp-mail-smtp-conditional__row">
<td class="wp-mail-smtp-conditional__property-col">
<select>
<option><?php esc_html_e( 'Initiator', 'wp-mail-smtp' ); ?></option>
</select>
</td>
<td class="wp-mail-smtp-conditional__operator-col">
<select class="wp-mail-smtp-conditional__operator">
<option><?php esc_html_e( 'Is', 'wp-mail-smtp' ); ?></option>
</select>
</td>
<td class="wp-mail-smtp-conditional__value-col">
<input type="text" value="<?php esc_html_e( 'WPForms', 'wp-mail-smtp' ); ?>" class="wp-mail-smtp-conditional__value">
</td>
<td class="wp-mail-smtp-conditional__actions">
<button class="wp-mail-smtp-conditional__add-rule wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-grey">
<?php esc_html_e( 'And', 'wp-mail-smtp' ); ?>
</button>
<button class="wp-mail-smtp-conditional__delete-rule">
<i class="dashicons dashicons-trash" aria-hidden="true"></i>
</button>
</td>
</tr>
</tbody>
</table>
<div class="wp-mail-smtp-conditional__group-delimiter"><?php esc_html_e( 'or', 'wp-mail-smtp' ); ?></div>
</div>
<button class="wp-mail-smtp-conditional__add-group wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-grey">
<?php esc_html_e( 'Add New Group', 'wp-mail-smtp' ); ?>
</button>
</div>
</div>
</div>
</div>
<div class="wp-mail-smtp-smart-routing-routes-note">
<img src="<?php echo esc_url( wp_mail_smtp()->assets_url . '/images/icons/lightbulb.svg' ); ?>" alt="<?php esc_attr_e( 'Light bulb icon', 'wp-mail-smtp' ); ?>">
<?php esc_html_e( 'Friendly reminder, your Primary Connection will be used for all emails that do not match the conditions above.', 'wp-mail-smtp' ); ?>
</div>
</div>
</div>
<a href="<?php echo esc_url( $bottom_upgrade_button_url ); ?>" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-product-education__upgrade-btn wp-mail-smtp-product-education__upgrade-btn--bottom wp-mail-smtp-btn wp-mail-smtp-btn-upgrade wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Upgrade to WP Mail SMTP Pro', 'wp-mail-smtp' ); ?>
</a>
</div>
<?php
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,55 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\ParentPageAbstract;
/**
* Class Tools.
*
* @since 2.8.0
*/
class Tools extends ParentPageAbstract {
/**
* Slug of a page.
*
* @since 2.8.0
*
* @var string
*/
protected $slug = 'tools';
/**
* Page default tab slug.
*
* @since 2.8.0
*
* @var string
*/
protected $default_tab = 'test';
/**
* Link label of a page.
*
* @since 2.8.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Tools', 'wp-mail-smtp' );
}
/**
* Title of a page.
*
* @since 2.8.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
}

View File

@@ -0,0 +1,281 @@
<?php
namespace WPMailSMTP\Admin\Pages;
use WPMailSMTP\Admin\PageAbstract;
/**
* Versus tab.
*
* @since 2.9.0
*/
class VersusTab extends PageAbstract {
/**
* Part of the slug of a tab.
*
* @since 2.9.0
*
* @var string
*/
protected $slug = 'versus';
/**
* Tab priority.
*
* @since 2.9.0
*
* @var int
*/
protected $priority = 40;
/**
* Link label of a tab.
*
* @since 2.9.0
*
* @return string
*/
public function get_label() {
return esc_html__( 'Lite vs Pro', 'wp-mail-smtp' );
}
/**
* Title of a tab.
*
* @since 2.9.0
*
* @return string
*/
public function get_title() {
return $this->get_label();
}
/**
* Tab content.
*
* @since 2.9.0
*/
public function display() {
$license = wp_mail_smtp()->get_license_type();
?>
<div class="wp-mail-smtp-admin-about-section wp-mail-smtp-admin-about-section-squashed">
<h1 class="centered">
<strong>
<?php
printf(
/* translators: %s - plugin current license type. */
esc_html__( '%s vs Pro', 'wp-mail-smtp' ),
esc_html( ucfirst( $license ) )
);
?>
</strong>
</h1>
<p class="centered <?php echo( $license === 'pro' ? 'hidden' : '' ); ?>">
<?php esc_html_e( 'Get the most out of WP Mail SMTP by upgrading to Pro and unlocking all of the powerful features.', 'wp-mail-smtp' ); ?>
</p>
</div>
<div class="wp-mail-smtp-admin-about-section wp-mail-smtp-admin-about-section-squashed wp-mail-smtp-admin-about-section-hero wp-mail-smtp-admin-about-section-table">
<div class="wp-mail-smtp-admin-about-section-hero-main wp-mail-smtp-admin-columns">
<div class="wp-mail-smtp-admin-column-33">
<h3 class="no-margin">
<?php esc_html_e( 'Feature', 'wp-mail-smtp' ); ?>
</h3>
</div>
<div class="wp-mail-smtp-admin-column-33">
<h3 class="no-margin">
<?php echo esc_html( ucfirst( $license ) ); ?>
</h3>
</div>
<div class="wp-mail-smtp-admin-column-33">
<h3 class="no-margin">
<?php esc_html_e( 'Pro', 'wp-mail-smtp' ); ?>
</h3>
</div>
</div>
<div class="wp-mail-smtp-admin-about-section-hero-extra no-padding wp-mail-smtp-admin-columns">
<table>
<?php
foreach ( $this->get_license_features() as $slug => $name ) {
$current = $this->get_license_data( $slug, $license );
$pro = $this->get_license_data( $slug, 'pro' );
?>
<tr class="wp-mail-smtp-admin-columns">
<td class="wp-mail-smtp-admin-column-33">
<p><?php echo esc_html( $name ); ?></p>
</td>
<td class="wp-mail-smtp-admin-column-33">
<p class="features-<?php echo esc_attr( $current['status'] ); ?>">
<?php echo implode( '<br>', $current['text'] ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</p>
</td>
<td class="wp-mail-smtp-admin-column-33">
<p class="features-full">
<?php echo implode( '<br>', $pro['text'] ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>
</p>
</td>
</tr>
<?php
}
?>
</table>
</div>
</div>
<?php if ( 'lite' === $license ) : ?>
<div class="wp-mail-smtp-admin-about-section wp-mail-smtp-admin-about-section-hero">
<div class="wp-mail-smtp-admin-about-section-hero-main no-border">
<h3 class="call-to-action centered">
<a href="<?php echo esc_url( wp_mail_smtp()->get_upgrade_link( 'lite-vs-pro' ) ); ?>" target="_blank" rel="noopener noreferrer">
<?php esc_html_e( 'Get WP Mail SMTP Pro Today and Unlock all of these Powerful Features', 'wp-mail-smtp' ); ?>
</a>
</h3>
<p class="centered">
<?php
printf(
wp_kses( /* Translators: %s - discount value $50. */
__( 'Bonus: WP Mail SMTP Lite users get <span class="price-off">%s off regular price</span>, automatically applied at checkout.', 'wp-mail-smtp' ),
[
'span' => [
'class' => [],
],
]
),
'$50'
);
?>
</p>
</div>
</div>
<?php endif; ?>
<?php
}
/**
* Get the list of features for all licenses.
*
* @since 2.9.0
*
* @return array
*/
private function get_license_features() {
return [
'log' => esc_html__( 'Email Log', 'wp-mail-smtp' ),
'control' => esc_html__( 'Email Controls', 'wp-mail-smtp' ),
'mailers' => esc_html__( 'Mailer Options', 'wp-mail-smtp' ),
'multisite' => esc_html__( 'WordPress Multisite', 'wp-mail-smtp' ),
'support' => esc_html__( 'Customer Support', 'wp-mail-smtp' ),
];
}
/**
* Get the array of data that compared the license data.
*
* @since 2.9.0
*
* @param string $feature Feature name.
* @param string $license License type to get data for.
*
* @return array|false
*/
private function get_license_data( $feature, $license ) {
$data = [
'log' => [
'lite' => [
'status' => 'none',
'text' => [
'<strong>' . esc_html__( 'Emails are not logged', 'wp-mail-smtp' ) . '</strong>',
],
],
'pro' => [
'status' => 'full',
'text' => [
'<strong>' . esc_html__( 'Access to all Email Logging options right inside WordPress', 'wp-mail-smtp' ) . '</strong>',
],
],
],
'control' => [
'lite' => [
'status' => 'none',
'text' => [
'<strong>' . esc_html__( 'No controls over whether default WordPress emails are sent', 'wp-mail-smtp' ) . '</strong>',
],
],
'pro' => [
'status' => 'full',
'text' => [
'<strong>' . esc_html__( 'Complete Email Controls management for most default WordPress emails', 'wp-mail-smtp' ) . '</strong>',
],
],
],
'mailers' => [
'lite' => [
'status' => 'none',
'text' => [
'<strong>' . esc_html__( 'Limited Mailers', 'wp-mail-smtp' ) . '</strong><br>' . esc_html__( 'Access is limited to standard mailer options only', 'wp-mail-smtp' ),
],
],
'pro' => [
'status' => 'full',
'text' => [
'<strong>' . esc_html__( 'Additional Mailer Options', 'wp-mail-smtp' ) . '</strong><br>' . esc_html__( 'Microsoft Outlook (with Office365 support), Amazon SES and Zoho Mail', 'wp-mail-smtp' ),
],
],
],
'multisite' => [
'lite' => [
'status' => 'none',
'text' => [
'<strong>' . esc_html__( 'No Global Network Settings', 'wp-mail-smtp' ) . '</strong>',
],
],
'pro' => [
'status' => 'full',
'text' => [
'<strong>' . esc_html__( 'All Global Network Settings', 'wp-mail-smtp' ) . '</strong><br>' . esc_html__( 'Optionally configure settings at the network level or manage separately for each subsite', 'wp-mail-smtp' ),
],
],
],
'support' => [
'lite' => [
'status' => 'none',
'text' => [
'<strong>' . esc_html__( 'Limited Support', 'wp-mail-smtp' ) . '</strong>',
],
],
'pro' => [
'status' => 'full',
'text' => [
'<strong>' . esc_html__( 'Priority Support', 'wp-mail-smtp' ) . '</strong>',
],
],
],
];
// Wrong feature?
if ( ! isset( $data[ $feature ] ) ) {
return false;
}
// Wrong license type?
if ( ! isset( $data[ $feature ][ $license ] ) ) {
return false;
}
return $data[ $feature ][ $license ];
}
}

View File

@@ -0,0 +1,381 @@
<?php
namespace WPMailSMTP\Admin;
use WPMailSMTP\WP;
/**
* Class ParentPageAbstract.
*
* @since 2.8.0
*/
abstract class ParentPageAbstract implements PageInterface {
/**
* Slug of a page.
*
* @since 2.8.0
*
* @var string
*/
protected $slug;
/**
* Page tabs.
*
* @since 2.8.0
*
* @var PageAbstract[]
*/
protected $tabs = [];
/**
* Page default tab slug.
*
* @since 2.8.0
*
* @var string
*/
protected $default_tab = '';
/**
* Constructor.
*
* @since 2.8.0
*
* @param array $tabs Page tabs.
*/
public function __construct( $tabs = [] ) {
/**
* Filters parent page tabs.
*
* @since 2.8.0
*
* @param string[] $tabs Parent page tabs.
*/
$tabs = apply_filters( 'wp_mail_smtp_admin_page_' . $this->slug . '_tabs', $tabs );
if ( wp_mail_smtp()->get_admin()->is_admin_page( $this->slug ) ) {
$this->init_tabs( $tabs );
$this->hooks();
}
if ( WP::is_doing_self_ajax() ) {
$this->init_ajax( $tabs );
}
}
/**
* Hooks.
*
* @since 2.8.0
*/
protected function hooks() {
add_action( 'admin_init', [ $this, 'process_actions' ] );
// Register tab related hooks.
if ( isset( $this->tabs[ $this->get_current_tab() ] ) ) {
$this->tabs[ $this->get_current_tab() ]->hooks();
}
}
/**
* Initialize ajax actions.
*
* @since 3.0.0
*
* @param array $tabs Page tabs.
*/
private function init_ajax( $tabs ) {
foreach ( $tabs as $tab ) {
if ( $this->is_valid_tab( $tab ) ) {
( new $tab( $this ) )->ajax();
}
}
}
/**
* Get the page slug.
*
* @since 2.8.0
*
* @return string
*/
public function get_slug() {
return $this->slug;
}
/**
* Get the page tabs.
*
* @since 2.8.0
*
* @return PageAbstract[]
*/
public function get_tabs() {
return $this->tabs;
}
/**
* Get the page tabs slugs.
*
* @since 2.8.0
*
* @return string[]
*/
public function get_tabs_slugs() {
return array_map(
function ( $tab ) {
return $tab->get_slug();
},
$this->tabs
);
}
/**
* Get the page/tab link.
*
* @since 2.8.0
*
* @param string $tab Tab to generate a link to.
*
* @return string
*/
public function get_link( $tab = '' ) {
return add_query_arg(
'tab',
$this->get_defined_tab( $tab ),
WP::admin_url( 'admin.php?page=' . Area::SLUG . '-' . $this->slug )
);
}
/**
* Get the current tab.
*
* @since 2.8.0
*
* @return string
*/
public function get_current_tab() {
$tab = isset( $_GET['tab'] ) ? sanitize_key( $_GET['tab'] ) : ''; // phpcs:ignore WordPress.Security.NonceVerification.Recommended
return $this->get_defined_tab( $tab );
}
/**
* Get the tab label.
*
* @since 2.9.0
*
* @param string $tab Tab key.
*
* @return string
*/
public function get_tab_label( $tab ) {
$tabs = $this->get_tabs();
return isset( $tabs[ $tab ] ) ? $tabs[ $tab ]->get_label() : '';
}
/**
* Get the tab title.
*
* @since 2.9.0
*
* @param string $tab Tab key.
*
* @return string
*/
public function get_tab_title( $tab ) {
$tabs = $this->get_tabs();
return isset( $tabs[ $tab ] ) ? $tabs[ $tab ]->get_title() : '';
}
/**
* Get the defined or default tab.
*
* @since 2.8.0
*
* @param string $tab Tab to check.
*
* @return string Defined tab. Fallback to default one if it doesn't exist.
*/
protected function get_defined_tab( $tab ) {
$tab = sanitize_key( $tab );
return in_array( $tab, $this->get_tabs_slugs(), true ) ? $tab : $this->default_tab;
}
/**
* Initialize tabs.
*
* @since 2.8.0
*
* @param array $tabs Page tabs.
*/
public function init_tabs( $tabs ) {
foreach ( $tabs as $key => $tab ) {
if ( ! $this->is_valid_tab( $tab ) ) {
continue;
}
$this->tabs[ $key ] = new $tab( $this );
}
// Sort tabs by priority.
$this->sort_tabs();
}
/**
* All possible plugin forms manipulation and hooks registration will be done here.
*
* @since 2.8.0
*/
public function process_actions() {
$tabs = $this->get_tabs_slugs();
// Allow to process only own tabs.
if ( ! array_key_exists( $this->get_current_tab(), $tabs ) ) {
return;
}
// Process POST only if it exists.
// phpcs:disable WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized, WordPress.Security.ValidatedSanitizedInput.MissingUnslash
if ( ! empty( $_POST ) && isset( $_POST['wp-mail-smtp-post'] ) ) {
if ( ! empty( $_POST['wp-mail-smtp'] ) ) {
$post = $_POST['wp-mail-smtp'];
} else {
$post = [];
}
$this->tabs[ $this->get_current_tab() ]->process_post( $post );
}
// phpcs:enable
// This won't do anything for most pages.
// Works for plugin page only, when GET params are allowed.
$this->tabs[ $this->get_current_tab() ]->process_auth();
}
/**
* Display page content based on the current tab.
*
* @since 2.8.0
*/
public function display() {
$current_tab = $this->get_current_tab();
$page_slug = $this->slug;
?>
<div class="wp-mail-smtp-page-title">
<?php if ( count( $this->tabs ) > 1 ) : ?>
<?php foreach ( $this->tabs as $tab ) : ?>
<a href="<?php echo esc_url( $tab->get_link() ); ?>"
class="tab <?php echo $current_tab === $tab->get_slug() ? 'active' : ''; ?>">
<?php echo esc_html( $tab->get_label() ); ?>
</a>
<?php endforeach; ?>
<?php else : ?>
<span class="page-title"><?php echo esc_html( array_values( $this->tabs )[0]->get_title() ); ?></span>
<?php endif; ?>
<?php
/**
* Fires after page title.
*
* @since 2.9.0
*
* @param ParentPageAbstract $page Current page.
*/
do_action( "wp_mail_smtp_admin_page_{$page_slug}_{$current_tab}_display_header", $this );
?>
</div>
<div class="wp-mail-smtp-page-content">
<?php
foreach ( $this->tabs as $tab ) {
if ( $tab->get_slug() === $current_tab ) {
printf( '<h1 class="screen-reader-text">%s</h1>', esc_html( $tab->get_title() ) );
/**
* Fires before tab content.
*
* @since 2.8.0
*
* @param PageAbstract $tab Current tab.
*/
do_action( 'wp_mail_smtp_admin_pages_before_content', $tab );
/**
* Fires before tab content.
*
* @since 2.9.0
*
* @param PageAbstract $tab Current tab.
*/
do_action( "wp_mail_smtp_admin_page_{$page_slug}_{$current_tab}_display_before", $tab );
$tab->display();
/**
* Fires after tab content.
*
* @since 2.8.0
*
* @param PageAbstract $tab Current tab.
*/
do_action( "wp_mail_smtp_admin_page_{$page_slug}_{$current_tab}_display_after", $tab );
break;
}
}
?>
</div>
<?php
}
/**
* Sort tabs by priority.
*
* @since 2.8.0
*/
protected function sort_tabs() {
uasort(
$this->tabs,
function ( $a, $b ) {
return ( $a->get_priority() < $b->get_priority() ) ? - 1 : 1;
}
);
}
/**
* Whether tab is valid.
*
* @since 3.0.0
*
* @param array $tab Page tab.
*
* @return bool
*/
private function is_valid_tab( $tab ) {
return is_subclass_of( $tab, '\WPMailSMTP\Admin\PageAbstract' );
}
}

View File

@@ -0,0 +1,58 @@
<?php
namespace WPMailSMTP\Admin;
use Automatic_Upgrader_Skin;
/**
* WordPress class extended for on-the-fly plugin installations.
*
* @since 1.5.0
* @since 1.7.1 Removed feedback() method override to be compatible with PHP5.3+ and WP5.3.
* @since 3.11.0 Updated to extend Automatic_Upgrader_Skin.
*/
class PluginsInstallSkin extends Automatic_Upgrader_Skin {
/**
* Empty out the header of its HTML content and only check to see if it has
* been performed or not.
*
* @since 1.5.0
*/
public function header() {
}
/**
* Empty out the footer of its HTML contents.
*
* @since 1.5.0
*/
public function footer() {
}
/**
* Instead of outputting HTML for errors, json_encode the errors and send them
* back to the Ajax script for processing.
*
* @since 1.5.0
*
* @param array $errors Array of errors with the install process.
*/
public function error( $errors ) {
if ( ! empty( $errors ) ) {
wp_send_json_error( $errors );
}
}
/**
* Empty out JavaScript output that calls function to decrement the update counts.
*
* @since 1.5.0
*
* @param string $type Type of update count to decrement.
*/
public function decrement_update_count( $type ) {
}
}

View File

@@ -0,0 +1,227 @@
<?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_init', [ $this, 'admin_notices' ] );
add_action( 'wp_ajax_wp_mail_smtp_review_dismiss', array( $this, 'review_dismiss' ) );
}
/**
* Display notices only in Network Admin if in Multisite.
* Otherwise, display in Admin Dashboard.
*
* @since 3.8.0
*
* @return void
*/
public function admin_notices() { // phpcs:ignore WPForms.PHP.HooksMethod.InvalidPlaceForAddingHooks
if ( is_multisite() ) {
add_action( 'network_admin_notices', [ $this, 'review_request' ] );
} else {
add_action( 'admin_notices', [ $this, 'review_request' ] );
}
}
/**
* 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 no or the default mailer is selected.
if ( empty( $mailer ) || $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;
}
$mailer_object = wp_mail_smtp()
->get_providers()
->get_mailer( $mailer, wp_mail_smtp()->get_processor()->get_phpmailer() );
// Check if mailer setup is complete.
$mailer_setup_complete = ! empty( $mailer_object ) ? $mailer_object->is_mailer_complete() : false;
// 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>
<?php
printf(
'<a href="%1$s" class="wp-mail-smtp-dismiss-review-notice wp-mail-smtp-review-out" target="_blank" rel="noopener noreferrer">%2$s</a>',
// phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/plugin-feedback/', [ 'medium' => 'review-notice', 'content' => 'Give Feedback' ] ) ),
esc_html__( 'Give Feedback', 'wp-mail-smtp' )
);
?>
<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>Co-Founder, 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();
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,70 @@
<?php
namespace WPMailSMTP\Compatibility;
use WPMailSMTP\WP;
/**
* Compatibility.
* Class for managing compatibility with other plugins.
*
* @since 2.8.0
*/
class Compatibility {
/**
* Initialized compatibility plugins.
*
* @since 2.8.0
*
* @var array
*/
protected $plugins = [];
/**
* Initialize class.
*
* @since 2.8.0
*/
public function init() {
// Setup compatibility only in admin area.
if ( WP::in_wp_admin() ) {
$this->setup_compatibility();
}
}
/**
* Setup compatibility plugins.
*
* @since 2.8.0
*/
public function setup_compatibility() {
$plugins = [
'admin-2020' => '\WPMailSMTP\Compatibility\Plugin\Admin2020',
];
foreach ( $plugins as $key => $classname ) {
if ( class_exists( $classname ) && is_callable( [ $classname, 'is_applicable' ] ) ) {
if ( $classname::is_applicable() ) {
$this->plugins[ $key ] = new $classname();
}
}
}
}
/**
* Get compatibility plugin.
*
* @since 2.8.0
*
* @param string $key Plugin key.
*
* @return \WPMailSMTP\Compatibility\Plugin\PluginAbstract | false
*/
public function get_plugin( $key ) {
return isset( $this->plugins[ $key ] ) ? $this->plugins[ $key ] : false;
}
}

View File

@@ -0,0 +1,56 @@
<?php
namespace WPMailSMTP\Compatibility\Plugin;
/**
* Admin 2020 Lite compatibility plugin.
*
* @since 2.8.0
*/
class Admin2020 extends PluginAbstract {
/**
* Get plugin name.
*
* @since 2.8.0
*
* @return string
*/
public static function get_name() {
return 'Admin 2020';
}
/**
* Get plugin path.
*
* @since 2.8.0
*
* @return string
*/
public static function get_path() {
return 'admin-2020/admin-2020.php';
}
/**
* Execute on init action in admin area.
*
* @since 2.8.0
*/
public function load_admin() {
add_action( 'wp_mail_smtp_admin_setup_wizard_load_setup_wizard_before', [ $this, 'disable_admin_bar' ] );
}
/**
* Disable admin bar on Setup Wizard page.
*
* @since 2.8.0
*/
public function disable_admin_bar() {
global $wp_admin_bar;
$wp_admin_bar = ''; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
}
}

View File

@@ -0,0 +1,77 @@
<?php
namespace WPMailSMTP\Compatibility\Plugin;
use WPMailSMTP\WP;
/**
* Compatibility plugin.
*
* @since 2.8.0
*/
abstract class PluginAbstract implements PluginInterface {
/**
* Class constructor.
*
* @since 2.8.0
*/
public function __construct() {
add_action( 'init', [ $this, 'load' ], 0 );
if ( WP::in_wp_admin() ) {
add_action( 'init', [ $this, 'load_admin' ], 0 );
}
$this->after_plugins_loaded();
}
/**
* Is plugin can be loaded.
*
* @since 2.8.0
*
* @return bool
*/
public static function is_applicable() {
return static::is_activated();
}
/**
* Is plugin activated.
*
* @since 2.8.0
*
* @return bool
*/
public static function is_activated() {
return WP::is_plugin_activated( static::get_path() );
}
/**
* Execute after plugins loaded.
*
* @since 2.8.0
*/
public function after_plugins_loaded() {
}
/**
* Execute on init action in admin area.
*
* @since 2.8.0
*/
public function load_admin() {
}
/**
* Execute on init action.
*
* @since 2.8.0
*/
public function load() {
}
}

View File

@@ -0,0 +1,68 @@
<?php
namespace WPMailSMTP\Compatibility\Plugin;
/**
* Compatibility plugin interface.
*
* @since 2.8.0
*/
interface PluginInterface {
/**
* Is plugin can be loaded.
*
* @since 2.8.0
*
* @return bool
*/
public static function is_applicable();
/**
* Is plugin activated.
*
* @since 2.8.0
*
* @return bool
*/
public static function is_activated();
/**
* Execute after plugins loaded.
*
* @since 2.8.0
*/
public function after_plugins_loaded();
/**
* Execute on init action in admin area.
*
* @since 2.8.0
*/
public function load_admin();
/**
* Execute on init action.
*
* @since 2.8.0
*/
public function load();
/**
* Get plugin name.
*
* @since 2.8.0
*
* @return string
*/
public static function get_name();
/**
* Get plugin path.
*
* @since 2.8.0
*
* @return string
*/
public static function get_path();
}

View File

@@ -0,0 +1,602 @@
<?php
namespace WPMailSMTP;
/**
* Class Conflicts.
*
* @since 1.5.0
*/
class Conflicts {
/**
* List of plugins WP Mail SMTP may be conflicting with.
*
* @since 1.5.0
* @since 2.8.0 Updated the format of the plugins array.
*
* @var array List of plugins WP Mail SMTP may be conflicting with.
*/
public static $plugins = [];
/**
* All detected conflicting plugins.
*
* @since 1.5.0
* @since 3.6.0 Changed from storing a single conflicting plugin info to storing multiple conflicting plugin items.
*
* @var array
*/
protected $conflict = [];
/**
* Constructor.
*
* @since 2.9.0
*/
public function __construct() {
self::$plugins = [
/**
* Url: https://wordpress.org/plugins/easy-wp-smtp/
*/
[
'name' => 'Easy WP SMTP',
'slug' => 'easy-wp-smtp/easy-wp-smtp.php',
'class' => 'EasyWPSMTP',
],
/**
* Closed.
*
* Url: https://wordpress.org/plugins/postman-smtp/
*/
[
'name' => 'Postman SMTP',
'slug' => 'postman-smtp/postman-smtp.php',
'function' => 'postman_start',
],
/**
* Url: https://wordpress.org/plugins/post-smtp/
*/
[
'name' => 'Post SMTP',
'slug' => 'post-smtp/postman-smtp.php',
'function' => 'post_smtp_start',
],
/**
* Url: https://wordpress.org/plugins/wp-mail-bank/
*/
[
'name' => 'Mail Bank',
'slug' => 'wp-mail-bank/wp-mail-bank.php',
'function' => 'mail_bank',
],
/**
* Url: https://wordpress.org/plugins/smtp-mailer/
*/
[
'name' => 'SMTP Mailer',
'slug' => 'smtp-mailer/main.php',
'class' => 'SMTP_MAILER',
],
/**
* Url: https://wordpress.org/plugins/gmail-smtp/
*/
[
'name' => 'Gmail SMTP',
'slug' => 'gmail-smtp/main.php',
'class' => 'GMAIL_SMTP',
],
/**
* Url: https://wordpress.org/plugins/wp-email-smtp/
*/
[
'name' => 'WP Email SMTP',
'class' => 'WP_Email_Smtp',
],
/**
* Url: https://wordpress.org/plugins/smtp-mail/
*/
[
'name' => 'SMTP Mail',
'slug' => 'smtp-mail/index.php',
'function' => 'smtpmail_include',
],
/**
* Url: https://wordpress.org/plugins/bws-smtp/
*/
[
'name' => 'SMTP by BestWebSoft',
'slug' => 'bws-smtp/bws-smtp.php',
'function' => 'bwssmtp_init',
],
/**
* Url: https://wordpress.org/plugins/wp-sendgrid-smtp/
*/
[
'name' => 'WP SendGrid SMTP',
'slug' => 'wp-sendgrid-smtp/wp-sendgrid-smtp.php',
'class' => 'WPSendGrid_SMTP',
],
/**
* Url: https://wordpress.org/plugins/sar-friendly-smtp/
*/
[
'name' => 'SAR Friendly SMTP',
'slug' => 'sar-friendly-smtp/sar-friendly-smtp.php',
'function' => 'sar_friendly_smtp',
],
/**
* Url: https://wordpress.org/plugins/wp-gmail-smtp/
*/
[
'name' => 'WP Gmail SMTP',
'slug' => 'wp-gmail-smtp/wp-gmail-smtp.php',
'class' => 'WPGmail_SMTP',
],
/**
* Url: https://wordpress.org/plugins/cimy-swift-smtp/
*/
[
'name' => 'Cimy Swift SMTP',
'slug' => 'cimy-swift-smtp/cimy_swift_smtp.php',
'function' => 'st_smtp_check_config',
],
/**
* Closed.
*
* Url: https://wordpress.org/plugins/wp-easy-smtp/
*/
[
'name' => 'WP Easy SMTP',
'slug' => 'wp-easy-smtp/wp-easy-smtp.php',
'class' => 'WP_Easy_SMTP',
],
/**
* Url: https://wordpress.org/plugins/wp-mailgun-smtp/
*/
[
'name' => 'WP Mailgun SMTP',
'slug' => 'wp-mailgun-smtp/wp-mailgun-smtp.php',
'class' => 'WPMailgun_SMTP',
],
/**
* Url: https://wordpress.org/plugins/my-smtp-wp/
*/
[
'name' => 'MY SMTP WP',
'slug' => 'my-smtp-wp/my-smtp-wp.php',
'function' => 'my_smtp_wp',
],
/**
* Closed.
*
* Url: https://wordpress.org/plugins/wp-mail-booster/
*/
[
'name' => 'WP Mail Booster',
'slug' => 'wp-mail-booster/wp-mail-booster.php',
'function' => 'mail_booster',
],
/**
* Url: https://wordpress.org/plugins/sendgrid-email-delivery-simplified/
*/
[
'name' => 'SendGrid',
'slug' => 'sendgrid-email-delivery-simplified/wpsendgrid.php',
'class' => 'Sendgrid_Settings',
],
/**
* Url: https://wordpress.org/plugins/wp-mail-smtp-mailer/
*/
[
'name' => 'WP Mail Smtp Mailer',
'slug' => 'wp-mail-smtp-mailer/wp-mail-smtp-mailer.php',
'function' => 'WPMS_php_mailer',
],
/**
* Closed.
*
* Url: https://wordpress.org/plugins/wp-amazon-ses-smtp/
*/
[
'name' => 'WP Amazon SES SMTP',
'slug' => 'wp-amazon-ses-smtp/wp-amazon-ses.php',
'class' => 'WPAmazonSES_SMTP',
],
/**
* Url: https://wordpress.org/plugins/postmark-approved-wordpress-plugin/
*/
[
'name' => 'Postmark (Official)',
'slug' => 'postmark-approved-wordpress-plugin/postmark.php',
'class' => 'Postmark_Mail',
],
/**
* Url: https://wordpress.org/plugins/mailgun/
*/
[
'name' => 'Mailgun',
'slug' => 'mailgun/mailgun.php',
'class' => 'Mailgun',
],
/**
* Url: https://wordpress.org/plugins/sparkpost/
*/
[
'name' => 'SparkPost',
'slug' => 'sparkpost/wordpress-sparkpost.php',
'class' => 'WPSparkPost\SparkPost',
],
/**
* Url: https://wordpress.org/plugins/wp-yahoo-smtp/
*/
[
'name' => 'WP Yahoo SMTP',
'slug' => 'wp-yahoo-smtp/wp-yahoo-smtp.php',
'class' => 'WPYahoo_SMTP',
],
/**
* Url: https://wordpress.org/plugins/wp-ses/
*/
[
'name' => 'WP Offload SES Lite',
'slug' => 'wp-ses/wp-ses.php',
'function' => 'wp_offload_ses_lite_init',
],
/**
* Url: https://deliciousbrains.com/wp-offload-ses/
*/
[
'name' => 'WP Offload SES',
'slug' => 'wp-offload-ses/wp-offload-ses.php',
],
/**
* Url: https://wordpress.org/plugins/turbosmtp/
*/
[
'name' => 'turboSMTP',
'slug' => 'turbosmtp/turbo-smtp-plugin.php',
'function' => 'TSPHPMailer',
],
/**
* Url: https://wordpress.org/plugins/wp-smtp/
*/
[
'name' => 'WP SMTP',
'slug' => 'wp-smtp/wp-smtp.php',
'class' => 'WP_SMTP',
],
/**
* This plugin can be used along with our plugin if disable next option
* WooCommerce -> Settings -> Sendinblue -> Email Options -> Enable Sendinblue to send WooCommerce emails.
*
* Url: https://wordpress.org/plugins/woocommerce-sendinblue-newsletter-subscription
*/
[
'name' => 'Sendinblue - WooCommerce Email Marketing',
'slug' => 'woocommerce-sendinblue-newsletter-subscription/woocommerce-sendinblue.php',
'class' => 'WC_Sendinblue_Integration',
'test' => 'test_wc_sendinblue_integration',
'message' => esc_html__( 'Or disable the Sendinblue email sending setting in WooCommerce > Settings > Sendinblue (tab) > Email Options (tab) > Enable Sendinblue to send WooCommerce emails.', 'wp-mail-smtp' ),
],
/**
* Url: https://wordpress.org/plugins/disable-emails/
*/
[
'name' => 'Disable Emails',
'slug' => 'disable-emails/disable-emails.php',
'class' => '\webaware\disable_emails\Plugin',
],
/**
* Url: https://wordpress.org/plugins/fluent-smtp/
*/
[
'name' => 'FluentSMTP',
'slug' => 'fluent-smtp/fluent-smtp.php',
'function' => 'fluentSmtpInit',
],
/**
* This plugin can be used along with our plugin if enable next option
* Settings > Email template > Sender (tab) -> Do not change email sender by default.
*
* Url: https://wordpress.org/plugins/wp-html-mail/
*/
[
'name' => 'WP HTML Mail - Email Template Designer',
'slug' => 'wp-html-mail/wp-html-mail.php',
'function' => 'Haet_Mail',
'test' => 'test_wp_html_mail_integration',
'message' => esc_html__( 'Or enable "Do not change email sender by default" setting in Settings > Email template > Sender (tab).', 'wp-mail-smtp' ),
],
/**
* This plugin can be used along with our plugin if "SMTP" module is deactivated.
*
* Url: https://wordpress.org/plugins/branda-white-labeling/
*/
[
'name' => 'Branda',
'slug' => 'branda-white-labeling/ultimate-branding.php',
'function' => 'set_ultimate_branding',
'test' => 'test_branda_integration',
'message' => esc_html__( 'Or deactivate "SMTP" module in Branda > Emails > SMTP.', 'wp-mail-smtp' ),
],
/**
* Url: https://wordpress.org/plugins/zoho-mail/
*/
[
'name' => 'Zoho Mail for WordPress',
'slug' => 'zoho-mail/zohoMail.php',
'function' => 'zmail_send_mail_callback',
],
];
}
/**
* Whether we have a conflict with predefined list of plugins.
*
* @since 1.5.0
*
* @return bool
*/
public function is_detected() {
foreach ( self::$plugins as $plugin ) {
if ( $this->is_conflicting_plugin( $plugin ) ) {
$this->conflict[] = $plugin;
}
}
return ! empty( $this->conflict );
}
/**
* Whether we have a conflict with plugin.
*
* @since 2.9.0
*
* @param array $plugin Plugin data.
*
* @return bool
*/
protected function is_conflicting_plugin( $plugin ) {
$conflict = false;
if ( isset( $plugin['slug'] ) && WP::is_plugin_activated( $plugin['slug'] ) ) {
$conflict = true;
} elseif ( isset( $plugin['class'] ) && class_exists( $plugin['class'], false ) ) {
$conflict = true;
} elseif ( isset( $plugin['function'] ) && function_exists( $plugin['function'] ) ) {
$conflict = true;
}
if (
$conflict &&
isset( $plugin['test'] ) &&
is_callable( [ $this, $plugin['test'] ] )
) {
$conflict = call_user_func( [ $this, $plugin['test'] ] );
}
/**
* Filters whether the plugin is conflicting.
*
* @since 2.9.0
*
* @param bool $conflict Whether the plugin is conflicting.
* @param array $plugin {
* Plugin data.
*
* @type string $name Plugin name.
* @type string $slug Plugin slug.
* }
*/
return apply_filters( 'wp_mail_smtp_conflicts_is_conflicting_plugin', $conflict, $plugin );
}
/**
* Add a warning admin message to a user about the conflicting plugin.
*
* @since 1.5.0
*/
public function notify() {
if ( empty( $this->conflict ) ) {
return;
}
foreach ( $this->conflict as $conflict_plugin ) {
WP::add_admin_notice( $this->get_conflict_message( $conflict_plugin ), WP::ADMIN_NOTICE_WARNING );
}
}
/**
* Get the conflicting plugin name is any.
*
* @since 1.5.0
* @since 3.6.0 Added optional conflict_plugin parameter.
*
* @param array $conflict_plugin The conflicting plugin array. If provided then extract the name from the array.
* Else get the name from first conflicting plugin.
*
* @return null|string
*/
public function get_conflict_name( $conflict_plugin = [] ) {
$name = null;
if ( empty( $conflict_plugin ) && isset( $this->conflict[0] ) ) {
$conflict_plugin = $this->conflict[0];
}
if ( ! empty( $conflict_plugin['name'] ) ) {
$name = $conflict_plugin['name'];
}
return $name;
}
/**
* Get the conflicting plugin message.
*
* @since 2.9.0
* @since 3.6.0 Added optional conflict_plugin parameter.
*
* @param array $conflict_plugin The conflicting plugin array. If provided then extract the message from the array.
* Else get the message from first conflicting plugin.
*
* @return string
*/
public function get_conflict_message( $conflict_plugin = [] ) {
if ( empty( $conflict_plugin ) && isset( $this->conflict[0] ) ) {
$conflict_plugin = $this->conflict[0];
}
$message = sprintf( /* translators: %1$s - Plugin name causing conflict. */
esc_html__( 'Heads up! WP Mail SMTP has detected %1$s is activated. Please deactivate %1$s to prevent conflicts.', 'wp-mail-smtp' ),
$this->get_conflict_name( $conflict_plugin )
);
if ( ! empty( $conflict_plugin['message'] ) ) {
$message .= ' ' . $conflict_plugin['message'];
}
return $message;
}
/**
* Returns array containing (names) of all the conflicting plugins.
*
* @since 3.6.0
*
* @return array
*/
public function get_all_conflict_names() {
if ( empty( $this->conflict ) ) {
return [];
}
$names_arr = [];
foreach ( $this->conflict as $conflict_plugin ) {
$names_arr[] = $this->get_conflict_name( $conflict_plugin );
}
return $names_arr;
}
/**
* Check whether we have conflict with "WooCommerce Sendinblue Newsletter Subscription" plugin.
*
* @since 2.9.0
* @since 3.7.0 Added a version compatibility check.
*
* @return bool Returns true if we have conflict otherwise false.
*/
protected function test_wc_sendinblue_integration() {
// Since version `3.0.0` "Sendinblue - WooCommerce Email Marketing" plugin no longer conflicts with WP Mail SMTP.
if ( defined( 'SENDINBLUE_WC_PLUGIN_VERSION' ) && version_compare( SENDINBLUE_WC_PLUGIN_VERSION, '3.0.0', '>=' ) ) {
return false;
}
// Check requirements for test.
if (
! class_exists( 'WC_Sendinblue_Integration', false ) ||
! property_exists( 'WC_Sendinblue_Integration', 'ws_smtp_enabled' )
) {
return true;
}
// Display or hide conflict message after toggle "Enable Sendinblue to send WooCommerce emails" option.
// phpcs:disable WordPress.Security.NonceVerification.Recommended, WordPress.Security.NonceVerification.Missing
if (
! empty( $_POST ) &&
( isset( $_GET['page'] ) && $_GET['page'] === 'wc-settings' ) &&
( isset( $_GET['tab'] ) && $_GET['tab'] === 'sendinblue' ) &&
( isset( $_GET['section'] ) && $_GET['section'] === 'email_options' )
) {
return isset( $_POST['ws_smtp_enable'] );
}
// phpcs:enable
return \WC_Sendinblue_Integration::$ws_smtp_enabled === 'yes';
}
/**
* Check whether we have conflict with "WP HTML Mail - Email Template Designer" plugin.
*
* @since 3.3.0
*
* @return bool Returns true if we have conflict otherwise false.
*/
protected function test_wp_html_mail_integration() {
// Check requirements for test.
if (
! function_exists( 'Haet_Mail' ) ||
! is_object( Haet_Mail() ) ||
! method_exists( Haet_Mail(), 'get_options' )
) {
return true;
}
$options = Haet_Mail()->get_options();
return ! isset( $options['disable_sender'] ) || ! $options['disable_sender'];
}
/**
* Check whether we have conflict with "Branda" plugin.
*
* @since 3.5.0
*
* @return bool Returns true if we have conflict otherwise false.
*/
protected function test_branda_integration() {
// Check requirements for test.
if ( ! function_exists( 'branda_is_active_module' ) ) {
return true;
}
return branda_is_active_module( 'emails/smtp.php' );
}
}

View File

@@ -0,0 +1,307 @@
<?php
namespace WPMailSMTP;
use Plugin_Upgrader;
use WP_Error;
use WPMailSMTP\Admin\PluginsInstallSkin;
use WPMailSMTP\Helpers\Helpers;
/**
* WP Mail SMTP Connect.
*
* WP Mail SMTP Connect is our service that makes it easy for non-techy users to
* upgrade to Pro version without having to manually install Pro plugin.
*
* @since 2.6.0
*/
class Connect {
/**
* Hooks.
*
* @since 2.6.0
*/
public function hooks() {
add_action( 'wp_mail_smtp_admin_area_enqueue_assets', [ $this, 'enqueue_scripts' ] );
add_action( 'wp_ajax_wp_mail_smtp_connect_url', [ $this, 'ajax_generate_url' ] );
add_action( 'wp_ajax_nopriv_wp_mail_smtp_connect_process', [ $this, 'process' ] );
}
/**
* Enqueue connect JS file to WP Mail SMTP admin area hook.
*
* @since 2.6.0
*/
public function enqueue_scripts() {
wp_enqueue_script(
'wp-mail-smtp-connect',
wp_mail_smtp()->assets_url . '/js/connect' . WP::asset_min() . '.js',
[ 'jquery' ],
WPMS_PLUGIN_VER,
true
);
wp_localize_script(
'wp-mail-smtp-connect',
'wp_mail_smtp_connect',
[
'ajax_url' => admin_url( 'admin-ajax.php' ),
'plugin_url' => wp_mail_smtp()->plugin_url,
'nonce' => wp_create_nonce( 'wp-mail-smtp-connect' ),
'text' => [
'plugin_activate_btn' => esc_html__( 'Activate', 'wp-mail-smtp' ),
'almost_done' => esc_html__( 'Almost Done', 'wp-mail-smtp' ),
'oops' => esc_html__( 'Oops!', 'wp-mail-smtp' ),
'ok' => esc_html__( 'OK', 'wp-mail-smtp' ),
'server_error' => esc_html__( 'Unfortunately there was a server connection error.', 'wp-mail-smtp' ),
],
]
);
}
/**
* Generate and return WP Mail SMTP Connect URL.
*
* @since 2.6.0
*
* @param string $key The license key.
* @param string $oth The One-time hash.
* @param string $redirect The redirect URL.
*
* @return bool|string
*/
public static function generate_url( $key, $oth = '', $redirect = '' ) {
if ( empty( $key ) || wp_mail_smtp()->is_pro() ) {
return false;
}
$oth = ! empty( $oth ) ? $oth : hash( 'sha512', wp_rand() );
$hashed_oth = hash_hmac( 'sha512', $oth, wp_salt() );
$redirect = ! empty( $redirect ) ? $redirect : wp_mail_smtp()->get_admin()->get_admin_page_url();
update_option( 'wp_mail_smtp_connect_token', $oth );
update_option( 'wp_mail_smtp_connect', $key );
return add_query_arg(
[
'key' => $key,
'oth' => $hashed_oth,
'endpoint' => admin_url( 'admin-ajax.php' ),
'version' => WPMS_PLUGIN_VER,
'siteurl' => admin_url(),
'homeurl' => home_url(),
'redirect' => rawurldecode( base64_encode( $redirect ) ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
'v' => 2,
],
'https://upgrade.wpmailsmtp.com'
);
}
/**
* AJAX callback to generate and return the WP Mail SMTP Connect URL.
*
* @since 2.6.0
*/
public function ajax_generate_url() { //phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
// Run a security check.
check_ajax_referer( 'wp-mail-smtp-connect', 'nonce' );
// Check for permissions.
if ( ! current_user_can( 'install_plugins' ) ) {
wp_send_json_error(
[
'message' => esc_html__( 'You are not allowed to install plugins.', 'wp-mail-smtp' ),
]
);
}
$key = ! empty( $_POST['key'] ) ? sanitize_text_field( wp_unslash( $_POST['key'] ) ) : '';
if ( empty( $key ) ) {
wp_send_json_error(
[
'message' => esc_html__( 'Please enter your license key to connect.', 'wp-mail-smtp' ),
]
);
}
if ( wp_mail_smtp()->is_pro() ) {
wp_send_json_error(
[
'message' => esc_html__( 'Only the Lite version can be upgraded.', 'wp-mail-smtp' ),
]
);
}
// Verify pro version is not installed.
$active = activate_plugin( 'wp-mail-smtp-pro/wp_mail_smtp.php', false, false, true );
if ( ! is_wp_error( $active ) ) {
// Deactivate Lite.
deactivate_plugins( plugin_basename( WPMS_PLUGIN_FILE ) );
wp_send_json_success(
[
'message' => esc_html__( 'WP Mail SMTP Pro was already installed, but was not active. We activated it for you.', 'wp-mail-smtp' ),
'reload' => true,
]
);
}
$url = self::generate_url( $key );
if ( empty( $url ) ) {
wp_send_json_error(
[
'message' => esc_html__( 'There was an error while generating an upgrade URL. Please try again.', 'wp-mail-smtp' ),
]
);
}
wp_send_json_success( [ 'url' => $url ] );
}
/**
* AJAX callback to process WP Mail SMTP Connect.
*
* @since 2.6.0
*/
public function process() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
$error = esc_html__( 'There was an error while installing an upgrade. Please download the plugin from wpmailsmtp.com and install it manually.', 'wp-mail-smtp' );
// Verify params present (oth & download link).
$post_oth = ! empty( $_REQUEST['oth'] ) ? sanitize_text_field( wp_unslash( $_REQUEST['oth'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
$post_url = ! empty( $_REQUEST['file'] ) ? esc_url_raw( wp_unslash( $_REQUEST['file'] ) ) : ''; // phpcs:ignore WordPress.Security.NonceVerification
if ( empty( $post_oth ) || empty( $post_url ) ) {
wp_send_json_error( $error );
}
// Verify oth.
$oth = get_option( 'wp_mail_smtp_connect_token' );
if ( empty( $oth ) ) {
wp_send_json_error( $error );
}
if ( hash_hmac( 'sha512', $oth, wp_salt() ) !== $post_oth ) {
wp_send_json_error( $error );
}
// Delete so cannot replay.
delete_option( 'wp_mail_smtp_connect_token' );
// Set the current screen to avoid undefined notices.
set_current_screen( 'toplevel_page_wp-mail-smtp' );
// Prepare variables.
$url = esc_url_raw( wp_mail_smtp()->get_admin()->get_admin_page_url() );
// Verify pro not activated.
if ( wp_mail_smtp()->is_pro() ) {
wp_send_json_success( esc_html__( 'Plugin installed & activated.', 'wp-mail-smtp' ) );
}
// Verify pro not installed.
$active = activate_plugin( 'wp-mail-smtp-pro/wp_mail_smtp.php', $url, false, true );
if ( ! is_wp_error( $active ) ) {
deactivate_plugins( plugin_basename( WPMS_PLUGIN_FILE ) );
wp_send_json_success( esc_html__( 'Plugin installed & activated.', 'wp-mail-smtp' ) );
}
/*
* The `request_filesystem_credentials` function will output a credentials form in case of failure.
* We don't want that, since it will break AJAX response. So just hide output with a buffer.
*/
ob_start();
// phpcs:ignore WPForms.Formatting.EmptyLineAfterAssigmentVariables.AddEmptyLine
$creds = request_filesystem_credentials( $url, '', false, false, null );
ob_end_clean();
// Check for file system permissions.
$perm_error = esc_html__( 'There was an error while installing an upgrade. Please check file system permissions and try again. Also, you can download the plugin from wpmailsmtp.com and install it manually.', 'wp-mail-smtp' );
if ( false === $creds || ! WP_Filesystem( $creds ) ) {
wp_send_json_error( $perm_error );
}
/*
* We do not need any extra credentials if we have gotten this far, so let's install the plugin.
*/
// Do not allow WordPress to search/download translations, as this will break JS output.
remove_action( 'upgrader_process_complete', array( 'Language_Pack_Upgrader', 'async_upgrade' ), 20 );
// Import the plugin upgrader.
Helpers::include_plugin_upgrader();
// Create the plugin upgrader with our custom skin.
$installer = new Plugin_Upgrader( new PluginsInstallSkin() );
// Error check.
if ( ! method_exists( $installer, 'install' ) ) {
wp_send_json_error( $error );
}
// Check license key.
$key = get_option( 'wp_mail_smtp_connect', false );
delete_option( 'wp_mail_smtp_connect' );
if ( empty( $key ) ) {
wp_send_json_error(
new WP_Error(
'403',
esc_html__( 'There was an error while installing an upgrade. Please try again.', 'wp-mail-smtp' )
)
);
}
$installer->install( $post_url );
// Flush the cache and return the newly installed plugin basename.
wp_cache_flush();
$plugin_basename = $installer->plugin_info();
if ( $plugin_basename ) {
// Deactivate the lite version first.
deactivate_plugins( plugin_basename( WPMS_PLUGIN_FILE ) );
// Activate the plugin silently.
$activated = activate_plugin( $plugin_basename, '', false, true );
if ( ! is_wp_error( $activated ) ) {
// Save the license data, since it was verified on the connect page.
$options = Options::init();
$all_opt = $options->get_all_raw();
$all_opt['license']['key'] = $key;
$all_opt['license']['type'] = 'pro';
$all_opt['license']['is_expired'] = false;
$all_opt['license']['is_disabled'] = false;
$all_opt['license']['is_invalid'] = false;
$options->set( $all_opt, false, true );
wp_send_json_success( esc_html__( 'Plugin installed & activated.', 'wp-mail-smtp' ) );
} else {
// Reactivate the lite plugin if pro activation failed.
activate_plugin( plugin_basename( WPMS_PLUGIN_FILE ), '', false, true );
wp_send_json_error( esc_html__( 'Pro version installed but needs to be activated on the Plugins page.', 'wp-mail-smtp' ) );
}
}
wp_send_json_error( $error );
}
}

View File

@@ -0,0 +1,78 @@
<?php
namespace WPMailSMTP;
/**
* Class Connection.
*
* @since 3.7.0
*/
class Connection extends AbstractConnection {
/**
* Connection Options object.
*
* @since 3.7.0
*
* @var Options
*/
private $options;
/**
* Constructor.
*
* @since 3.7.0
*/
public function __construct() {
$this->options = Options::init();
}
/**
* Get the connection identifier.
*
* @since 3.7.0
*
* @return string
*/
public function get_id() {
return 'primary';
}
/**
* Get the connection name.
*
* @since 3.7.0
*
* @return string
*/
public function get_name() {
return esc_html__( 'Primary', 'wp-mail-smtp' );
}
/**
* Get connection options object.
*
* @since 3.7.0
*
* @return Options
*/
public function get_options() {
return $this->options;
}
/**
* Whether the connection is primary or not.
*
* @since 3.7.0
*
* @return bool
*/
public function is_primary() {
return true;
}
}

View File

@@ -0,0 +1,76 @@
<?php
namespace WPMailSMTP;
use WPMailSMTP\Providers\MailerAbstract;
/**
* Interface ConnectionInterface.
*
* @since 3.7.0
*/
interface ConnectionInterface {
/**
* Get the connection identifier.
*
* @since 3.7.0
*
* @return string
*/
public function get_id();
/**
* Get the connection name.
*
* @since 3.7.0
*
* @return string
*/
public function get_name();
/**
* Get the connection title. Includes mailer name.
*
* @since 3.7.0
*
* @return string
*/
public function get_title();
/**
* Get connection mailer slug.
*
* @since 3.7.0
*
* @return string
*/
public function get_mailer_slug();
/**
* Get connection mailer object.
*
* @since 3.7.0
*
* @return MailerAbstract
*/
public function get_mailer();
/**
* Get connection options object.
*
* @since 3.7.0
*
* @return Options
*/
public function get_options();
/**
* Whether the connection is primary or not.
*
* @since 3.7.0
*
* @return bool
*/
public function is_primary();
}

View File

@@ -0,0 +1,48 @@
<?php
namespace WPMailSMTP;
/**
* Class ConnectionsManager.
*
* @since 3.7.0
*/
class ConnectionsManager {
/**
* Primary connection object.
*
* @since 3.7.0
*
* @var ConnectionInterface
*/
private $primary_connection = null;
/**
* Get the connection object that should be used for email sending.
*
* @since 3.7.0
*
* @return ConnectionInterface
*/
public function get_mail_connection() {
return $this->get_primary_connection();
}
/**
* Get the primary connection object.
*
* @since 3.7.0
*
* @return ConnectionInterface
*/
public function get_primary_connection() {
if ( is_null( $this->primary_connection ) ) {
$this->primary_connection = new Connection();
}
return $this->primary_connection;
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,234 @@
<?php
namespace WPMailSMTP;
use WPMailSMTP\Admin\Area;
use WPMailSMTP\Admin\DebugEvents\DebugEvents;
use WPMailSMTP\Admin\DebugEvents\Migration as DebugMigration;
use WPMailSMTP\Tasks\Meta;
/**
* Class DBRepair to fix the DB related issues.
*
* @since 3.6.0
*/
class DBRepair {
/**
* Hook all the functionality.
*
* @since 3.6.0
*/
public function hooks() {
add_action( 'admin_init', [ $this, 'fix_missing_db_tables' ] );
add_action( 'admin_init', [ $this, 'verify_db_tables_after_fixing' ] );
}
/**
* Fixed the missing tables.
*
* @since 3.6.0
*/
public function fix_missing_db_tables() { // phpcs:ignore Generic.Metrics.NestingLevel.MaxExceeded
// Check if this is the request to create missing tables.
if (
isset( $_GET['create-missing-db-tables'] ) &&
$_GET['create-missing-db-tables'] === '1' &&
wp_mail_smtp()->get_admin()->is_admin_page() &&
current_user_can( wp_mail_smtp()->get_capability_manage_options() )
) {
check_admin_referer( Area::SLUG . '-create-missing-db-tables' );
$missing_tables = $this->get_missing_tables();
if ( ! empty( $missing_tables ) ) {
foreach ( $missing_tables as $missing_table ) {
$this->fix_missing_db_table( $missing_table );
}
$redirect_page = isset( $_GET['page'] ) ? sanitize_key( $_GET['page'] ) : Area::SLUG;
$redirect_url = add_query_arg(
[
'check-db-tables' => 1,
],
wp_mail_smtp()->get_admin()->get_admin_page_url( $redirect_page )
);
wp_safe_redirect( $redirect_url );
exit;
}
}
}
/**
* Update the Migration option to fix the missing table.
*
* @since 3.6.0
*
* @param string $missing_table The name of the table.
*/
protected function fix_missing_db_table( $missing_table ) {
if ( $missing_table === DebugEvents::get_table_name() ) {
update_option( DebugMigration::OPTION_NAME, 0 );
} elseif ( $missing_table === Meta::get_table_name() ) {
update_option( Migration::OPTION_NAME, 1 );
}
}
/**
* Default Unknown error message - If the table is not created.
*
* @since 3.6.0
*
* @return string
*/
protected function get_missing_table_default_error_message() {
$unknown_reason_msg = esc_html__( 'Unknown.', 'wp-mail-smtp' );
/**
* Filter the default error message for unknown reason.
*
* @since 3.6.0
*
* @param string $unknown_reason_msg The default unknown reason message.
*/
return apply_filters( 'wp_mail_smtp_db_repair_get_missing_table_default_error_message', $unknown_reason_msg );
}
/**
* Get the error message (Reason) if the table is missing.
*
* @since 3.6.0
*
* @param string $missing_table The table name that we are checking.
* @param array $reasons The array that holds all the error messages or reason.
*/
protected function get_error_message_for_missing_table( $missing_table, &$reasons ) {
$reason = '';
if ( $missing_table === DebugEvents::get_table_name() ) {
$reason .= $this->get_reason_output_message(
$missing_table,
get_option( DebugMigration::ERROR_OPTION_NAME, $this->get_missing_table_default_error_message() )
);
} elseif ( $missing_table === Meta::get_table_name() ) {
$reason .= $this->get_reason_output_message(
$missing_table,
get_option( Migration::ERROR_OPTION_NAME, $this->get_missing_table_default_error_message() )
);
}
$reasons[] = $reason;
}
/**
* Get the reason output message, why the DB table creation failed.
*
* @since 3.6.0
*
* @param string $table The DB table name.
* @param string $error_message The error message.
*
* @return string
*/
protected function get_reason_output_message( $table, $error_message ) {
return sprintf(
wp_kses( /* translators: %1$s - missing table name; %2$s - error message. */
__( '<strong>Table:</strong> %1$s. <strong>Reason:</strong> %2$s', 'wp-mail-smtp' ),
[
'strong' => [],
]
),
esc_html( $table ),
esc_html( $error_message )
);
}
/**
* Verify the tables.
* If there is any missing table then display the Admin Notice of error type.
* Else display the success message (Success Admin Notice).
*
* @since 3.6.0
*/
public function verify_db_tables_after_fixing() {
// Display success or error message based on if there is any missing table available or not.
if (
// phpcs:ignore WordPress.Security.NonceVerification.Recommended
isset( $_GET['check-db-tables'] ) && $_GET['check-db-tables'] === '1' &&
wp_mail_smtp()->get_admin()->is_admin_page() &&
current_user_can( wp_mail_smtp()->get_capability_manage_options() )
) {
$missing_tables = $this->get_missing_tables();
if ( empty( $missing_tables ) ) {
WP::add_admin_notice(
esc_html__( 'Missing DB tables were created successfully.', 'wp-mail-smtp' ),
WP::ADMIN_NOTICE_SUCCESS
);
return;
}
$reasons = [];
foreach ( $missing_tables as $missing_table ) {
$this->get_error_message_for_missing_table( $missing_table, $reasons );
}
$reasons = array_filter( $reasons ); // Filtering out the empty values.
if ( ! empty( $reasons ) ) {
$msg = sprintf(
wp_kses( /* translators: %1$s: Singular/Plural string, %2$s - the error messages from the migrations for the missing tables. */
__( 'The following DB %1$s still missing. <br />%2$s', 'wp-mail-smtp' ),
[
'br' => [],
]
),
_n( 'Table is', 'Tables are', count( $missing_tables ), 'wp-mail-smtp' ),
implode( '<br/>', $reasons )
);
$msg = sprintf(
wp_kses(
_n( 'The following DB table is still missing.', 'The following DB tables are still missing.', count( $missing_tables ), 'wp-mail-smtp' ) . '<br />%s',
[
'br' => [],
]
),
implode( '<br/>', $reasons )
);
} else {
$msg = esc_html__( 'Some DB Tables are still missing.', 'wp-mail-smtp' );
}
WP::add_admin_notice(
$msg,
WP::ADMIN_NOTICE_ERROR
);
}
}
/**
* Get the missing tables.
*
* @since 3.6.0
*
* @return array The array of the missing tables.
*/
protected function get_missing_tables() {
$site_health = new SiteHealth();
return $site_health->get_missing_db_tables();
}
}

View File

@@ -0,0 +1,199 @@
<?php
namespace WPMailSMTP;
use WPMailSMTP\Admin\DebugEvents\DebugEvents;
/**
* Class Debug that will save all errors or warnings generated by APIs or SMTP
* and display in area for administrators.
*
* Usage example:
* Debug::set( 'Some warning: %s', array( '%s' => $e->getMessage() );
* $debug = Debug::get(); // array
* $debug = Debug::get_last(); // string
*
* @since 1.2.0
*/
class Debug {
/**
* Key for options table where all messages will be saved to.
*
* @since 1.2.0
*/
const OPTION_KEY = 'wp_mail_smtp_debug';
/**
* Hold the cached error messages.
*
* @since 3.0.0
*
* @var array
*/
private static $cached_messages;
/**
* Save unique debug message to a debug log.
* Adds one more to a list, at the end.
*
* @since 1.2.0
* @since 3.0.0 Start saving the Debug Event IDs, instead of error messages.
* @since 3.5.0 Returns Event ID.
*
* @param mixed $message An array or string error message.
*
* @return bool|int
*/
public static function set( $message ) {
if ( empty( $message ) ) {
return false;
}
self::clear_cache();
// Log the error message to the Debug Events.
$event_id = DebugEvents::add( $message );
$all = self::get_raw();
if ( ! empty( $event_id ) ) {
array_push( $all, $event_id );
} else {
if ( ! is_string( $message ) ) {
$message = wp_json_encode( $message );
} else {
$message = wp_strip_all_tags( $message, false );
}
array_push( $all, $message );
}
update_option( self::OPTION_KEY, array_unique( $all ), false );
return $event_id;
}
/**
* Remove all messages for a debug log.
*
* @since 1.2.0
*/
public static function clear() {
self::clear_cache();
update_option( self::OPTION_KEY, [], false );
}
/**
* Clear cached error messages.
*
* @since 3.0.0
*/
private static function clear_cache() {
self::$cached_messages = null;
}
/**
* Get the raw DB debug option values.
*
* @since 3.0.0
*/
private static function get_raw() {
$all = get_option( self::OPTION_KEY, [] );
if ( ! is_array( $all ) ) {
$all = (array) $all;
}
return $all;
}
/**
* Retrieve all messages from a debug log.
*
* @since 1.2.0
*
* @return array
*/
public static function get() {
if ( isset( self::$cached_messages ) ) {
return self::$cached_messages;
}
$all = self::get_raw();
if ( empty( $all ) ) {
self::$cached_messages = [];
return [];
}
$event_ids = [];
$old_messages = [];
foreach ( $all as $item ) {
if ( is_int( $item ) ) {
$event_ids[] = (int) $item;
} else {
$old_messages[] = $item;
}
}
$event_messages = DebugEvents::get_debug_messages( $event_ids );
self::$cached_messages = array_unique( array_merge( $old_messages, $event_messages ) );
return self::$cached_messages;
}
/**
* Get the last message that was saved to a debug log.
*
* @since 1.2.0
*
* @return string
*/
public static function get_last() {
$all = self::get();
if ( ! empty( $all ) && is_array( $all ) ) {
return (string) end( $all );
}
return '';
}
/**
* Get the proper variable content output to debug.
*
* @since 1.2.0
*
* @param mixed $var Variable to output.
*
* @return string
*/
public static function pvar( $var = '' ) {
ob_start();
echo '<code>';
if ( is_bool( $var ) || empty( $var ) ) {
var_dump( $var );
} else {
print_r( $var );
}
echo '</code>';
$output = ob_get_clean();
return str_replace( array( "\r\n", "\r", "\n" ), '', $output );
}
}

View File

@@ -0,0 +1,225 @@
<?php
namespace WPMailSMTP;
/**
* Class Geo to work with location, domain, IPs etc.
*
* @since 1.5.0
*/
class Geo {
/**
* Get the current site hostname.
* In case of CLI we don't have SERVER_NAME, so use host name instead, may be not a domain name.
* Examples: example.com, localhost.
*
* @since 1.5.0
*
* @return string
*/
public static function get_site_domain() {
return ! empty( $_SERVER['SERVER_NAME'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_NAME'] ) ) : wp_parse_url( get_home_url( get_current_blog_id() ), PHP_URL_HOST );
}
/**
* Get the domain IP address.
* Uses gethostbyname() which is quite slow, but this is done only one time.
*
* @since 1.5.0
*
* @param string $domain
*
* @return string
*/
public static function get_ip_by_domain( $domain ) {
if ( $domain === 'localhost' ) {
return '127.0.0.1';
}
return gethostbyname( $domain );
}
/**
* Get the location coordinates by IP address.
* We make a request to 3rd party services.
*
* @since 1.5.0
* @since 1.6.0 Added new geo API endpoint, provided by WPForms.
* @since 2.0.0 Updated the WPForms geo API endpoint to v3.
*
* @param string $ip The IP address.
*
* @return array Empty array for localhost.
*/
public static function get_location_by_ip( $ip ) {
// Check for a non-local IP.
if ( empty( $ip ) || in_array( $ip, [ '127.0.0.1', '::1' ], true ) ) {
return [];
}
$request = wp_remote_get( 'https://geo.wpforms.com/v3/geolocate/json/' . $ip );
if ( ! is_wp_error( $request ) ) {
$request = json_decode( wp_remote_retrieve_body( $request ), true );
if ( ! empty( $request['latitude'] ) && ! empty( $request['longitude'] ) ) {
$data = [
'latitude' => sanitize_text_field( $request['latitude'] ),
'longitude' => sanitize_text_field( $request['longitude'] ),
'city' => isset( $request['city'] ) ? sanitize_text_field( $request['city'] ) : '',
'region' => isset( $request['region_name'] ) ? sanitize_text_field( $request['region_name'] ) : '',
'country' => isset( $request['country_iso'] ) ? sanitize_text_field( $request['country_iso'] ) : '',
'postal' => isset( $request['zip_code'] ) ? sanitize_text_field( $request['zip_code'] ) : '',
];
return $data;
}
}
$request = wp_remote_get( 'https://ipapi.co/' . $ip . '/json' );
if ( ! is_wp_error( $request ) ) {
$request = json_decode( wp_remote_retrieve_body( $request ), true );
if ( ! empty( $request['latitude'] ) && ! empty( $request['longitude'] ) ) {
$data = [
'latitude' => sanitize_text_field( $request['latitude'] ),
'longitude' => sanitize_text_field( $request['longitude'] ),
'city' => isset( $request['city'] ) ? sanitize_text_field( $request['city'] ) : '',
'region' => isset( $request['region'] ) ? sanitize_text_field( $request['region'] ) : '',
'country' => isset( $request['country'] ) ? sanitize_text_field( $request['country'] ) : '',
'postal' => isset( $request['postal'] ) ? sanitize_text_field( $request['postal'] ) : '',
];
return $data;
}
}
$request = wp_remote_get(
'https://tools.keycdn.com/geo.json?host=' . $ip,
[
'user-agent' => 'keycdn-tools:' . get_home_url(),
]
);
if ( ! is_wp_error( $request ) ) {
$request = json_decode( wp_remote_retrieve_body( $request ), true );
if ( ! empty( $request['data']['geo']['latitude'] ) && ! empty( $request['data']['geo']['longitude'] ) ) {
$data = [
'latitude' => sanitize_text_field( $request['data']['geo']['latitude'] ),
'longitude' => sanitize_text_field( $request['data']['geo']['longitude'] ),
'city' => isset( $request['data']['geo']['city'] ) ? sanitize_text_field( $request['data']['geo']['city'] ) : '',
'region' => isset( $request['data']['geo']['region_name'] ) ? sanitize_text_field( $request['data']['geo']['region_name'] ) : '',
'country' => isset( $request['data']['geo']['country_code'] ) ? sanitize_text_field( $request['data']['geo']['country_code'] ) : '',
'postal' => isset( $request['data']['geo']['postal_code'] ) ? sanitize_text_field( $request['data']['geo']['postal_code'] ) : '',
];
return $data;
}
}
return [];
}
/**
* This routine calculates the distance between two points (given the latitude/longitude of those points).
* Definitions: South latitudes are negative, east longitudes are positive.
*
* @see https://www.geodatasource.com/developers/php
*
* @since 1.5.0
*
* @param float $lat1 Latitude of point 1 (in decimal degrees).
* @param float $lon1 Longitude of point 1 (in decimal degrees).
* @param float $lat2 Latitude of point 2 (in decimal degrees).
* @param float $lon2 Longitude of point 2 (in decimal degrees).
* @param string $unit Supported values: M, K, N. Miles by default.
*
* @return float|int
*/
public static function get_distance_between( $lat1, $lon1, $lat2, $lon2, $unit = 'M' ) {
if ( ( $lat1 === $lat2 ) && ( $lon1 === $lon2 ) ) {
return 0;
}
$theta = $lon1 - $lon2;
$dist = sin( deg2rad( $lat1 ) ) * sin( deg2rad( $lat2 ) ) + cos( deg2rad( $lat1 ) ) * cos( deg2rad( $lat2 ) ) * cos( deg2rad( $theta ) );
$dist = acos( $dist );
$dist = rad2deg( $dist );
$miles = $dist * 60 * 1.1515;
$unit = strtoupper( $unit );
if ( $unit === 'K' ) {
return ( $miles * 1.609344 );
} elseif ( $unit === 'N' ) {
return ( $miles * 0.8684 );
}
return $miles;
}
/**
* Get the user IP address.
*
* @since 3.11.0
*
* Code based on the:
* - WordPress method \WP_Community_Events::get_unsafe_client_ip
* - Cloudflare documentation https://support.cloudflare.com/hc/en-us/articles/206776727
*
* @return string
*/
public static function get_ip() {
$ip = '127.0.0.1';
$address_headers = [
'HTTP_TRUE_CLIENT_IP',
'HTTP_CF_CONNECTING_IP',
'HTTP_X_REAL_IP',
'HTTP_CLIENT_IP',
'HTTP_X_FORWARDED_FOR',
'HTTP_X_FORWARDED',
'HTTP_X_CLUSTER_CLIENT_IP',
'HTTP_FORWARDED_FOR',
'HTTP_FORWARDED',
'REMOTE_ADDR',
];
foreach ( $address_headers as $header ) {
if ( empty( $_SERVER[ $header ] ) ) {
continue;
}
/*
* HTTP_X_FORWARDED_FOR can contain a chain of comma-separated addresses, with or without spaces.
* The first address is the original client. It can't be trusted for authenticity,
* but we don't need to for this purpose.
*/
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$address_chain = explode( ',', wp_unslash( $_SERVER[ $header ] ) );
$ip = filter_var( trim( $address_chain[0] ), FILTER_VALIDATE_IP );
break;
}
/**
* Filter detected IP address.
*
* @since 3.11.0
*
* @param string $ip IP address.
*/
return filter_var( apply_filters( 'wp_mail_smtp_geo_get_ip', $ip ), FILTER_VALIDATE_IP );
}
}

View File

@@ -0,0 +1,163 @@
<?php
namespace WPMailSMTP\Helpers;
/**
* Class for encryption functionality.
*
* @since 2.5.0
*
* @link https://www.php.net/manual/en/intro.sodium.php
*/
class Crypto {
/**
* Get a secret key for encrypt/decrypt.
*
* @since 2.5.0
*
* @param bool $create Should the key be created, if it does not exist yet.
*
* @return string|bool
*/
public static function get_secret_key( $create = false ) {
if ( defined( 'WPMS_CRYPTO_KEY' ) ) {
return WPMS_CRYPTO_KEY;
}
$secret_key = apply_filters( 'wp_mail_smtp_helpers_crypto_get_secret_key', get_option( 'wp_mail_smtp_mail_key' ) );
// If we already have the secret, send it back.
if ( false !== $secret_key ) {
return base64_decode( $secret_key ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
}
if ( $create ) {
// We don't have a secret, so let's generate one.
try {
$secret_key = sodium_crypto_secretbox_keygen(); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_secretbox_keygenFound
} catch ( \Exception $e ) {
$secret_key = wp_generate_password( SODIUM_CRYPTO_SECRETBOX_KEYBYTES ); // phpcs:ignore PHPCompatibility.Constants.NewConstants.sodium_crypto_secretbox_keybytesFound
}
add_option( 'wp_mail_smtp_mail_key', base64_encode( $secret_key ) ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
return $secret_key;
}
return false;
}
/**
* Encrypt a message.
*
* @since 2.5.0
*
* @param string $message Message to encrypt.
* @param string $key Encryption key.
*
* @return string
* @throws \Exception The exception object.
*/
public static function encrypt( $message, $key = '' ) {
if ( apply_filters( 'wp_mail_smtp_helpers_crypto_stop', false ) ) {
return $message;
}
// Create a nonce for this operation. It will be stored and recovered in the message itself.
// phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.random_bytesFound, PHPCompatibility.Constants.NewConstants.sodium_crypto_secretbox_noncebytesFound
$nonce = random_bytes( SODIUM_CRYPTO_SECRETBOX_NONCEBYTES );
if ( empty( $key ) ) {
$key = self::get_secret_key( true );
}
// Encrypt message and combine with nonce.
$cipher = base64_encode( // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
$nonce .
sodium_crypto_secretbox( // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_secretboxFound
$message,
$nonce,
$key
)
);
try {
sodium_memzero( $message ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.sodium_memzeroFound
sodium_memzero( $key ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.sodium_memzeroFound
} catch ( \Exception $e ) {
return $cipher;
}
return $cipher;
}
/**
* Decrypt a message.
* Returns encrypted message on any failure and the decrypted message on success.
*
* @since 2.5.0
*
* @param string $encrypted Encrypted message.
* @param string $key Encryption key.
*
* @return string
* @throws \Exception The exception object.
*/
public static function decrypt( $encrypted, $key = '' ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
if ( apply_filters( 'wp_mail_smtp_helpers_crypto_stop', false ) ) {
return $encrypted;
}
// Unpack base64 message.
$decoded = base64_decode( $encrypted ); // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
if ( false === $decoded ) {
return $encrypted;
}
// Include polyfill if mbstring PHP extension is not enabled.
if ( ! function_exists( 'mb_strlen' ) || ! function_exists( 'mb_substr' ) ) {
Helpers::include_mbstring_polyfill();
}
// phpcs:ignore PHPCompatibility.Constants.NewConstants.sodium_crypto_secretbox_noncebytesFound, PHPCompatibility.Constants.NewConstants.sodium_crypto_secretbox_macbytesFound
if ( mb_strlen( $decoded, '8bit' ) < ( SODIUM_CRYPTO_SECRETBOX_NONCEBYTES + SODIUM_CRYPTO_SECRETBOX_MACBYTES ) ) {
return $encrypted;
}
// Pull nonce and ciphertext out of unpacked message.
$nonce = mb_substr( $decoded, 0, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, '8bit' ); // phpcs:ignore PHPCompatibility.Constants.NewConstants.sodium_crypto_secretbox_noncebytesFound
$ciphertext = mb_substr( $decoded, SODIUM_CRYPTO_SECRETBOX_NONCEBYTES, null, '8bit' ); // phpcs:ignore PHPCompatibility.Constants.NewConstants.sodium_crypto_secretbox_noncebytesFound
$key = empty( $key ) ? self::get_secret_key() : $key;
if ( empty( $key ) ) {
return $encrypted;
}
// Decrypt it.
$message = sodium_crypto_secretbox_open( // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.sodium_crypto_secretbox_openFound
$ciphertext,
$nonce,
$key
);
// Check for decryption failures.
if ( false === $message ) {
return $encrypted;
}
try {
sodium_memzero( $ciphertext ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.sodium_memzeroFound
sodium_memzero( $key ); // phpcs:ignore PHPCompatibility.FunctionUse.NewFunctions.sodium_memzeroFound
} catch ( \Exception $e ) {
return $message;
}
return $message;
}
}

View File

@@ -0,0 +1,41 @@
<?php
namespace WPMailSMTP\Helpers;
/**
* Class for Database functionality.
*
* @since 3.6.0
*/
class DB {
/**
* The function is used to check if the given index exists in the given table.
*
* @since 3.6.0
*
* @param string $table The table name.
* @param string $index The index name.
*
* @return bool If index exists then return true else returns false.
*/
public static function index_exists( $table, $index ) {
global $wpdb;
$query = $wpdb->prepare(
'SELECT COUNT(1) IndexIsThere
FROM INFORMATION_SCHEMA.STATISTICS
WHERE table_schema = DATABASE()
AND table_name = %s
AND index_name = %s',
$table,
$index
);
// phpcs:ignore WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
$result = $wpdb->get_var( $query );
return $result === '1';
}
}

View File

@@ -0,0 +1,170 @@
<?php
namespace WPMailSMTP\Helpers;
use WPMailSMTP\Options;
use WPMailSMTP\WP;
use WP_Error;
/**
* Class with all the misc helper functions that don't belong elsewhere.
*
* @since 3.0.0
*/
class Helpers {
/**
* Check if the current active mailer has email send confirmation functionality.
*
* @since 3.0.0
*
* @return bool
*/
public static function mailer_without_send_confirmation() {
return ! in_array(
Options::init()->get( 'mail', 'mailer' ),
[
'sendlayer',
'smtpcom',
'sendinblue',
'mailgun',
'postmark',
'sparkpost',
],
true
);
}
/**
* Include mbstring polyfill.
*
* @since 3.1.0
*/
public static function include_mbstring_polyfill() {
static $included = false;
if ( $included === true ) {
return;
}
require_once wp_mail_smtp()->plugin_path . '/vendor_prefixed/symfony/polyfill-mbstring/Mbstring.php';
require_once wp_mail_smtp()->plugin_path . '/vendor_prefixed/symfony/polyfill-mbstring/bootstrap.php';
$included = true;
}
/**
* Test if the REST API is accessible.
*
* @since 3.3.0
*
* @return true|\WP_Error
*/
public static function test_rest_availability() {
$headers = [
'Cache-Control' => 'no-cache',
];
/** This filter is documented in wp-includes/class-wp-http-streams.php */
$sslverify = apply_filters( 'https_local_ssl_verify', false );
$url = rest_url( 'wp-mail-smtp/v1' );
$response = wp_remote_get(
$url,
[
'headers' => $headers,
'sslverify' => $sslverify,
]
);
if ( is_wp_error( $response ) ) {
return $response;
} elseif ( wp_remote_retrieve_response_code( $response ) !== 200 ) {
return new WP_Error( wp_remote_retrieve_response_code( $response ), wp_remote_retrieve_body( $response ) );
}
return true;
}
/**
* Get string size in bytes.
*
* @since 3.4.0
*
* @param string $str String.
*
* @return int
*/
public static function strsize( $str ) {
if ( ! function_exists( 'mb_strlen' ) ) {
self::include_mbstring_polyfill();
}
return mb_strlen( $str, '8bit' );
}
/**
* Format error message.
*
* @since 3.4.0
*
* @param string $message Error message.
* @param string $code Error code.
* @param string $description Error description.
*
* @return string
*/
public static function format_error_message( $message, $code = '', $description = '' ) {
$error_text = '';
if ( ! empty( $code ) ) {
$error_text .= $code . ': ';
}
if ( ! is_string( $message ) ) {
$error_text .= wp_json_encode( $message );
} else {
$error_text .= $message;
}
if ( ! empty( $description ) ) {
$error_text .= WP::EOL . $description;
}
return $error_text;
}
/**
* Get the default user agent.
*
* @since 3.9.0
*
* @return string
*/
public static function get_default_user_agent() {
$license_type = wp_mail_smtp()->get_license_type();
return 'WordPress/' . get_bloginfo( 'version' ) . '; ' . get_bloginfo( 'url' ) . '; WPMailSMTP/' . $license_type . '-' . WPMS_PLUGIN_VER;
}
/**
* Import Plugin_Upgrader class from core.
*
* @since 3.11.0
*/
public static function include_plugin_upgrader() {
/** \WP_Upgrader class */
require_once ABSPATH . 'wp-admin/includes/class-wp-upgrader.php';
/** \Plugin_Upgrader class */
require_once ABSPATH . 'wp-admin/includes/class-plugin-upgrader.php';
}
}

View File

@@ -0,0 +1,323 @@
<?php
namespace WPMailSMTP\Helpers;
/**
* Class for preparing import data from other SMTP plugins.
*
* @since 2.6.0
*/
class PluginImportDataRetriever {
/**
* The slug of the SMTP plugin to prepare the data for.
*
* @since 2.6.0
*
* @var string
*/
private $slug;
/**
* PluginImportDataRetriever constructor.
*
* @since 2.6.0
*
* @param string $slug The SMTP plugin slug.
*/
public function __construct( $slug ) {
$this->slug = $slug;
}
/**
* Get the data for the current plugin slug.
*
* @since 2.6.0
*
* @return false|array
*/
public function get() {
$method_name = preg_replace( '/[\-]/', '_', sanitize_key( "get_$this->slug" ) );
if ( method_exists( $this, $method_name ) ) {
return $this->$method_name();
}
return false;
}
/**
* Check if Easy WP SMTP plugin settings are present and extract them.
*
* @since 2.6.0
*
* @return array
*/
private function get_easy_smtp() {
$options = get_option( 'swpsmtp_options' );
if ( empty( $options ) ) {
return [];
}
return [
'mail' => [
'mailer' => 'smtp',
'from_email' => isset( $options['from_email_field'] ) ? $options['from_email_field'] : '',
'from_name' => isset( $options['from_name_field'] ) ? $options['from_name_field'] : '',
'from_name_force' => isset( $options['force_from_name_replace'] ) ? $options['force_from_name_replace'] : false,
],
'smtp' => [
'host' => isset( $options['smtp_settings']['host'] ) ? $options['smtp_settings']['host'] : '',
'encryption' => isset( $options['smtp_settings']['type_encryption'] ) ? $options['smtp_settings']['type_encryption'] : 'none',
'port' => isset( $options['smtp_settings']['port'] ) ? $options['smtp_settings']['port'] : 25,
'auth' => isset( $options['smtp_settings']['autentication'] ) ? $options['smtp_settings']['autentication'] : true,
'user' => isset( $options['smtp_settings']['username'] ) ? $options['smtp_settings']['username'] : '',
'pass' => '',
'autotls' => true,
],
];
}
/**
* Check if FluentSMTP plugin settings are present and extract them.
*
* @since 3.2.0
*
* @return array
*/
private function get_fluent_smtp() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
$options = get_option( 'fluentmail-settings' );
if ( empty( $options ) ) {
return [];
}
if ( empty( $options['misc']['default_connection'] ) || empty( $options['connections'][ $options['misc']['default_connection'] ]['provider_settings'] ) ) {
return [];
}
$fluent_data = $options['connections'][ $options['misc']['default_connection'] ]['provider_settings'];
$allowed_mailers = [
'smtp' => 'smtp',
'ses' => 'amazonses',
'mailgun' => 'mailgun',
'sendgrid' => 'sendgrid',
'sendinblue' => 'sendinblue',
'sparkpost' => 'sparkpost',
'postmark' => 'postmark',
'outlook' => 'outlook',
];
if ( empty( $fluent_data['provider'] ) || ! in_array( $fluent_data['provider'], array_keys( $allowed_mailers ), true ) ) {
return [];
}
$data = [
'mail' => [
'mailer' => $allowed_mailers[ $fluent_data['provider'] ],
'from_email' => isset( $fluent_data['sender_email'] ) ? $fluent_data['sender_email'] : '',
'from_name' => isset( $fluent_data['sender_name'] ) ? $fluent_data['sender_name'] : '',
'from_email_force' => isset( $fluent_data['force_from_email'] ) && $fluent_data['force_from_email'] === 'yes',
'from_name_force' => isset( $fluent_data['force_from_name'] ) && $fluent_data['force_from_name'] === 'yes',
],
];
switch ( $data['mail']['mailer'] ) {
case 'smtp':
$data['smtp'] = [
'host' => isset( $fluent_data['host'] ) ? $fluent_data['host'] : '',
'encryption' => isset( $fluent_data['encryption'] ) && in_array( $fluent_data['encryption'], [ 'none', 'ssl', 'tls' ], true ) ? $fluent_data['encryption'] : 'none',
'port' => isset( $fluent_data['port'] ) ? $fluent_data['port'] : 25,
'auth' => isset( $fluent_data['auth'] ) && $fluent_data['auth'] === 'yes',
'user' => isset( $fluent_data['username'] ) ? $fluent_data['username'] : '',
'pass' => isset( $fluent_data['password'] ) ? $fluent_data['password'] : '',
'autotls' => isset( $fluent_data['auto_tls'] ) && $fluent_data['auto_tls'] === 'yes',
];
break;
case 'amazonses':
$data['amazonses'] = [
'client_id' => isset( $fluent_data['access_key'] ) ? $fluent_data['access_key'] : '',
'client_secret' => isset( $fluent_data['secret_key'] ) ? $fluent_data['secret_key'] : '',
'region' => isset( $fluent_data['region'] ) ? $fluent_data['region'] : '',
];
break;
case 'mailgun':
$data['mailgun'] = [
'api_key' => isset( $fluent_data['api_key'] ) ? $fluent_data['api_key'] : '',
'domain' => isset( $fluent_data['domain_name'] ) ? $fluent_data['domain_name'] : '',
'region' => isset( $fluent_data['region'] ) && in_array( $fluent_data['region'], [ 'us', 'eu' ], true ) ? strtoupper( $fluent_data['region'] ) : '',
];
break;
case 'sendgrid':
$data['sendgrid'] = [
'api_key' => isset( $fluent_data['api_key'] ) ? $fluent_data['api_key'] : '',
];
break;
case 'sendinblue':
$data['sendinblue'] = [
'api_key' => isset( $fluent_data['api_key'] ) ? $fluent_data['api_key'] : '',
];
break;
case 'sparkpost':
$data['sparkpost'] = [
'api_key' => isset( $fluent_data['api_key'] ) ? $fluent_data['api_key'] : '',
];
break;
case 'postmark':
$data['postmark'] = [
'api_key' => isset( $fluent_data['api_key'] ) ? $fluent_data['api_key'] : '',
'message_stream' => isset( $fluent_data['message_stream'] ) ? $fluent_data['message_stream'] : '',
];
break;
case 'outlook':
$data['outlook'] = [
'client_id' => isset( $fluent_data['client_id'] ) ? $fluent_data['client_id'] : '',
'client_secret' => isset( $fluent_data['client_secret'] ) ? $fluent_data['client_secret'] : '',
];
break;
}
return $data;
}
/**
* Check if Post SMTP Mailer plugin settings are present and extract them.
*
* @since 2.6.0
*
* @return array
*/
private function get_post_smtp_mailer() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
$options = get_option( 'postman_options' );
if ( empty( $options ) ) {
return [];
}
$allowed_mailers = [
'smtp' => 'smtp',
'gmail_api' => 'gmail',
'sendgrid_api' => 'sendgrid',
'mailgun_api' => 'mailgun',
];
$data = [
'mail' => [
'mailer' => ( isset( $options['transport_type'] ) && in_array( $options['transport_type'], array_keys( $allowed_mailers ), true ) ) ? $allowed_mailers[ $options['transport_type'] ] : 'mail',
'from_email' => isset( $options['sender_email'] ) ? $options['sender_email'] : '',
'from_name' => isset( $options['sender_name'] ) ? $options['sender_name'] : '',
],
'smtp' => [
'host' => isset( $options['hostname'] ) ? $options['hostname'] : '',
'encryption' => isset( $options['enc_type'] ) ? $options['enc_type'] : 'none',
'port' => isset( $options['port'] ) ? $options['port'] : 25,
'auth' => isset( $options['auth_type'] ) && $options['auth_type'] !== 'none',
'user' => isset( $options['basic_auth_username'] ) ? $options['basic_auth_username'] : '',
'pass' => ! empty( $options['basic_auth_password'] ) ? base64_decode( $options['basic_auth_password'] ) : '', // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
'autotls' => true,
],
'gmail' => [
'client_id' => isset( $options['oauth_client_id'] ) ? $options['oauth_client_id'] : '',
'client_secret' => isset( $options['oauth_client_secret'] ) ? $options['oauth_client_secret'] : '',
],
'sendgrid' => [
'api_key' => ! empty( $options['sendgrid_api_key'] ) ? base64_decode( $options['sendgrid_api_key'] ) : '', // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
],
'mailgun' => [
'api_key' => ! empty( $options['mailgun_api_key'] ) ? base64_decode( $options['mailgun_api_key'] ) : '', // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
'domain' => isset( $options['mailgun_domain_name'] ) ? $options['mailgun_domain_name'] : '',
'region' => ( isset( $options['mailgun_region'] ) && ! empty( $options['mailgun_region'] ) ) ? 'EU' : 'US',
],
];
if ( class_exists( '\PostmanOptions' ) ) {
$pm_options = \PostmanOptions::getInstance();
$data['sendgrid']['api_key'] = $pm_options->getSendGridApiKey();
$data['mailgun']['api_key'] = $pm_options->getMailgunApiKey();
$data['smtp']['pass'] = $pm_options->getPassword();
}
return $data;
}
/**
* Check if SMTP Mailer plugin settings are present and extract them.
*
* @since 2.6.0
*
* @return array
*/
private function get_smtp_mailer() {
$options = get_option( 'smtp_mailer_options' );
if ( empty( $options ) ) {
return [];
}
return [
'mail' => [
'mailer' => 'smtp',
'from_email' => isset( $options['from_email'] ) ? $options['from_email'] : '',
'from_name' => isset( $options['from_name'] ) ? $options['from_name'] : '',
],
'smtp' => [
'host' => isset( $options['smtp_host'] ) ? $options['smtp_host'] : '',
'encryption' => isset( $options['type_of_encryption'] ) ? $options['type_of_encryption'] : 'none',
'port' => isset( $options['smtp_port'] ) ? $options['smtp_port'] : 25,
'auth' => isset( $options['smtp_auth'] ) && $options['smtp_auth'] === 'true',
'user' => isset( $options['smtp_username'] ) ? $options['smtp_username'] : '',
'pass' => ! empty( $options['smtp_password'] ) ? base64_decode( $options['smtp_password'] ) : '', // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
'autotls' => true,
],
];
}
/**
* Check if WP SMTP plugin settings are present and extract them.
*
* @since 2.6.0
*
* @return array
*/
private function get_wp_smtp() {
$options = get_option( 'wp_smtp_options' );
if ( empty( $options ) ) {
return [];
}
return [
'mail' => [
'mailer' => 'smtp',
'from_email' => isset( $options['from'] ) ? $options['from'] : '',
'from_name' => isset( $options['fromname'] ) ? $options['fromname'] : '',
],
'smtp' => [
'host' => isset( $options['host'] ) ? $options['host'] : '',
'encryption' => ! empty( $options['smtpsecure'] ) ? $options['smtpsecure'] : 'none',
'port' => isset( $options['port'] ) ? $options['port'] : 25,
'auth' => isset( $options['smtpauth'] ) && $options['smtpauth'] === 'yes',
'user' => isset( $options['username'] ) ? $options['username'] : '',
'pass' => isset( $options['password'] ) ? $options['password'] : '',
'autotls' => true,
],
];
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace WPMailSMTP\Helpers;
/**
* Reusable interface components.
*
* @since 3.10.0
*/
class UI {
/**
* Toggle component.
*
* @since 3.10.0
*
* @param array $args {
* Toggle parameters.
*
* @type string $name Name attribute of the toggle's input element. Default ''.
* @type string $value Value attribute of the toggle's input element. Default 'yes'.
* @type string|string[] $label Single label, or a 2-elements array of on/off labels. Default ''.
* @type string $id ID attribute of the toggle's container element. Default ''.
* @type string $class Class attribute of the toggle's container element. Default ''.
* @type bool $checked Checked attribute of the toggle's input element. Default false.
* @type bool $disabled Disabled attribute of the toggle's input element. Default false.
* }
*/
public static function toggle( $args = [] ) {
$args = wp_parse_args(
$args,
[
'name' => '',
'value' => 'yes',
'label' => [
esc_html__( 'On', 'wp-mail-smtp' ),
esc_html__( 'Off', 'wp-mail-smtp' ),
],
'id' => '',
'class' => '',
'checked' => false,
'disabled' => false,
]
);
?>
<label class="wp-mail-smtp-toggle">
<input type="checkbox"
name="<?php echo esc_attr( $args['name'] ); ?>"
<?php echo empty( $args['class'] ) ? '' : ' class="' . esc_attr( $args['class'] ) . '"'; ?>
<?php echo empty( $args['id'] ) ? '' : ' id="' . esc_attr( $args['id'] ) . '"'; ?>
value="<?php echo esc_attr( $args['value'] ); ?>"
<?php checked( (bool) $args['checked'] ); ?>
<?php disabled( (bool) $args['disabled'] ); ?> />
<span class="wp-mail-smtp-toggle__switch"></span>
<?php if ( is_array( $args['label'] ) ) : ?>
<?php if ( count( $args['label'] ) > 0 ) : ?>
<span class="wp-mail-smtp-toggle__label wp-mail-smtp-toggle__label--checked"><?php echo esc_html( $args['label'][0] ); ?></span>
<?php endif; ?>
<?php if ( count( $args['label'] ) > 1 ) : ?>
<span class="wp-mail-smtp-toggle__label wp-mail-smtp-toggle__label--unchecked"><?php echo esc_html( $args['label'][1] ); ?></span>
<?php endif; ?>
<?php else : ?>
<span class="wp-mail-smtp-toggle__label wp-mail-smtp-toggle__label--static"><?php echo esc_html( $args['label'] ); ?></span>
<?php endif; ?>
</label>
<?php
}
}

View File

@@ -0,0 +1,57 @@
<?php
namespace WPMailSMTP;
// Load PHPMailer class, so we can subclass it.
if ( ! class_exists( 'PHPMailer', false ) ) {
require_once ABSPATH . WPINC . '/class-phpmailer.php';
}
/**
* 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.
*
* @since 1.0.0
*/
class MailCatcher extends \PHPMailer implements MailCatcherInterface {
use MailCatcherTrait;
/**
* Callback Action function name.
*
* The function that handles the result of the send email action.
* It is called out by send() for each email sent.
*
* @since 1.3.0
*
* @var string
*/
public $action_function = '\WPMailSMTP\Processor::send_callback';
/**
* Returns all custom headers.
* 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; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
}
/**
* Get the PHPMailer line ending.
*
* @since 2.2.0
*
* @return string
*/
public function get_line_ending() {
return $this->LE; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
}
}

View File

@@ -0,0 +1,69 @@
<?php
namespace WPMailSMTP;
/**
* Interface MailCatcherInterface.
*
* @since 2.2.0
*/
interface MailCatcherInterface {
/**
* Modify the default send() behaviour.
* For those mailers, that relies on PHPMailer class - call it directly.
* For others - init the correct provider and process it.
*
* @since 2.2.0
*
* @throws \phpmailerException|\PHPMailer\PHPMailer\Exception When sending via PhpMailer fails for some reason.
*
* @return bool
*/
public function send();
/**
* Get the PHPMailer line ending.
*
* @since 2.2.0
*
* @return string
*/
public function get_line_ending();
/**
* Create a unique ID to use for multipart email boundaries.
*
* @since 2.4.0
*
* @return string
*/
public function generate_id();
/**
* Get debug event ID.
*
* @since 3.5.0
*
* @return bool|int
*/
public function get_debug_event_id();
/**
* Whether the current email is a test email.
*
* @since 3.5.0
*
* @return bool
*/
public function is_test_email();
/**
* Whether the current email is a Setup Wizard test email.
*
* @since 3.5.0
*
* @return bool
*/
public function is_setup_wizard_test_email();
}

View File

@@ -0,0 +1,396 @@
<?php
namespace WPMailSMTP;
use Exception;
use WPMailSMTP\Admin\DebugEvents\DebugEvents;
use WPMailSMTP\Providers\MailerAbstract;
/**
* Trait MailCatcherTrait.
*
* @since 3.7.0
*/
trait MailCatcherTrait {
/**
* Debug output buffer.
*
* @since 3.3.0
*
* @var array
*/
private $debug_output_buffer = [];
/**
* Debug event ID.
*
* @since 3.5.0
*
* @var int
*/
private $debug_event_id = false;
/**
* Whether the current email is a test email.
*
* @since 3.5.0
*
* @var bool
*/
private $is_test_email = false;
/**
* Whether the current email is a Setup Wizard test email.
*
* @since 3.5.0
*
* @var bool
*/
private $is_setup_wizard_test_email = false;
/**
* Whether the current email is blocked to be sent.
*
* @since 3.8.0
*
* @var bool
*/
private $is_emailing_blocked = false;
/**
* Holds the most recent error message.
*
* @since 3.7.0
*
* @var string
*/
protected $latest_error = '';
/**
* Modify the default send() behaviour.
* For those mailers, that relies on PHPMailer class - call it directly.
* For others - init the correct provider and process it.
*
* @since 1.0.0
* @since 1.4.0 Process "Do Not Send" option, but always allow test email.
*
* @throws Exception When sending via PhpMailer fails for some reason.
*
* @return bool
*/
public function send() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded, Generic.Metrics.NestingLevel.MaxExceeded
$connection = wp_mail_smtp()->get_connections_manager()->get_mail_connection();
$mail_mailer = $connection->get_mailer_slug();
// Reset email related variables.
$this->debug_event_id = false;
$this->is_test_email = false;
$this->is_setup_wizard_test_email = false;
$this->is_emailing_blocked = false;
$this->latest_error = '';
if ( wp_mail_smtp()->is_blocked() ) {
$this->is_emailing_blocked = true;
}
// Always allow a test email - check for the specific header.
foreach ( (array) $this->getCustomHeaders() as $header ) {
if (
! empty( $header[0] ) &&
! empty( $header[1] ) &&
$header[0] === 'X-Mailer-Type'
) {
if ( trim( $header[1] ) === 'WPMailSMTP/Admin/Test' ) {
$this->is_emailing_blocked = false;
$this->is_test_email = true;
} elseif ( trim( $header[1] ) === 'WPMailSMTP/Admin/SetupWizard/Test' ) {
$this->is_setup_wizard_test_email = true;
}
}
}
// Do not send emails if admin desired that.
if ( $this->is_emailing_blocked ) {
return false;
}
// Define a custom header, that will be used to identify the plugin and the mailer.
$this->XMailer = 'WPMailSMTP/Mailer/' . $mail_mailer . ' ' . WPMS_PLUGIN_VER; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
// Use the default PHPMailer, as we inject our settings there for certain providers.
if (
$mail_mailer === 'mail' ||
$mail_mailer === 'smtp' ||
$mail_mailer === 'pepipost'
) {
try {
if ( DebugEvents::is_debug_enabled() && ! $this->is_test_email ) {
$this->SMTPDebug = 3; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
$this->Debugoutput = [ $this, 'debug_output_callback' ]; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
}
/**
* Fires before email pre send via SMTP.
*
* Allow to hook early to catch any early failed emails.
*
* @since 2.9.0
*
* @param MailCatcherInterface $mailcatcher The MailCatcher object.
*/
do_action( 'wp_mail_smtp_mailcatcher_smtp_pre_send_before', $this );
// Prepare all the headers.
if ( ! $this->preSend() ) {
return false;
}
/**
* Fires before email send via SMTP.
*
* Allow to hook after all the preparation before the actual sending.
*
* @since 2.9.0
*
* @param MailCatcherInterface $mailcatcher The MailCatcher object.
*/
do_action( 'wp_mail_smtp_mailcatcher_smtp_send_before', $this );
$post_send = $this->postSend();
DebugEvents::add_debug(
esc_html__( 'An email request was sent.', 'wp-mail-smtp' )
);
return $post_send;
} catch ( Exception $e ) {
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
$this->mailHeader = '';
$this->setError( $e->getMessage() );
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
$error_message = 'Mailer: ' . esc_html( wp_mail_smtp()->get_providers()->get_options( $mail_mailer )->get_title() ) . "\r\n" . $this->ErrorInfo;
// Set the debug error, but not for default PHP mailer.
if ( $mail_mailer !== 'mail' ) {
$this->debug_event_id = Debug::set( $error_message );
$this->latest_error = $error_message;
if ( DebugEvents::is_debug_enabled() && ! empty( $this->debug_output_buffer ) ) {
$debug_message = $error_message . "\r\n" . esc_html__( 'Debug Output:', 'wp-mail-smtp' ) . "\r\n";
$debug_message .= implode( "\r\n", $this->debug_output_buffer );
$this->debug_event_id = DebugEvents::add_debug( $debug_message );
}
}
/**
* Fires after email sent failure via SMTP.
*
* @since 3.5.0
*
* @param string $error_message Error message.
* @param MailCatcherInterface $mailcatcher The MailCatcher object.
* @param string $mail_mailer Current mailer name.
*/
do_action( 'wp_mail_smtp_mailcatcher_send_failed', $error_message, $this, $mail_mailer );
if ( $this->exceptions ) {
throw $e;
}
return false;
} finally {
// Clear debug output buffer.
$this->debug_output_buffer = [];
}
}
// We need this so that the \PHPMailer class will correctly prepare all the headers.
$this->Mailer = 'mail'; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
/**
* Fires before email pre send.
*
* Allow to hook early to catch any early failed emails.
*
* @since 2.9.0
*
* @param MailCatcherInterface $mailcatcher The MailCatcher object.
*/
do_action( 'wp_mail_smtp_mailcatcher_pre_send_before', $this );
// Prepare everything (including the message) for sending.
if ( ! $this->preSend() ) {
return false;
}
$mailer = wp_mail_smtp()->get_providers()->get_mailer( $mail_mailer, $this, $connection );
if ( ! $mailer ) {
return false;
}
if ( ! $mailer->is_php_compatible() ) {
return false;
}
/**
* Fires before email send.
*
* Allows to hook after all the preparation before the actual sending.
*
* @since 3.3.0
*
* @param MailerAbstract $mailer The Mailer object.
*/
do_action( 'wp_mail_smtp_mailcatcher_send_before', $mailer );
/*
* Send the actual email.
* We reuse everything, that was preprocessed for usage in \PHPMailer.
*/
$mailer->send();
$is_sent = $mailer->is_email_sent();
if ( ! $is_sent ) {
$error = $mailer->get_response_error();
$error_message = '';
if ( ! empty( $error ) ) {
// Add mailer to the beginning and save to display later.
$message = 'Mailer: ' . esc_html( wp_mail_smtp()->get_providers()->get_options( $mailer->get_mailer_name() )->get_title() ) . "\r\n";
$conflicts = new Conflicts();
if ( $conflicts->is_detected() ) {
$conflict_plugin_names = implode( ', ', $conflicts->get_all_conflict_names() );
$message .= 'Conflicts: ' . esc_html( $conflict_plugin_names ) . "\r\n";
}
$error_message = $message . $error;
$this->debug_event_id = Debug::set( $error_message );
$this->latest_error = $error_message;
}
/**
* Fires after email sent failure.
*
* @since 3.5.0
*
* @param string $error_message Error message.
* @param MailCatcherInterface $mailcatcher The MailCatcher object.
* @param string $mail_mailer Current mailer name.
*/
do_action( 'wp_mail_smtp_mailcatcher_send_failed', $error_message, $this, $mail_mailer );
} else {
// Clear debug messages if email is successfully sent.
Debug::clear();
}
/**
* Fires after email send.
*
* Allow to perform any actions with the data.
*
* @since 3.5.0
*
* @param MailerAbstract $mailer The Mailer object.
* @param MailCatcherInterface $mailcatcher The MailCatcher object.
*/
do_action( 'wp_mail_smtp_mailcatcher_send_after', $mailer, $this );
return $is_sent;
}
/**
* Create a unique ID to use for multipart email boundaries.
*
* @since 2.4.0
*
* @return string
*/
public function generate_id() {
return $this->generateId();
}
/**
* Debug output callback.
* Save debugging info to buffer array.
*
* @since 3.3.0
*
* @param string $str Message.
* @param int $level Debug level.
*/
public function debug_output_callback( $str, $level ) {
/*
* Filter out all higher levels than 3.
* SMTPDebug level 3 is commands, data and connection status.
*/
if ( $level > 3 ) {
return;
}
$this->debug_output_buffer[] = trim( $str, "\r\n" );
}
/**
* Get debug event ID.
*
* @since 3.5.0
*
* @return bool|int
*/
public function get_debug_event_id() {
return $this->debug_event_id;
}
/**
* Whether the current email is a test email.
*
* @since 3.5.0
*
* @return bool
*/
public function is_test_email() {
return $this->is_test_email;
}
/**
* Whether the current email is a Setup Wizard test email.
*
* @since 3.5.0
*
* @return bool
*/
public function is_setup_wizard_test_email() {
return $this->is_setup_wizard_test_email;
}
/**
* Whether the current email is blocked to be sent.
*
* @since 3.8.0
*
* @return bool
*/
public function is_emailing_blocked() {
return $this->is_emailing_blocked;
}
}

View File

@@ -0,0 +1,50 @@
<?php
namespace WPMailSMTP;
/**
* Class MailCatcher replaces the \PHPMailer\PHPMailer\PHPMailer introduced in WP 5.5 and
* modifies the email sending logic. Thus, we can use other mailers API to do what we need, or stop emails completely.
*
* @since 2.2.0
*/
class MailCatcherV6 extends \PHPMailer\PHPMailer\PHPMailer implements MailCatcherInterface {
use MailCatcherTrait;
/**
* Callback Action function name.
*
* The function that handles the result of the send email action.
* It is called out by send() for each email sent.
*
* @since 2.2.0
*
* @var string
*/
public $action_function = '\WPMailSMTP\Processor::send_callback';
/**
* Which validator to use by default when validating email addresses.
* We are using built-in WordPress function `is_email` to validate the email address.
*
* @see PHPMailer::validateAddress()
*
* @since 3.6.0
*
* @var string|callable
*/
public static $validator = [ Processor::class, 'is_email_callback' ];
/**
* Get the PHPMailer line ending.
*
* @since 2.2.0
*
* @return string
*/
public function get_line_ending() {
return static::$LE; // phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
}
}

View File

@@ -0,0 +1,517 @@
<?php
namespace WPMailSMTP;
use WPMailSMTP\Reports\Emails\Summary as SummaryReportEmail;
use WPMailSMTP\Tasks\Meta;
use WPMailSMTP\Tasks\Reports\SummaryEmailTask as SummaryReportEmailTask;
use WPMailSMTP\Tasks\Tasks;
/**
* Class Migration helps migrate plugin options, DB tables and more.
*
* @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).
* @since 3.0.0 Extends MigrationAbstract.
*/
class Migration extends MigrationAbstract {
/**
* Version of the latest migration.
*
* @since 2.1.0
*/
const VERSION = 5;
/**
* Option key where we save the current migration version.
*
* @since 2.1.0
*/
const OPTION_NAME = 'wp_mail_smtp_migration_version';
/**
* Current migration version, received from static::OPTION_NAME WP option.
*
* @since 2.1.0
*
* @var int
*/
protected $cur_ver;
/**
* All old values for pre 1.0 version of a plugin.
*
* @since 1.0.0
*
* @var array
*/
protected $old_keys = array(
'pepipost_ssl',
'pepipost_port',
'pepipost_pass',
'pepipost_user',
'smtp_pass',
'smtp_user',
'smtp_auth',
'smtp_ssl',
'smtp_port',
'smtp_host',
'mail_set_return_path',
'mailer',
'mail_from_name',
'mail_from',
'wp_mail_smtp_am_notifications_hidden',
);
/**
* Old values, taken from $old_keys options.
*
* @since 1.0.0
*
* @var array
*/
protected $old_values = array();
/**
* Converted array of data from previous option values.
*
* @since 1.0.0
*
* @var array
*/
protected $new_values = array();
/**
* Initialize migration.
*
* @since 3.0.0
*/
public function init() {
$this->maybe_migrate();
}
/**
* Static on purpose, to get current migration version without __construct() and validation.
*
* @since 2.1.0
*
* @return int
*/
public static function get_cur_version() {
return (int) get_option( static::OPTION_NAME, 0 );
}
/**
* Run the migration if needed.
*
* @since 2.1.0
*/
protected function maybe_migrate() {
if ( version_compare( $this->cur_ver, static::VERSION, '<' ) ) {
$this->run( static::VERSION );
}
}
/**
* Actual migration launcher.
*
* @since 2.1.0
*
* @param int $version The version of migration to run.
*/
protected function run( $version ) {
$function_version = (int) $version;
if ( method_exists( $this, 'migrate_to_' . $function_version ) ) {
$this->{'migrate_to_' . $function_version}();
} else {
if ( WP::in_wp_admin() ) {
$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' ),
'<strong>WP Mail SMTP</strong>',
'<code>migration from v' . static::get_cur_version() . ' to v' . static::VERSION . ' failed. Plugin version: v' . WPMS_PLUGIN_VER . '</code>'
);
WP::add_admin_notice( $message, WP::ADMIN_NOTICE_ERROR );
}
}
}
/**
* Update migration version in options table.
*
* @since 2.1.0
*
* @param int $version Migration version.
*/
protected function update_db_ver( $version = 0 ) {
if ( empty( $version ) ) {
$version = static::VERSION;
}
// Autoload it, because this value is checked all the time
// and no need to request it separately from all autoloaded options.
update_option( static::OPTION_NAME, $version, true );
}
/**
* Prevent running the same migration twice.
* Run migration only when required.
*
* @since 2.1.0
*
* @param string $version The version of migration to check for potential execution.
*/
protected function maybe_required_older_migrations( $version ) {
if ( version_compare( $this->cur_ver, $version, '<' ) ) {
$this->run( $version );
}
}
/**
* Migration from 0.x to 1.0.0.
* Move separate plugin WP options to one main plugin WP option setting.
*
* @since 2.1.0
*/
private function migrate_to_1() {
if ( $this->is_migrated() ) {
return;
}
$this->old_values = $this->get_old_values();
$this->new_values = $this->get_converted_options();
Options::init()->set( $this->new_values, true );
$this->update_db_ver( 1 );
}
/**
* Migration from 1.x to 2.1.0.
* Create Tasks\Meta table, if it does not exist.
*
* @since 2.1.0
*/
private function migrate_to_2() {
$this->maybe_required_older_migrations( 1 );
$meta = new Meta();
// Create the table if it doesn't exist.
if ( $meta && ! $meta->table_exists() ) {
$meta->create_table();
}
$this->update_db_ver( 2 );
}
/**
* Migration to 2.6.0.
* Cancel all recurring ActionScheduler tasks, so they will be newly created and no longer
* cause PHP fatal error on PHP 8 (because of the named parameter 'tasks_meta_id').
*
* @since 2.6.0
*/
private function migrate_to_3() {
$this->maybe_required_older_migrations( 2 );
$tasks = [];
$ut = new UsageTracking\UsageTracking();
if ( $ut->is_enabled() ) {
$tasks[] = '\WPMailSMTP\UsageTracking\SendUsageTask';
}
$recurring_tasks = apply_filters( 'wp_mail_smtp_migration_cancel_recurring_tasks', $tasks );
foreach ( $recurring_tasks as $task ) {
( new $task() )->cancel();
}
$this->update_db_ver( 3 );
}
/**
* Migration to 3.0.0.
* Disable summary report email for Lite users and Multisite installations after update.
* For new installations we have default values in Options::get_defaults.
*
* @since 3.0.0
*/
protected function migrate_to_4() {
$this->maybe_required_older_migrations( 3 );
$options = Options::init();
$value = $options->get( 'general', SummaryReportEmail::SETTINGS_SLUG );
// If option was not already set, then plugin was updated from lower version.
if (
( $value === '' || $value === null ) &&
( is_multisite() || ! wp_mail_smtp()->is_pro() )
) {
$data = [
'general' => [
SummaryReportEmail::SETTINGS_SLUG => true,
],
];
$options->set( $data, false, false );
// Just to be safe cancel summary report email task.
( new SummaryReportEmailTask() )->cancel();
}
$this->update_db_ver( 4 );
}
/**
* Cleanup scheduled actions meta table.
*
* @since 3.5.0
*/
protected function migrate_to_5() {
$this->maybe_required_older_migrations( 4 );
global $wpdb;
$meta = new Meta();
if (
$meta->table_exists() &&
$meta->table_exists( $wpdb->prefix . 'actionscheduler_actions' ) &&
$meta->table_exists( $wpdb->prefix . 'actionscheduler_groups' )
) {
$group = Tasks::GROUP;
$sql = "SELECT DISTINCT a.args FROM {$wpdb->prefix}actionscheduler_actions a
JOIN {$wpdb->prefix}actionscheduler_groups g ON g.group_id = a.group_id
WHERE g.slug = '$group' AND a.status IN ('pending', 'in-progress')";
// phpcs:disable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
$results = $wpdb->get_results( $sql, 'ARRAY_A' );
// phpcs:enable WordPress.DB.DirectDatabaseQuery.NoCaching, WordPress.DB.PreparedSQL.NotPrepared
$results = $results ? $results : [];
$meta_ids = [];
foreach ( $results as $result ) {
$args = isset( $result['args'] ) ? json_decode( $result['args'], true ) : null;
if ( $args && isset( $args[0] ) && is_numeric( $args[0] ) ) {
$meta_ids[] = $args[0];
}
}
$table = Meta::get_table_name();
$not_in = 0;
if ( ! empty( $meta_ids ) ) {
// phpcs:ignore WordPress.DB.PreparedSQL.NotPrepared
$not_in = $wpdb->prepare( implode( ',', array_fill( 0, count( $meta_ids ), '%d' ) ), $meta_ids );
}
// phpcs:disable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
$wpdb->query( "DELETE FROM $table WHERE id NOT IN ($not_in)" );
// phpcs:enable WordPress.DB.PreparedSQL.InterpolatedNotPrepared, WordPress.DB.DirectDatabaseQuery.NoCaching
}
// Save the current version to DB.
$this->update_db_ver( 5 );
}
/**
* Whether we already migrated or not.
*
* @since 1.0.0
*
* @return bool
*/
protected function is_migrated() {
$is_migrated = false;
$new_values = get_option( Options::META_KEY, array() );
if ( ! empty( $new_values ) ) {
$is_migrated = true;
}
return $is_migrated;
}
/**
* Get all old values from DB.
*
* @since 1.0.0
*
* @return array
*/
protected function get_old_values() {
$old_values = array();
foreach ( $this->old_keys as $old_key ) {
$value = get_option( $old_key, '' );
if ( ! empty( $value ) ) {
$old_values[ $old_key ] = $value;
}
}
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'] = ! empty( $old_value ) ? $old_value : 'mail';
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

@@ -0,0 +1,161 @@
<?php
namespace WPMailSMTP;
/**
* Class MigrationAbstract helps migrate plugin options, DB tables and more.
*
* @since 3.0.0
*/
abstract class MigrationAbstract {
/**
* Version of the latest migration.
*
* @since 3.0.0
*/
const DB_VERSION = 1;
/**
* Option key where we save the current migration version.
*
* @since 3.0.0
*/
const OPTION_NAME = 'wp_mail_smtp_migration_version';
/**
* Option key where we save any errors while performing migration.
*
* @since 3.0.0
*/
const ERROR_OPTION_NAME = 'wp_mail_smtp_migration_error';
/**
* Current migration version, received from static::OPTION_NAME WP option
*
* @since 3.0.0
*
* @var int
*/
protected $cur_ver;
/**
* Migration constructor.
*
* @since 3.0.0
*/
public function __construct() {
$this->cur_ver = static::get_current_version();
}
/**
* Initialize migration.
*
* @since 3.0.0
*/
public function init() {
$this->validate_db();
}
/**
* Whether migration is enabled.
*
* @since 3.0.0
*
* @return bool
*/
public static function is_enabled() {
return true;
}
/**
* Static on purpose, to get current DB version without __construct() and validation.
*
* @since 3.0.0
*
* @return int
*/
public static function get_current_version() {
return (int) get_option( static::OPTION_NAME, 0 );
}
/**
* Check DB version and update to the latest one.
*
* @since 3.0.0
*/
protected function validate_db() {
if ( $this->cur_ver < static::DB_VERSION ) {
$this->run( static::DB_VERSION );
}
}
/**
* Update DB version in options table.
*
* @since 3.0.0
*
* @param int $version Version number.
*/
protected function update_db_ver( $version = 0 ) {
$version = (int) $version;
if ( empty( $version ) ) {
$version = static::DB_VERSION;
}
// Autoload it, because this value is checked all the time
// and no need to request it separately from all autoloaded options.
update_option( static::OPTION_NAME, $version, true );
}
/**
* Prevent running the same migration twice.
* Run migration only when required.
*
* @since 3.0.0
*
* @param int $version The current migration version.
*/
protected function maybe_required_older_migrations( $version ) {
$version = (int) $version;
if ( ( $version - $this->cur_ver ) > 1 ) {
$this->run( $version - 1 );
}
}
/**
* Actual migration launcher.
*
* @since 3.0.0
*
* @param int $version The specified migration version to run.
*/
protected function run( $version ) {
$version = (int) $version;
if ( method_exists( $this, 'migrate_to_' . $version ) ) {
$this->{'migrate_to_' . $version}();
} else {
if ( WP::in_wp_admin() ) {
$message = sprintf( /* translators: %1$s - the DB option name, %2$s - WP Mail SMTP, %3$s - error message. */
esc_html__( 'There was an error while upgrading the %1$s database. Please contact %2$s support with this information: %3$s.', 'wp-mail-smtp' ),
static::OPTION_NAME,
'<strong>WP Mail SMTP</strong>',
'<code>migration from v' . static::get_current_version() . ' to v' . static::DB_VERSION . ' failed. Plugin version: v' . WPMS_PLUGIN_VER . '</code>'
);
WP::add_admin_notice( $message, WP::ADMIN_NOTICE_ERROR );
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,380 @@
<?php
namespace WPMailSMTP;
/**
* Class Processor modifies the behaviour of wp_mail() function.
*
* @since 1.0.0
*/
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;
/**
* Connections manager.
*
* @since 3.7.0
*
* @var ConnectionsManager
*/
private $connections_manager;
/**
* Class constructor.
*
* @since 3.7.0
*
* @param ConnectionsManager $connections_manager Connections manager.
*/
public function __construct( $connections_manager = null ) {
if ( is_null( $connections_manager ) ) {
$this->connections_manager = wp_mail_smtp()->get_connections_manager();
} else {
$this->connections_manager = $connections_manager;
}
}
/**
* Assign all hooks to proper places.
*
* @since 1.0.0
*/
public function hooks() {
add_action( 'phpmailer_init', array( $this, 'phpmailer_init' ) );
// High priority number tries to ensure our plugin code executes last and respects previous hooks, if not forced.
add_filter( 'wp_mail_from', array( $this, 'filter_mail_from_email' ), PHP_INT_MAX );
add_filter( 'wp_mail_from_name', array( $this, 'filter_mail_from_name' ), PHP_INT_MAX );
}
/**
* Redefine certain PHPMailer options with our custom ones.
*
* @since 1.0.0
*
* @param \PHPMailer $phpmailer It's passed by reference, so no need to return anything.
*/
public function phpmailer_init( $phpmailer ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
$connection = $this->connections_manager->get_mail_connection();
$connection_options = $connection->get_options();
$mailer = $connection->get_mailer_slug();
// Check that mailer is not blank, and if mailer=smtp, host is not blank.
if (
! $mailer ||
( 'smtp' === $mailer && ! $connection_options->get( 'smtp', 'host' ) )
) {
return;
}
// If the mailer is pepipost, make sure we have a username and password.
if (
'pepipost' === $mailer &&
( ! $connection_options->get( 'pepipost', 'user' ) && ! $connection_options->get( 'pepipost', 'pass' ) )
) {
return;
}
// phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
// Set the mailer type as per config above, this overrides the already called isMail method.
// It's basically always 'smtp'.
$phpmailer->Mailer = $mailer;
// Set the Sender (return-path) if required.
if ( $connection_options->get( 'mail', 'return_path' ) ) {
$phpmailer->Sender = $phpmailer->From;
}
// Set the SMTPSecure value, if set to none, leave this blank. Possible values: 'ssl', 'tls', ''.
if ( 'none' === $connection_options->get( $mailer, 'encryption' ) ) {
$phpmailer->SMTPSecure = '';
} else {
$phpmailer->SMTPSecure = $connection_options->get( $mailer, 'encryption' );
}
// Check if user has disabled SMTPAutoTLS.
if ( $connection_options->get( $mailer, 'encryption' ) !== 'tls' && ! $connection_options->get( $mailer, 'autotls' ) ) {
$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 ( 'smtp' === $mailer ) {
// Set the other options.
$phpmailer->Host = $connection_options->get( $mailer, 'host' );
$phpmailer->Port = $connection_options->get( $mailer, 'port' );
// If we're using smtp auth, set the username & password.
if ( $connection_options->get( $mailer, 'auth' ) ) {
$phpmailer->SMTPAuth = true;
$phpmailer->Username = $connection_options->get( $mailer, 'user' );
$phpmailer->Password = $connection_options->get( $mailer, 'pass' );
}
} elseif ( 'pepipost' === $mailer ) {
// Set the Pepipost settings for BC.
$phpmailer->Mailer = 'smtp';
$phpmailer->Host = 'smtp.pepipost.com';
$phpmailer->Port = $connection_options->get( $mailer, 'port' );
$phpmailer->SMTPSecure = $connection_options->get( $mailer, 'encryption' ) === 'none' ? '' : $connection_options->get( $mailer, 'encryption' );
$phpmailer->SMTPAuth = true;
$phpmailer->Username = $connection_options->get( $mailer, 'user' );
$phpmailer->Password = $connection_options->get( $mailer, 'pass' );
}
// phpcs:enable
// Maybe set default reply-to header.
$this->set_default_reply_to( $phpmailer );
// You can add your own options here.
// See the phpmailer documentation for more info: https://github.com/PHPMailer/PHPMailer/tree/5.2-stable.
/* @noinspection PhpUnusedLocalVariableInspection It's passed by reference. */
$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 ) {
$connection = $this->connections_manager->get_mail_connection();
$connection_options = $connection->get_options();
$forced = $connection_options->get( 'mail', 'from_email_force' );
$from_email = $connection_options->get( 'mail', 'from_email' );
if ( ! empty( $reply_to ) || empty( $this->wp_mail_from ) ) {
return false;
}
if ( in_array( $mailer, [ 'zoho' ], true ) ) {
$sender = $connection_options->get( $mailer, 'user_details' );
$from_email = ! empty( $sender['email'] ) ? $sender['email'] : '';
$forced = true;
}
if (
$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.
*
* @since 1.3.0
* @since 1.5.0 Added a do_action() to be able to hook into.
*
* @param bool $is_sent If the email was sent.
* @param array $to To email address.
* @param array $cc CC email addresses.
* @param array $bcc BCC email addresses.
* @param string $subject The email subject.
* @param string $body The email body.
* @param string $from The from email address.
*/
public static function send_callback( $is_sent, $to, $cc, $bcc, $subject, $body, $from ) {
if ( ! $is_sent ) {
// Add mailer to the beginning and save to display later.
Debug::set(
'Mailer: ' . esc_html( wp_mail_smtp()->get_providers()->get_options( wp_mail_smtp()->get_connections_manager()->get_mail_connection()->get_mailer_slug() )->get_title() ) . "\r\n" .
'PHPMailer was able to connect to SMTP server but failed while trying to send an email.'
);
} else {
Debug::clear();
}
do_action( 'wp_mail_smtp_mailcatcher_smtp_send_after', $is_sent, $to, $cc, $bcc, $subject, $body, $from );
}
/**
* Validate the email address.
*
* @since 3.6.0
*
* @param string $email The email address.
*
* @return boolean True if email address is valid, false on failure.
*/
public static function is_email_callback( $email ) {
return (bool) is_email( $email );
}
/**
* Modify the email address that is used for sending emails.
*
* @since 1.0.0
* @since 1.3.0 Forcing email rewrite if option is selected.
* @since 1.7.0 Default email may be empty, so pay attention to that as well.
*
* @param string $wp_email The email address passed by the filter.
*
* @return string
*/
public function filter_mail_from_email( $wp_email ) {
$connection = $this->connections_manager->get_mail_connection();
$connection_options = $connection->get_options();
$forced = $connection_options->get( 'mail', 'from_email_force' );
$from_email = $connection_options->get( 'mail', 'from_email' );
$def_email = WP::get_default_email();
// Save the "original" set WP email from address for later use.
if ( $wp_email !== $def_email ) {
$this->wp_mail_from = filter_var( $wp_email, FILTER_VALIDATE_EMAIL );
}
// Return FROM EMAIL if forced in settings.
if ( $forced && ! empty( $from_email ) ) {
return $from_email;
}
// If the FROM EMAIL is not the default, return it unchanged.
if ( ! empty( $def_email ) && $wp_email !== $def_email ) {
return $wp_email;
}
return ! empty( $from_email ) ? $from_email : $wp_email;
}
/**
* Modify the sender name that is used for sending emails.
*
* @since 1.0.0
* @since 1.3.0 Forcing name rewrite if option is selected.
*
* @param string $name The from name passed through the filter.
*
* @return string
*/
public function filter_mail_from_name( $name ) {
$connection = $this->connections_manager->get_mail_connection();
$connection_options = $connection->get_options();
$force = $connection_options->get( 'mail', 'from_name_force' );
// If the FROM NAME is not the default and not forced, return it unchanged.
if ( ! $force && $name !== $this->get_default_name() ) {
return $name;
}
$name = $connection_options->get( 'mail', 'from_name' );
return $name;
}
/**
* Get the default email address based on domain name.
*
* @since 1.0.0
* @since 1.7.0 May return an empty string.
*
* @return string Empty string when we aren't able to get the site domain (CLI, misconfigured server etc).
*/
public function get_default_email() {
$server_name = Geo::get_site_domain();
if ( empty( $server_name ) ) {
return '';
}
// Get rid of www.
$sitename = strtolower( $server_name );
if ( substr( $sitename, 0, 4 ) === 'www.' ) {
$sitename = substr( $sitename, 4 );
}
return 'wordpress@' . $sitename;
}
/**
* Get the default email FROM NAME generated by WordPress.
*
* @since 1.3.0
*
* @return string
*/
public function get_default_name() {
return 'WordPress';
}
/**
* Get or create the phpmailer.
*
* @since 1.9.0
*
* @return MailCatcherInterface
*/
public function get_phpmailer() {
global $phpmailer;
// Make sure the PHPMailer class has been instantiated.
if ( ! is_object( $phpmailer ) || ! is_a( $phpmailer, 'PHPMailer' ) ) {
$phpmailer = wp_mail_smtp()->generate_mail_catcher( true ); // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
}
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 MailCatcherInterface $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

@@ -0,0 +1,44 @@
<?php
namespace WPMailSMTP\Providers\AmazonSES;
use WPMailSMTP\Providers\OptionsAbstract;
/**
* Class Options.
*
* @since 1.7.0
*/
class Options extends OptionsAbstract {
/**
* AmazonSES Options constructor.
*
* @since 1.7.0
*/
public function __construct() {
parent::__construct(
array(
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/aws.svg',
'slug' => 'amazonses',
'title' => esc_html__( 'Amazon SES', 'wp-mail-smtp' ),
'disabled' => true,
)
);
}
/**
* @inheritdoc
*/
public function display_options() {
?>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading">
<p>
<?php esc_html_e( 'We\'re sorry, the Amazon SES mailer is not available on your plan. Please upgrade to the PRO plan to unlock all these awesome features.', 'wp-mail-smtp' ); ?>
</p>
</div>
<?php
}
}

View File

@@ -0,0 +1,245 @@
<?php
namespace WPMailSMTP\Providers;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Options;
/**
* Class AuthAbstract.
*
* @since 1.0.0
*/
abstract class AuthAbstract implements AuthInterface {
/**
* The Connection object.
*
* @since 3.7.0
*
* @var ConnectionInterface
*/
protected $connection;
/**
* The connection options object.
*
* @since 3.7.0
*
* @var Options
*/
protected $connection_options;
/**
* Mailer DB options.
*
* @since 1.0.0
*
* @var array
*/
protected $options = [];
/**
* @since 1.0.0
*
* @var mixed
*/
protected $client;
/**
* Mailer slug.
*
* @since 1.0.0
*
* @var string
*/
protected $mailer_slug = '';
/**
* Key for a stored unique state value.
*
* @since 1.5.0
*
* @var string
*/
public $state_key = 'wp_mail_smtp_provider_client_state';
/**
* Auth constructor.
*
* @since 1.0.0
*
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $connection = null ) {
if ( ! is_null( $connection ) ) {
$this->connection = $connection;
} else {
$this->connection = wp_mail_smtp()->get_connections_manager()->get_primary_connection();
}
$this->connection_options = $this->connection->get_options();
$this->mailer_slug = $this->connection->get_mailer_slug();
}
/**
* Use the composer autoloader to include the auth library and all dependencies.
*
* @since 1.0.0
*/
protected function include_vendor_lib() {
require_once wp_mail_smtp()->plugin_path . '/vendor/autoload.php';
}
/**
* Get the url, that users will be redirected back to finish the OAuth process.
*
* @since 1.0.0
*
* @return string
*/
public static function get_plugin_auth_url() {
return add_query_arg( 'tab', 'auth', wp_mail_smtp()->get_admin()->get_admin_page_url() );
}
/**
* Update auth code in our DB.
*
* @since 1.0.0
*
* @param string $code
*/
protected function update_auth_code( $code ) {
$all = $this->connection_options->get_all();
// To save in DB.
$all[ $this->mailer_slug ]['auth_code'] = $code;
// To save in currently retrieved options array.
$this->options['auth_code'] = $code;
// NOTE: These options need to be saved by overwriting all options, because WP automatic updates can cause an issue: GH #575!
$this->connection_options->set( $all, false, true );
}
/**
* Update Setup Wizard flag in our DB.
*
* @since 2.6.0
*
* @param boolean $state A state (true/false) to set the is_setup_wizard_auth mailer setting.
*/
public function update_is_setup_wizard_auth( $state ) {
$all = $this->connection_options->get_all();
// To save in DB.
$all[ $this->mailer_slug ]['is_setup_wizard_auth'] = (bool) $state;
// To save in currently retrieved options array.
$this->options['is_setup_wizard_auth'] = (bool) $state;
// NOTE: These options need to be saved by overwriting all options, because WP automatic updates can cause an issue: GH #575!
$this->connection_options->set( $all, false, true );
}
/**
* Update access token in our DB.
*
* @since 1.0.0
*
* @param mixed $token
*/
protected function update_access_token( $token ) {
$all = $this->connection_options->get_all();
// To save in DB.
$all[ $this->mailer_slug ]['access_token'] = $token;
// To save in currently retrieved options array.
$this->options['access_token'] = $token;
// NOTE: These options need to be saved by overwriting all options, because WP automatic updates can cause an issue: GH #575!
$this->connection_options->set( $all, false, true );
}
/**
* Update refresh token in our DB.
*
* @since 1.0.0
*
* @param mixed $token
*/
protected function update_refresh_token( $token ) {
$all = $this->connection_options->get_all();
// To save in DB.
$all[ $this->mailer_slug ]['refresh_token'] = $token;
// To save in currently retrieved options array.
$this->options['refresh_token'] = $token;
// NOTE: These options need to be saved by overwriting all options, because WP automatic updates can cause an issue: GH #575!
$this->connection_options->set( $all, false, true );
}
/**
* Update access token scopes in our DB.
*
* @since 3.4.0
*
* @param array $scopes Scopes array.
*/
protected function update_scopes( $scopes ) {
$all = $this->connection_options->get_all();
// To save in DB.
$all[ $this->mailer_slug ]['scopes'] = $scopes;
// To save in currently retrieved options array.
$this->options['scopes'] = $scopes;
// NOTE: These options need to be saved by overwriting all options, because WP automatic updates can cause an issue: GH #575!
$this->connection_options->set( $all, false, true );
}
/**
* Get state value that should be used for `state` parameter in OAuth authorization request.
*
* @since 3.7.0
*
* @return string
*/
protected function get_state() {
$state = [
wp_create_nonce( $this->state_key ),
$this->connection->get_id(),
];
return implode( '-', $state );
}
/**
* @inheritdoc
*/
public function is_clients_saved() {
return ! empty( $this->options['client_id'] ) && ! empty( $this->options['client_secret'] );
}
/**
* @inheritdoc
*/
public function is_auth_required() {
return empty( $this->options['access_token'] ) || empty( $this->options['refresh_token'] );
}
}

View File

@@ -0,0 +1,30 @@
<?php
namespace WPMailSMTP\Providers;
/**
* Interface AuthInterface.
*
* @since 1.0.0
*/
interface AuthInterface {
/**
* Whether user saved Client ID/App ID and Client Secret/App Password or not.
* Both options are required.
*
* @since 1.0.0
*
* @return bool
*/
public function is_clients_saved();
/**
* Whether we have an access and refresh tokens or not.
*
* @since 1.0.0
*
* @return bool
*/
public function is_auth_required();
}

View File

@@ -0,0 +1,547 @@
<?php
namespace WPMailSMTP\Providers\Gmail;
use Exception;
use WPMailSMTP\Admin\Area;
use WPMailSMTP\Admin\ConnectionSettings;
use WPMailSMTP\Admin\DebugEvents\DebugEvents;
use WPMailSMTP\Admin\SetupWizard;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Debug;
use WPMailSMTP\Providers\AuthAbstract;
use WPMailSMTP\Vendor\Google_Client;
use WPMailSMTP\Vendor\Google\Service\Gmail;
/**
* Class Auth to request access and refresh tokens.
*
* @since 1.0.0
*/
class Auth extends AuthAbstract {
/**
* List of all possible "from email" email addresses (aliases).
*
* @since 2.2.0
*
* @var null|array
*/
private $aliases = null;
/**
* Auth constructor.
*
* @since 1.0.0
*
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $connection = null ) {
parent::__construct( $connection );
if ( $this->mailer_slug !== Options::SLUG ) {
return;
}
$this->options = $this->connection_options->get_group( $this->mailer_slug );
if ( $this->is_clients_saved() ) {
$this->include_vendor_lib();
$this->client = $this->get_client();
}
}
/**
* Get the url, that users will be redirected back to finish the OAuth process.
*
* @since 1.5.2 Returned to the old, pre-1.5, structure of the link to preserve BC.
*
* @param ConnectionInterface $connection The Connection object.
*
* @return string
*/
public static function get_plugin_auth_url( $connection = null ) {
if ( is_null( $connection ) ) {
$connection = wp_mail_smtp()->get_connections_manager()->get_primary_connection();
}
$auth_url = apply_filters(
'wp_mail_smtp_gmail_get_plugin_auth_url',
add_query_arg(
[
'page' => Area::SLUG,
'tab' => 'auth',
],
admin_url( 'options-general.php' )
)
);
return add_query_arg( 'state', self::get_state_param( $connection ), $auth_url );
}
/**
* Init and get the Google Client object.
*
* @since 1.0.0
* @since 1.5.0 Add ability to apply custom options to the client via a filter.
*
* @param bool $force If the client should be forcefully reinitialized.
*
* @return Google_Client
*/
public function get_client( $force = false ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
// Doesn't load client twice + gives ability to overwrite.
if ( ! empty( $this->client ) && ! $force ) {
return $this->client;
}
$this->include_vendor_lib();
$client = new Google_Client(
array(
'client_id' => $this->options['client_id'],
'client_secret' => $this->options['client_secret'],
'redirect_uris' => array(
self::get_oauth_redirect_url(),
),
)
);
$client->setApplicationName( 'WP Mail SMTP v' . WPMS_PLUGIN_VER );
$client->setAccessType( 'offline' );
$client->setPrompt( 'consent' );
$client->setIncludeGrantedScopes( false );
// We request only the sending capability, as it's what we only need to do.
$client->setScopes( array( Gmail::MAIL_GOOGLE_COM ) );
$client->setRedirectUri( self::get_oauth_redirect_url() );
if ( self::use_self_oauth_redirect_url() ) {
$client->setState( self::get_state_param( $this->connection ) );
} else {
$client->setState( self::get_plugin_auth_url( $this->connection ) );
}
// Apply custom options to the client.
$client = apply_filters( 'wp_mail_smtp_providers_gmail_auth_get_client_custom_options', $client );
if (
$this->is_auth_required() &&
! empty( $this->options['auth_code'] )
) {
try {
$creds = $client->fetchAccessTokenWithAuthCode( $this->options['auth_code'] );
} catch ( Exception $e ) {
$creds['error'] = $e->getMessage();
}
// Bail if we have an error.
if ( ! empty( $creds['error'] ) ) {
if ( $creds['error'] === 'invalid_client' ) {
$creds['error'] .= PHP_EOL . esc_html__( 'Please make sure your Google Client ID and Secret in the plugin settings are valid. Save the settings and try the Authorization again.' , 'wp-mail-smtp' );
}
Debug::set(
'Mailer: Gmail' . "\r\n" .
$creds['error']
);
return $client;
} else {
Debug::clear();
}
$this->update_access_token( $client->getAccessToken() );
$this->update_refresh_token( $client->getRefreshToken() );
$this->update_user_details( $client );
// Update the "from email" to the connected user's email.
if ( ! empty( $this->options['user_details']['email'] ) ) {
$this->connection_options->set(
[
'mail' => [
'from_email' => $this->options['user_details']['email'],
],
],
false,
false
);
}
}
if ( ! empty( $this->options['access_token'] ) ) {
$client->setAccessToken( $this->options['access_token'] );
}
// Refresh the token if it's expired.
if ( $client->isAccessTokenExpired() ) {
$refresh = $client->getRefreshToken();
if ( empty( $refresh ) && isset( $this->options['refresh_token'] ) ) {
$refresh = $this->options['refresh_token'];
}
if ( ! empty( $refresh ) ) {
try {
$creds = $client->fetchAccessTokenWithRefreshToken( $refresh );
} catch ( Exception $e ) {
$creds['error'] = $e->getMessage();
Debug::set(
'Mailer: Gmail' . "\r\n" .
$e->getMessage()
);
}
// Bail if we have an error.
if ( ! empty( $creds['error'] ) ) {
return $client;
}
$this->update_access_token( $client->getAccessToken() );
$this->update_refresh_token( $client->getRefreshToken() );
}
}
return $client;
}
/**
* Get the auth code from the $_GET and save it.
* Redirect user back to settings with an error message, if failed.
*
* @since 1.0.0
*/
public function process() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
$redirect_url = ( new ConnectionSettings( $this->connection ) )->get_admin_page_url();
$is_setup_wizard_auth = ! empty( $this->options['is_setup_wizard_auth'] );
if ( $is_setup_wizard_auth ) {
$this->update_is_setup_wizard_auth( false );
$redirect_url = SetupWizard::get_site_url() . '#/step/configure_mailer/gmail';
}
if ( ! ( isset( $_GET['tab'] ) && $_GET['tab'] === 'auth' ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
wp_safe_redirect( $redirect_url );
exit;
}
$state = isset( $_GET['state'] ) ? sanitize_key( $_GET['state'] ) : false;
if ( empty( $state ) ) {
wp_safe_redirect(
add_query_arg( 'error', 'oauth_invalid_state', $redirect_url )
);
}
list( $nonce ) = array_pad( explode( '-', $state ), 1, false );
// Verify the nonce that should be returned in the state parameter.
if ( ! wp_verify_nonce( $nonce, $this->state_key ) ) {
wp_safe_redirect(
add_query_arg(
'error',
'google_invalid_nonce',
$redirect_url
)
);
exit;
}
// We can't process without saved client_id/secret.
if ( ! $this->is_clients_saved() ) {
Debug::set(
esc_html__( 'There was an error while processing the Google authentication request. Please make sure that you have Client ID and Client Secret both valid and saved.', 'wp-mail-smtp' )
);
wp_safe_redirect(
add_query_arg(
'error',
'google_no_clients',
$redirect_url
)
);
exit;
}
$this->include_vendor_lib();
$code = '';
$scope = '';
$error = '';
if ( isset( $_GET['error'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Recommended
$error = sanitize_key( $_GET['error'] ); // phpcs:ignore WordPress.Security.NonceVerification.Recommended
}
// In case of any error: display a message to a user.
if ( ! empty( $error ) ) {
DebugEvents::add_debug(
sprintf( /* Translators: %s the error code passed from Google. */
esc_html__( 'There was an error while processing Google authorization: %s' ),
esc_html( $error )
)
);
wp_safe_redirect(
add_query_arg(
'error',
'google_' . $error,
$redirect_url
)
);
exit;
}
if ( isset( $_GET['code'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$code = urldecode( $_GET['code'] );
}
if ( isset( $_GET['scope'] ) ) {
// phpcs:ignore WordPress.Security.NonceVerification.Recommended, WordPress.Security.ValidatedSanitizedInput.MissingUnslash, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
$scope = $_GET['scope'];
if ( self::use_self_oauth_redirect_url() ) {
$scope = urldecode( $scope );
} else {
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_decode
$scope = urldecode( base64_decode( $scope ) );
}
}
// Let's try to get the access token.
if (
! empty( $code ) &&
(
$scope === Gmail::MAIL_GOOGLE_COM . ' ' . Gmail::GMAIL_SEND ||
$scope === Gmail::GMAIL_SEND . ' ' . Gmail::MAIL_GOOGLE_COM ||
$scope === Gmail::GMAIL_SEND ||
$scope === Gmail::MAIL_GOOGLE_COM
)
) {
// Save the auth code. So Google_Client can reuse it to retrieve the access token.
$this->update_auth_code( $code );
} else {
DebugEvents::add_debug(
esc_html__( 'There was an error while processing Google authorization: missing code or scope parameter.' )
);
wp_safe_redirect(
add_query_arg(
'error',
'google_no_code_scope',
$redirect_url
)
);
exit;
}
Debug::clear();
$this->get_client( true );
$error = Debug::get_last();
if ( ! empty( $error ) ) {
wp_safe_redirect(
add_query_arg(
'error',
'google_unsuccessful_oauth',
$redirect_url
)
);
exit;
}
wp_safe_redirect(
add_query_arg(
'success',
'google_site_linked',
$redirect_url
)
);
exit;
}
/**
* Get the auth URL used to proceed to Provider to request access to send emails.
*
* @since 1.0.0
*
* @return string
*/
public function get_auth_url() {
if (
! empty( $this->client ) &&
class_exists( 'WPMailSMTP\Vendor\Google_Client', false ) &&
$this->client instanceof Google_Client
) {
return filter_var( $this->client->createAuthUrl(), FILTER_SANITIZE_URL );
}
return '#';
}
/**
* Get and update user-related details (currently only email).
*
* @since 3.11.0
*
* @param Google_Client $client The Google Client object (optional).
*/
private function update_user_details( $client = false ) {
if ( $client === false ) {
$client = $this->get_client();
}
$gmail = new Gmail( $client );
try {
$email = $gmail->users->getProfile( 'me' )->getEmailAddress();
$user_details = [
'email' => $email,
];
// To save in DB.
$updated_settings = [
$this->mailer_slug => [
'user_details' => $user_details,
],
];
// To save in currently retrieved options array.
$this->options['user_details'] = $user_details;
$this->connection_options->set( $updated_settings, false, false );
} catch ( Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
// Do nothing.
}
}
/**
* Get user information (currently only email) that is associated with the current OAuth connection.
*
* @since 1.5.0
* @since 3.11.0 Switched to DB stored value instead of API call.
*
* @return array
*/
public function get_user_info() {
/*
* We need to populate user data on the fly for old users who already performed
* authorization before we switched to DB stored value.
*/
if ( ! isset( $this->options['user_details'] ) && ! $this->is_auth_required() ) {
$this->update_user_details();
}
return $this->connection_options->get( $this->mailer_slug, 'user_details' );
}
/**
* Get the registered email addresses that the user can use as the "from email".
*
* @since 2.2.0
*
* @return array The list of possible from email addresses.
*/
public function get_user_possible_send_from_addresses() {
if ( isset( $this->aliases ) ) {
return $this->aliases;
}
$gmail = new Gmail( $this->get_client() );
try {
// phpcs:ignore WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
$response = $gmail->users_settings_sendAs->listUsersSettingsSendAs( 'me' );
// phpcs:disable
$this->aliases = array_map(
function( $sendAsObject ) {
return $sendAsObject['sendAsEmail'];
},
(array) $response->getSendAs()
);
// phpcs:enable
} catch ( Exception $exception ) {
DebugEvents::add_debug(
sprintf( /* Translators: %s the error message. */
esc_html__( 'An error occurred when trying to get Gmail aliases: %s' ),
esc_html( $exception->getMessage() )
)
);
$this->aliases = [];
}
return $this->aliases;
}
/**
* Get the Google oAuth 2.0 redirect URL.
*
* This is the URL that Google will redirect after the access to the Gmail account is granted or rejected.
* The below endpoint will then redirect back to the user's WP site (to self::get_plugin_auth_url() URL).
*
* @since 2.5.0
*
* @return string
*/
public static function get_oauth_redirect_url() {
if ( self::use_self_oauth_redirect_url() ) {
return remove_query_arg( 'state', self::get_plugin_auth_url() );
} else {
return 'https://connect.wpmailsmtp.com/google/';
}
}
/**
* Get the state parameter for the Google oAuth redirect URL.
*
* @since 3.10.0
*
* @param ConnectionInterface $connection The Connection object.
*
* @return string
*/
private static function get_state_param( $connection ) {
$state = [
wp_create_nonce( 'wp_mail_smtp_provider_client_state' ),
$connection->get_id(),
];
return implode( '-', $state );
}
/**
* Whether to use self website redirect URL for the Google oAuth.
*
* @since 3.10.0
*
* @return bool
*/
private static function use_self_oauth_redirect_url() {
/**
* Filter whether to use self website redirect URL for the Google oAuth.
*
* @since 3.10.0
*
* @param bool $use Whether to use self website redirect URL for the Google oAuth.
*/
return apply_filters( 'wp_mail_smtp_providers_gmail_auth_use_self_oauth_redirect_url', false );
}
}

View File

@@ -0,0 +1,294 @@
<?php
namespace WPMailSMTP\Providers\Gmail;
use WPMailSMTP\Admin\DebugEvents\DebugEvents;
use WPMailSMTP\Helpers\Helpers;
use WPMailSMTP\MailCatcherInterface;
use WPMailSMTP\Providers\MailerAbstract;
use WPMailSMTP\Vendor\Google\Service\Gmail;
use WPMailSMTP\Vendor\Google\Service\Gmail\Message;
use WPMailSMTP\WP;
/**
* Class Mailer.
*
* @since 1.0.0
*/
class Mailer extends MailerAbstract {
/**
* URL to make an API request to.
* Not used for Gmail, as we are using its API.
*
* @since 1.0.0
*
* @var string
*/
protected $url = 'https://www.googleapis.com/upload/gmail/v1/users/{userId}/messages/send';
/**
* Gmail message.
*
* @since 1.0.0
*
* @var Message
*/
protected $message;
/**
* Re-use the MailCatcher class methods and properties.
*
* @since 1.2.0
*
* @param MailCatcherInterface $phpmailer The MailCatcher object.
*/
public function process_phpmailer( $phpmailer ) {
// Make sure that we have access to PHPMailer class methods.
if ( ! wp_mail_smtp()->is_valid_phpmailer( $phpmailer ) ) {
return;
}
$this->phpmailer = $phpmailer;
}
/**
* Use Google API Services to send emails.
*
* @since 1.0.0
*/
public function send() {
// Include the Google library.
require_once wp_mail_smtp()->plugin_path . '/vendor/autoload.php';
$auth = new Auth( $this->connection );
$message = new Message();
// Set the authorized Gmail email address as the "from email" if the set email is not on the list of aliases.
$possible_from_emails = $auth->get_user_possible_send_from_addresses();
if ( ! in_array( $this->phpmailer->From, $possible_from_emails, true ) ) {
$user_info = $auth->get_user_info();
if ( ! empty( $user_info['email'] ) ) {
$this->phpmailer->From = $user_info['email'];
$this->phpmailer->Sender = $user_info['email'];
}
}
try {
// Prepare a message for sending if any changes happened above.
$this->phpmailer->preSend();
// Get the raw MIME email using MailCatcher data. We need to make base64URL-safe string.
$base64 = str_replace(
[ '+', '/', '=' ],
[ '-', '_', '' ],
base64_encode( $this->phpmailer->getSentMIMEMessage() ) //phpcs:ignore
);
$message->setRaw( $base64 );
$service = new Gmail( $auth->get_client() );
$response = $service->users_messages->send( 'me', $message );
DebugEvents::add_debug(
esc_html__( 'An email request was sent to the Gmail API.', 'wp-mail-smtp' )
);
$this->process_response( $response );
} catch ( \Exception $e ) {
$this->error_message = $this->process_exception_message( $e->getMessage() );
}
}
/**
* Save response from the API to use it later.
*
* @since 1.0.0
* @since 1.5.0 Added action "wp_mail_smtp_providers_gmail_mailer_process_response" with $response.
*
* @param Message $response Instance of Gmail response.
*/
protected function process_response( $response ) {
$this->response = $response;
if ( empty( $this->response ) || ! method_exists( $this->response, 'getId' ) ) {
$this->error_message = esc_html__( 'The response object is invalid (missing getId method).', 'wp-mail-smtp' );
} else {
$message_id = $this->response->getId();
if ( empty( $message_id ) ) {
$this->error_message = esc_html__( 'The email message ID is missing.', 'wp-mail-smtp' );
}
}
do_action( 'wp_mail_smtp_providers_gmail_mailer_process_response', $this->response, $this->phpmailer );
}
/**
* Check whether the email was sent.
*
* @since 1.0.0
*
* @return bool
*/
public function is_email_sent() {
$is_sent = false;
if (
! empty( $this->response ) &&
method_exists( $this->response, 'getId' ) &&
! empty( $this->response->getId() )
) {
$is_sent = true;
}
/** This filter is documented in src/Providers/MailerAbstract.php. */
return apply_filters( 'wp_mail_smtp_providers_mailer_is_email_sent', $is_sent, $this->mailer );
}
/**
* 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() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
$gmail_text = array();
$gmail = $this->connection_options->get_group( 'gmail' );
$curl_ver = 'No';
if ( function_exists( 'curl_version' ) ) {
$curl = curl_version();
$curl_ver = $curl['version'];
}
$gmail_text[] = '<strong>Client ID/Secret:</strong> ' . ( ! empty( $gmail['client_id'] ) && ! empty( $gmail['client_secret'] ) ? 'Yes' : 'No' );
$gmail_text[] = '<strong>Auth Code:</strong> ' . ( ! empty( $gmail['auth_code'] ) ? 'Yes' : 'No' );
$gmail_text[] = '<strong>Access Token:</strong> ' . ( ! empty( $gmail['access_token'] ) ? 'Yes' : 'No' );
$gmail_text[] = '<br><strong>Server:</strong>';
$gmail_text[] = '<strong>OpenSSL:</strong> ' . ( extension_loaded( 'openssl' ) && defined( 'OPENSSL_VERSION_TEXT' ) ? OPENSSL_VERSION_TEXT : 'No' );
$gmail_text[] = '<strong>PHP.allow_url_fopen:</strong> ' . ( ini_get( 'allow_url_fopen' ) ? 'Yes' : 'No' );
$gmail_text[] = '<strong>PHP.stream_socket_client():</strong> ' . ( function_exists( 'stream_socket_client' ) ? 'Yes' : 'No' );
$gmail_text[] = '<strong>PHP.fsockopen():</strong> ' . ( function_exists( 'fsockopen' ) ? 'Yes' : 'No' );
$gmail_text[] = '<strong>PHP.curl_version():</strong> ' . $curl_ver;
if ( function_exists( 'apache_get_modules' ) ) {
$modules = apache_get_modules();
$gmail_text[] = '<strong>Apache.mod_security:</strong> ' . ( in_array( 'mod_security', $modules, true ) || in_array( 'mod_security2', $modules, true ) ? 'Yes' : 'No' );
}
if ( function_exists( 'selinux_is_enabled' ) ) {
$gmail_text[] = '<strong>OS.SELinux:</strong> ' . ( selinux_is_enabled() ? 'Yes' : 'No' );
}
if ( function_exists( 'grsecurity_is_enabled' ) ) {
$gmail_text[] = '<strong>OS.grsecurity:</strong> ' . ( grsecurity_is_enabled() ? 'Yes' : 'No' );
}
return implode( '<br>', $gmail_text );
}
/**
* Whether the mailer has all its settings correctly set up and saved.
*
* @since 1.4.0
*
* @return bool
*/
public function is_mailer_complete() {
if ( ! $this->is_php_compatible() ) {
return false;
}
$auth = new Auth( $this->connection );
if (
$auth->is_clients_saved() &&
! $auth->is_auth_required()
) {
return true;
}
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 = [
[
'errors' => [
'invalid_grant',
],
'explanation' => esc_html__( 'Please re-grant Google app permissions!', 'wp-mail-smtp' ) . ' ' . WP::EOL .
esc_html__( 'Go to WP Mail SMTP plugin settings page. Click the “Remove OAuth Connection” button.', 'wp-mail-smtp' ) . ' ' . WP::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 Helpers::format_error_message( $message, '', $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( $this->connection ) )->get_user_info();
if ( empty( $gmail_creds['email'] ) ) {
return [];
}
return [
$gmail_creds['email'] => [
$gmail_creds['email'],
'',
],
];
}
}

View File

@@ -0,0 +1,291 @@
<?php
namespace WPMailSMTP\Providers\Gmail;
use WPMailSMTP\Admin\ConnectionSettings;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Helpers\UI;
use WPMailSMTP\Providers\OptionsAbstract;
/**
* Class Option.
*
* @since 1.0.0
*/
class Options extends OptionsAbstract {
/**
* Mailer slug.
*
* @since 1.5.0
*/
const SLUG = 'gmail';
/**
* Gmail Options constructor.
*
* @since 1.0.0
* @since 2.3.0 Added supports parameter.
*
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $connection = null ) {
parent::__construct(
[
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/google.svg',
'slug' => self::SLUG,
'title' => esc_html__( 'Google / Gmail', 'wp-mail-smtp' ),
'description' => sprintf(
wp_kses( /* translators: %s - URL to our Gmail doc. */
__( 'Our Gmail mailer works with any Gmail or Google Workspace account via the Google API. You can send WordPress emails from your main email address or a Gmail alias, and it\'s more secure than connecting to Gmail using SMTP credentials. We now have a One-Click Setup, which simply asks you to authorize your Google account to use our app and takes care of everything for you. Alternatively, you can connect manually, which involves several steps that are more technical than other mailer options, so we created a detailed guide to walk you through the process.<br><br>To get started, read our <a href="%s" target="_blank" rel="noopener noreferrer">Gmail documentation</a>.', 'wp-mail-smtp' ),
[
'br' => [],
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-set-up-the-gmail-mailer-in-wp-mail-smtp/', 'Gmail documentation' ) )
),
'notices' => [
'educational' => wp_kses(
__( 'The Gmail mailer works well for sites that send low numbers of emails. However, Gmail\'s API has rate limitations and a number of additional restrictions that can lead to challenges during setup.<br><br>If you expect to send a high volume of emails, or if you find that your web host is not compatible with the Gmail API restrictions, then we recommend considering a different mailer option.', 'wp-mail-smtp' ),
[
'br' => [],
]
),
],
'php' => '5.6',
'supports' => [
'from_email' => true,
'from_name' => true,
'return_path' => false,
'from_email_force' => true,
'from_name_force' => true,
],
],
$connection
);
}
/**
* @inheritdoc
*/
public function display_options() {
// Do not display options if PHP version is not correct.
if ( ! $this->is_php_correct() ) {
$this->display_php_warning();
return;
}
?>
<?php if ( ! wp_mail_smtp()->is_pro() ) : ?>
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-one_click_setup_enabled-lite" class="wp-mail-smtp-setting-row">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-one_click_setup_enabled-lite">
<?php esc_html_e( 'One-Click Setup', 'wp-mail-smtp' ); ?>
</label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'id' => 'wp-mail-smtp-setting-' . esc_attr( $this->get_slug() ) . '-one_click_setup_enabled-lite',
]
);
?>
<p class="desc">
<?php esc_html_e( 'Provides a quick and easy way to connect to Google that doesn\'t require creating your own app.', 'wp-mail-smtp' ); ?>
</p>
</div>
</div>
<?php endif; ?>
<!-- Client ID -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_id"
class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_id"><?php esc_html_e( 'Client ID', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][client_id]" type="text"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'client_id' ) ); ?>"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'client_id' ) ? 'disabled' : ''; ?>
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_id" spellcheck="false"
/>
</div>
</div>
<!-- Client Secret -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret"
class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret"><?php esc_html_e( 'Client Secret', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php if ( $this->connection_options->is_const_defined( $this->get_slug(), 'client_secret' ) ) : ?>
<input type="text" disabled value="****************************************"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret"
/>
<?php $this->display_const_set_message( 'WPMS_GMAIL_CLIENT_SECRET' ); ?>
<?php else : ?>
<input type="password" spellcheck="false"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][client_secret]"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'client_secret' ) ); ?>"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_secret"
/>
<?php endif; ?>
</div>
</div>
<!-- Authorized redirect URI -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect"
class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect"><?php esc_html_e( 'Authorized redirect URI', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<input type="text" readonly="readonly" onfocus="this.select();"
value="<?php echo esc_attr( Auth::get_oauth_redirect_url() ); ?>"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect"
/>
<button type="button" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-grey wp-mail-smtp-setting-copy"
title="<?php esc_attr_e( 'Copy URL to clipboard', 'wp-mail-smtp' ); ?>"
data-source_id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-client_redirect">
<span class="dashicons dashicons-admin-page"></span>
</button>
<p class="desc">
<?php esc_html_e( 'Please copy this URL into the "Authorized redirect URIs" field of your Google web application.', 'wp-mail-smtp' ); ?>
</p>
</div>
</div>
<!-- Auth users button -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-authorize"
class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'Authorization', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php $this->display_auth_setting_action(); ?>
</div>
</div>
<?php
}
/**
* Display either an "Allow..." or "Remove..." button.
*
* @since 1.3.0
*/
protected function display_auth_setting_action() {
// Do the processing on the fly, as having ajax here is too complicated.
$this->process_provider_remove();
$auth = new Auth( $this->connection );
?>
<?php if ( $auth->is_clients_saved() ) : ?>
<?php if ( $auth->is_auth_required() ) : ?>
<a href="<?php echo esc_url( $auth->get_auth_url() ); ?>" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-orange">
<?php esc_html_e( 'Allow plugin to send emails using your Google account', 'wp-mail-smtp' ); ?>
</a>
<p class="desc">
<?php esc_html_e( 'Click the button above to confirm authorization.', 'wp-mail-smtp' ); ?>
</p>
<?php else : ?>
<a href="<?php echo esc_url( wp_nonce_url( ( new ConnectionSettings( $this->connection ) )->get_admin_page_url(), 'gmail_remove', 'gmail_remove_nonce' ) ); ?>#wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-authorize" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-red js-wp-mail-smtp-provider-remove">
<?php esc_html_e( 'Remove OAuth Connection', 'wp-mail-smtp' ); ?>
</a>
<span class="connected-as">
<?php
$user = $auth->get_user_info();
if ( ! empty( $user['email'] ) ) {
printf(
/* translators: %s - email address, as received from Google API. */
esc_html__( 'Connected as %s', 'wp-mail-smtp' ),
'<code>' . esc_html( $user['email'] ) . '</code>'
);
}
?>
</span>
<p class="desc">
<?php
printf(
wp_kses( /* translators: %s - URL to Google Gmail alias documentation page. */
__( 'If you want to use a different From Email address you can set up a Google email alias. <a href="%s" target="_blank" rel="noopener noreferrer">Follow these instructions</a> and then select the From Email at the top of this page.', 'wp-mail-smtp' ),
[
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/gmail-send-from-alias-wp-mail-smtp/', 'Gmail aliases description - Follow these instructions' ) )
);
?>
</p>
<p class="desc">
<?php esc_html_e( 'You can also send emails with different From Email addresses, by disabling the Force From Email setting and using registered aliases throughout your WordPress site as the From Email addresses.', 'wp-mail-smtp' ); ?>
</p>
<p class="desc">
<?php esc_html_e( 'Removing the OAuth connection will give you an ability to redo the OAuth connection or link to another Google account.', 'wp-mail-smtp' ); ?>
</p>
<?php endif; ?>
<?php else : ?>
<p class="inline-notice inline-error">
<?php esc_html_e( 'You need to save settings with Client ID and Client Secret before you can proceed.', 'wp-mail-smtp' ); ?>
</p>
<?php
endif;
}
/**
* Remove Provider OAuth connection.
*
* @since 1.3.0
*/
public function process_provider_remove() {
if ( ! current_user_can( wp_mail_smtp()->get_capability_manage_options() ) ) {
return;
}
if (
! isset( $_GET['gmail_remove_nonce'] ) ||
! wp_verify_nonce( sanitize_key( $_GET['gmail_remove_nonce'] ), 'gmail_remove' )
) {
return;
}
if ( $this->connection->get_mailer_slug() !== $this->get_slug() ) {
return;
}
$old_opt = $this->connection_options->get_all_raw();
unset( $old_opt[ $this->get_slug() ]['access_token'] );
unset( $old_opt[ $this->get_slug() ]['refresh_token'] );
unset( $old_opt[ $this->get_slug() ]['user_details'] );
unset( $old_opt[ $this->get_slug() ]['auth_code'] );
$this->connection_options->set( $old_opt );
}
}

View File

@@ -0,0 +1,234 @@
<?php
namespace WPMailSMTP\Providers;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Debug;
use WPMailSMTP\MailCatcherInterface;
use WPMailSMTP\Options;
/**
* Class Loader.
*
* @since 1.0.0
*/
class Loader {
/**
* Key is the mailer option, value is the path to its classes.
*
* @since 1.0.0
* @since 1.6.0 Added Sendinblue.
* @since 1.7.0 Added AmazonSES/Outlook as indication of the Pro mailers.
*
* @var array
*/
protected $providers = [
'mail' => 'WPMailSMTP\Providers\Mail\\',
'sendlayer' => 'WPMailSMTP\Providers\Sendlayer\\',
'smtpcom' => 'WPMailSMTP\Providers\SMTPcom\\',
'sendinblue' => 'WPMailSMTP\Providers\Sendinblue\\',
'amazonses' => 'WPMailSMTP\Providers\AmazonSES\\',
'gmail' => 'WPMailSMTP\Providers\Gmail\\',
'mailgun' => 'WPMailSMTP\Providers\Mailgun\\',
'outlook' => 'WPMailSMTP\Providers\Outlook\\',
'pepipostapi' => 'WPMailSMTP\Providers\PepipostAPI\\',
'postmark' => 'WPMailSMTP\Providers\Postmark\\',
'sendgrid' => 'WPMailSMTP\Providers\Sendgrid\\',
'sparkpost' => 'WPMailSMTP\Providers\SparkPost\\',
'zoho' => 'WPMailSMTP\Providers\Zoho\\',
'smtp' => 'WPMailSMTP\Providers\SMTP\\',
'pepipost' => 'WPMailSMTP\Providers\Pepipost\\',
];
/**
* Get all the supported providers.
*
* @since 1.0.0
*
* @return array
*/
public function get_providers() {
if ( ! Options::init()->is_mailer_active( 'pepipost' ) ) {
unset( $this->providers['pepipost'] );
}
if ( ! Options::init()->is_mailer_active( 'pepipostapi' ) ) {
unset( $this->providers['pepipostapi'] );
}
return apply_filters( 'wp_mail_smtp_providers_loader_get_providers', $this->providers );
}
/**
* Get a single provider FQN-path based on its name.
*
* @since 1.0.0
*
* @param string $provider
*
* @return string|null
*/
public function get_provider_path( $provider ) {
$provider = sanitize_key( $provider );
$providers = $this->get_providers();
return apply_filters(
'wp_mail_smtp_providers_loader_get_provider_path',
isset( $providers[ $provider ] ) ? $providers[ $provider ] : null,
$provider
);
}
/**
* Get the provider options, if exists.
*
* @since 1.0.0
*
* @param string $provider
* @param ConnectionInterface $connection The Connection object.
*
* @return OptionsAbstract|null
*/
public function get_options( $provider, $connection = null ) {
return $this->get_entity( $provider, 'Options', [ $connection ] );
}
/**
* Get all options of all providers.
*
* @since 1.0.0
*
* @param ConnectionInterface $connection The Connection object.
*
* @return OptionsAbstract[]
*/
public function get_options_all( $connection = null ) {
$options = array();
foreach ( $this->get_providers() as $provider => $path ) {
$option = $this->get_options( $provider, $connection );
if ( ! $option instanceof OptionsAbstract ) {
continue;
}
$slug = $option->get_slug();
$title = $option->get_title();
if ( empty( $title ) || empty( $slug ) ) {
continue;
}
$options[] = $option;
}
return apply_filters( 'wp_mail_smtp_providers_loader_get_providers_all', $options );
}
/**
* Get the provider mailer, if exists.
*
* @since 1.0.0
*
* @param string $provider The provider name.
* @param MailCatcherInterface $phpmailer The MailCatcher object.
* @param ConnectionInterface $connection The Connection object.
*
* @return MailerAbstract|null
*/
public function get_mailer( $provider, $phpmailer, $connection = null ) {
return $this->get_entity( $provider, 'Mailer', [ $phpmailer, $connection ] );
}
/**
* Get the provider auth, if exists.
*
* @param string $provider
* @param ConnectionInterface $connection The Connection object.
*
* @return AuthAbstract|null
*/
public function get_auth( $provider, $connection = null ) {
return $this->get_entity( $provider, 'Auth', [ $connection ] );
}
/**
* Get a generic entity based on the request.
*
* @uses \ReflectionClass
*
* @since 1.0.0
*
* @param string $provider
* @param string $request
* @param array $args Entity instantiation arguments.
*
* @return OptionsAbstract|MailerAbstract|AuthAbstract|null
*/
protected function get_entity( $provider, $request, $args = [] ) {
$provider = sanitize_key( $provider );
$request = sanitize_text_field( $request );
$path = $this->get_provider_path( $provider );
$entity = null;
if ( empty( $path ) ) {
return $entity;
}
try {
$reflection = new \ReflectionClass( $path . $request );
if ( file_exists( $reflection->getFileName() ) ) {
$class = $path . $request;
$entity = new $class( ...$args );
}
}
catch ( \Exception $e ) {
Debug::set( "There was a problem while retrieving {$request} for {$provider}: {$e->getMessage()}" );
$entity = null;
}
return apply_filters( 'wp_mail_smtp_providers_loader_get_entity', $entity, $provider, $request, $args );
}
/**
* Get supports options for all mailers.
*
* @since 2.3.0
*
* @return array
*/
public function get_supports_all() {
$supports = [];
foreach ( $this->get_providers() as $provider => $path ) {
$option = $this->get_options( $provider );
if ( ! $option instanceof OptionsAbstract ) {
continue;
}
$mailer_slug = $option->get_slug();
$mailer_supports = $option->get_supports();
if ( empty( $mailer_slug ) || empty( $mailer_supports ) ) {
continue;
}
$supports[ $mailer_slug ] = $mailer_supports;
}
return apply_filters( 'wp_mail_smtp_providers_loader_get_supports_all', $supports );
}
}

View File

@@ -0,0 +1,49 @@
<?php
namespace WPMailSMTP\Providers\Mail;
use WPMailSMTP\Providers\MailerAbstract;
/**
* Class Mailer inherits everything from parent abstract class.
* This file is required for a proper work of Loader and \ReflectionClass.
*
* @package WPMailSMTP\Providers\Mail
*/
class Mailer extends MailerAbstract {
/**
* @inheritdoc
*/
public function get_debug_info() {
$mail_text = array();
$mail_text[] = '<br><strong>Server:</strong>';
$disabled_functions = ini_get( 'disable_functions' );
$disabled = (array) explode( ',', trim( $disabled_functions ) );
$mail_text[] = '<strong>PHP.mail():</strong> ' . ( in_array( 'mail', $disabled, true ) || ! function_exists( 'mail' ) ? 'No' : 'Yes' );
if ( function_exists( 'apache_get_modules' ) ) {
$modules = apache_get_modules();
$mail_text[] = '<strong>Apache.mod_security:</strong> ' . ( in_array( 'mod_security', $modules, true ) || in_array( 'mod_security2', $modules, true ) ? 'Yes' : 'No' );
}
if ( function_exists( 'selinux_is_enabled' ) ) {
$mail_text[] = '<strong>OS.SELinux:</strong> ' . ( selinux_is_enabled() ? 'Yes' : 'No' );
}
if ( function_exists( 'grsecurity_is_enabled' ) ) {
$mail_text[] = '<strong>OS.grsecurity:</strong> ' . ( grsecurity_is_enabled() ? 'Yes' : 'No' );
}
return implode( '<br>', $mail_text );
}
/**
* @inheritdoc
*/
public function is_mailer_complete() {
return true;
}
}

View File

@@ -0,0 +1,59 @@
<?php
namespace WPMailSMTP\Providers\Mail;
use WPMailSMTP\Admin\SetupWizard;
use WPMailSMTP\Providers\OptionsAbstract;
/**
* Class Option.
*
* @since 1.0.0
*/
class Options extends OptionsAbstract {
/**
* Mail constructor.
*
* @since 1.0.0
*/
public function __construct() {
parent::__construct(
array(
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/php.svg',
'slug' => 'mail',
'title' => esc_html__( 'Default (none)', 'wp-mail-smtp' ),
)
);
}
/**
* @inheritdoc
*/
public function display_options() {
?>
<blockquote>
<?php
printf(
wp_kses( /* translators: %1$s - URL to all mailer doc page. %2$s - URL to the setup wizard. */
__( 'You currently have the <strong>Default (none)</strong> mailer selected, which won\'t improve email deliverability. Please select <a href="%1$s" target="_blank" rel="noopener noreferrer">any other email provider</a> and use the easy <a href="%2$s">Setup Wizard</a> to configure it.', 'wp-mail-smtp' ),
[
'strong' => [],
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/a-complete-guide-to-wp-mail-smtp-mailers/', 'Default mailer - any other email provider' ) ),
esc_url( SetupWizard::get_site_url() )
);
?>
</blockquote>
<?php
}
}

View File

@@ -0,0 +1,672 @@
<?php
namespace WPMailSMTP\Providers;
use WPMailSMTP\Admin\DebugEvents\DebugEvents;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Debug;
use WPMailSMTP\Helpers\Helpers;
use WPMailSMTP\MailCatcherInterface;
use WPMailSMTP\Options;
use WPMailSMTP\WP;
/**
* Class MailerAbstract.
*
* @since 1.0.0
*/
abstract class MailerAbstract implements MailerInterface {
/**
* Which response code from HTTP provider is considered to be successful?
*
* @since 1.0.0
*
* @var int
*/
protected $email_sent_code = 200;
/**
* @since 1.0.0
*
* @var Options
*/
protected $options;
/**
* @since 1.0.0
*
* @var MailCatcherInterface
*/
protected $phpmailer;
/**
* @since 1.0.0
*
* @var string
*/
protected $mailer = '';
/**
* URL to make an API request to.
*
* @since 1.0.0
*
* @var string
*/
protected $url = '';
/**
* @since 1.0.0
*
* @var array
*/
protected $headers = array();
/**
* @since 1.0.0
*
* @var array
*/
protected $body = array();
/**
* @since 1.0.0
*
* @var mixed
*/
protected $response = array();
/**
* The error message recorded when email sending failed and the error can't be processed from the API response.
*
* @since 2.5.0
*
* @var string
*/
protected $error_message = '';
/**
* Should the email sent by this mailer have its "sent status" verified via its API?
*
* @since 2.5.0
*
* @var bool
*/
protected $verify_sent_status = false;
/**
* The Connection object.
*
* @since 3.7.0
*
* @var ConnectionInterface
*/
protected $connection;
/**
* The connection options object.
*
* @since 3.7.0
*
* @var Options
*/
protected $connection_options;
/**
* Mailer constructor.
*
* @since 1.0.0
*
* @param MailCatcherInterface $phpmailer The MailCatcher object.
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( MailCatcherInterface $phpmailer, $connection = null ) {
if ( ! is_null( $connection ) ) {
$this->connection = $connection;
} else {
$this->connection = wp_mail_smtp()->get_connections_manager()->get_primary_connection();
}
$this->connection_options = $this->connection->get_options();
$this->mailer = $this->connection->get_mailer_slug();
$this->options = Options::init();
// Only non-SMTP mailers need URL and extra processing for PHPMailer class.
if ( ! $this->connection_options->is_mailer_smtp() && empty( $this->url ) ) {
return;
}
$this->process_phpmailer( $phpmailer );
}
/**
* Re-use the MailCatcher class methods and properties.
*
* @since 1.0.0
*
* @param MailCatcherInterface $phpmailer The MailCatcher object.
*/
public function process_phpmailer( $phpmailer ) {
// Make sure that we have access to PHPMailer class methods.
if ( ! wp_mail_smtp()->is_valid_phpmailer( $phpmailer ) ) {
return;
}
$this->phpmailer = $phpmailer;
// Prevent working with those methods, as they are not needed for SMTP-like mailers.
if ( $this->connection_options->is_mailer_smtp() ) {
return;
}
$this->set_headers( $this->phpmailer->getCustomHeaders() );
$this->set_from( $this->phpmailer->From, $this->phpmailer->FromName );
$this->set_recipients(
array(
'to' => $this->phpmailer->getToAddresses(),
'cc' => $this->phpmailer->getCcAddresses(),
'bcc' => $this->phpmailer->getBccAddresses(),
)
);
$this->set_subject( $this->phpmailer->Subject );
if ( $this->phpmailer->ContentType === 'text/plain' ) {
$this->set_content( $this->phpmailer->Body );
} else {
$this->set_content(
array(
'text' => $this->phpmailer->AltBody,
'html' => $this->phpmailer->Body,
)
);
}
$this->set_return_path( $this->phpmailer->From );
$this->set_reply_to( $this->phpmailer->getReplyToAddresses() );
/*
* In some cases we will need to modify the internal structure
* of the body content, if attachments are present.
* So lets make this call the last one.
*/
$this->set_attachments( $this->phpmailer->getAttachments() );
}
/**
* Set the email headers.
*
* @since 1.0.0
*
* @param array $headers List of key=>value pairs.
*/
public function set_headers( $headers ) {
foreach ( $headers as $header ) {
$name = isset( $header[0] ) ? $header[0] : false;
$value = isset( $header[1] ) ? $header[1] : false;
if ( empty( $name ) || empty( $value ) ) {
continue;
}
$this->set_header( $name, $value );
}
}
/**
* Set individual header key=>value pair for the email.
*
* @since 1.0.0
*
* @param string $name
* @param string $value
*/
public function set_header( $name, $value ) {
$name = sanitize_text_field( $name );
$this->headers[ $name ] = WP::sanitize_value( $value );
}
/**
* Set email subject.
*
* @since 1.0.0
*
* @param string $subject
*/
public function set_subject( $subject ) {
$this->set_body_param(
array(
'subject' => $subject,
)
);
}
/**
* Set the request params, that goes to the body of the HTTP request.
*
* @since 1.0.0
*
* @param array $param Key=>value of what should be sent to a 3rd party API.
*
* @internal param array $params
*/
protected function set_body_param( $param ) {
$this->body = Options::array_merge_recursive( $this->body, $param );
}
/**
* Get the email body.
*
* @since 1.0.0
*
* @return string|array
*/
public function get_body() {
return apply_filters( 'wp_mail_smtp_providers_mailer_get_body', $this->body, $this->mailer );
}
/**
* Get the email headers.
*
* @since 1.0.0
*
* @return array
*/
public function get_headers() {
return apply_filters( 'wp_mail_smtp_providers_mailer_get_headers', $this->headers, $this->mailer );
}
/**
* Send the email.
*
* @since 1.0.0
* @since 1.8.0 Added timeout for requests, same as max_execution_time.
*/
public function send() {
$timeout = (int) ini_get( 'max_execution_time' );
$params = Options::array_merge_recursive(
$this->get_default_params(),
array(
'headers' => $this->get_headers(),
'body' => $this->get_body(),
'timeout' => $timeout ? $timeout : 30,
)
);
$response = wp_safe_remote_post( $this->url, $params );
DebugEvents::add_debug(
esc_html__( 'An email request was sent.', 'wp-mail-smtp' )
);
$this->process_response( $response );
}
/**
* We might need to do something after the email was sent to the API.
* In this method we preprocess the response from the API.
*
* @since 1.0.0
*
* @param mixed $response Response array.
*/
protected function process_response( $response ) {
if ( is_wp_error( $response ) ) {
// Save the error text.
foreach ( $response->errors as $error_code => $error_message ) {
$this->error_message .= Helpers::format_error_message( $error_message, $error_code ) . WP::EOL;
}
return;
}
if ( isset( $response['body'] ) && WP::is_json( $response['body'] ) ) {
$response['body'] = json_decode( $response['body'] );
}
$this->response = $response;
}
/**
* Get the default params, required for wp_safe_remote_post().
*
* @since 1.0.0
*
* @return array
*/
protected function get_default_params() {
return apply_filters(
'wp_mail_smtp_providers_mailer_get_default_params',
array(
'timeout' => 15,
'httpversion' => '1.1',
'blocking' => true,
),
$this->mailer
);
}
/**
* Whether the email is sent or not.
* We basically check the response code from a request to provider.
* Might not be 100% correct, not guarantees that email is delivered.
*
* @since 1.0.0
*
* @return bool
*/
public function is_email_sent() {
$is_sent = false;
if ( wp_remote_retrieve_response_code( $this->response ) === $this->email_sent_code ) {
$is_sent = true;
}
/**
* Filters whether the email is sent or not.
*
* @since 3.1.0
*
* @param bool $is_sent Whether the email is sent or not.
* @param MailerAbstract $mailer Mailer object.
*/
return apply_filters( 'wp_mail_smtp_providers_mailer_is_email_sent', $is_sent, $this->mailer );
}
/**
* The error message when email sending failed.
* Should be overwritten when appropriate.
*
* @since 1.2.0
* @since 2.5.0 Return a non-empty error_message attribute.
*
* @return string
*/
public function get_response_error() {
return ! empty( $this->error_message ) ? $this->error_message : '';
}
/**
* Whether the mailer supports the current PHP version or not.
*
* @since 1.0.0
*
* @return bool
*/
public function is_php_compatible() {
$options = wp_mail_smtp()->get_providers()->get_options( $this->mailer, $this->connection );
return version_compare( phpversion(), $options->get_php_version(), '>=' );
}
/**
* 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() {
global $phpmailer;
$smtp_text = array();
// Mail mailer has nothing to return.
if ( $this->connection_options->is_mailer_smtp() ) {
// phpcs:disable
$smtp_text[] = '<strong>ErrorInfo:</strong> ' . make_clickable( wp_strip_all_tags( $phpmailer->ErrorInfo ) );
$smtp_text[] = '<strong>Host:</strong> ' . $phpmailer->Host;
$smtp_text[] = '<strong>Port:</strong> ' . $phpmailer->Port;
$smtp_text[] = '<strong>SMTPSecure:</strong> ' . Debug::pvar( $phpmailer->SMTPSecure );
$smtp_text[] = '<strong>SMTPAutoTLS:</strong> ' . Debug::pvar( $phpmailer->SMTPAutoTLS );
$smtp_text[] = '<strong>SMTPAuth:</strong> ' . Debug::pvar( $phpmailer->SMTPAuth );
if ( ! empty( $phpmailer->SMTPOptions ) ) {
$smtp_text[] = '<strong>SMTPOptions:</strong> <code>' . wp_json_encode( $phpmailer->SMTPOptions ) . '</code>';
}
// phpcs:enable
}
$smtp_text[] = '<br><strong>Server:</strong>';
$smtp_text[] = '<strong>OpenSSL:</strong> ' . ( extension_loaded( 'openssl' ) && defined( 'OPENSSL_VERSION_TEXT' ) ? OPENSSL_VERSION_TEXT : 'No' );
if ( function_exists( 'apache_get_modules' ) ) {
$modules = apache_get_modules();
$smtp_text[] = '<strong>Apache.mod_security:</strong> ' . ( in_array( 'mod_security', $modules, true ) || in_array( 'mod_security2', $modules, true ) ? 'Yes' : 'No' );
}
if ( function_exists( 'selinux_is_enabled' ) ) {
$smtp_text[] = '<strong>OS.SELinux:</strong> ' . ( selinux_is_enabled() ? 'Yes' : 'No' );
}
if ( function_exists( 'grsecurity_is_enabled' ) ) {
$smtp_text[] = '<strong>OS.grsecurity:</strong> ' . ( grsecurity_is_enabled() ? 'Yes' : 'No' );
}
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,
],
];
}
/**
* Should the email sent by this mailer have its "sent status" verified via its API?
*
* @since 2.5.0
*
* @return bool
*/
public function should_verify_sent_status() {
return $this->verify_sent_status;
}
/**
* Verify the "sent status" of the provided email log ID.
* The actual verification background task is triggered in the below action hook.
*
* @since 2.5.0
*
* @param int $email_log_id The ID of the email log.
*/
public function verify_sent_status( $email_log_id ) {
if ( ! $this->should_verify_sent_status() ) {
return;
}
do_action( 'wp_mail_smtp_providers_mailer_verify_sent_status', $email_log_id, $this );
}
/**
* Get the name/slug of the current mailer.
*
* @since 2.5.0
*
* @return string
*/
public function get_mailer_name() {
return $this->mailer;
}
/**
* Get PHPMailer attachment file content.
*
* @since 3.1.0
*
* @param array $attachment PHPMailer attachment.
*
* @return string|false
*/
public function get_attachment_file_content( $attachment ) {
$file = false;
/*
* We are not using WP_Filesystem API as we can't reliably work with it.
* It is not always available, same as credentials for FTP.
*/
try {
if ( $attachment[5] === true ) { // Whether there is string attachment.
$file = $attachment[0];
} elseif ( is_file( $attachment[0] ) && is_readable( $attachment[0] ) ) {
$file = file_get_contents( $attachment[0] );
}
} catch ( \Exception $e ) { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement.DetectedCatch
// We don't handle this exception as we define a default value above.
}
return $file;
}
/**
* Get PHPMailer attachment file size.
*
* @since 3.4.0
*
* @param array $attachment PHPMailer attachment.
*
* @return int|false
*/
public function get_attachment_file_size( $attachment ) {
$size = false;
if ( $attachment[5] === true ) { // Whether there is string attachment.
$size = Helpers::strsize( $attachment[0] );
} elseif ( is_file( $attachment[0] ) && is_readable( $attachment[0] ) ) {
$size = filesize( $attachment[0] );
}
return $size;
}
/**
* Get PHPMailer attachment file name.
*
* @since 3.4.0
*
* @param array $attachment PHPMailer attachment.
*
* @return string
*/
public function get_attachment_file_name( $attachment ) {
$filetype = str_replace( ';', '', trim( $attachment[4] ) );
return ! empty( $attachment[2] ) ? trim( $attachment[2] ) : 'file-' . wp_hash( microtime() ) . '.' . $filetype;
}
/**
* Perform remote request with merged default params.
*
* @since 3.4.0
*
* @param string $url Request url.
* @param array $params Request params.
*
* @return array
*/
public function remote_request( $url, $params ) {
if ( ! isset( $params['method'] ) ) {
$params['method'] = 'POST';
}
$params = Options::array_merge_recursive( $this->get_default_params(), $params );
/**
* Filters request params.
*
* @since 3.4.0
*
* @param array $params Request params.
* @param MailerAbstract $mailer Mailer object.
*/
$params = apply_filters( 'wp_mail_smtp_providers_mailer_remote_request_params', $params, $this );
/**
* Filters request url.
*
* @since 3.4.0
*
* @param string $url Request url.
* @param MailerAbstract $mailer Mailer object.
*/
$url = apply_filters( 'wp_mail_smtp_providers_mailer_remote_request_url', $url, $this );
return wp_safe_remote_request( $url, $params );
}
/**
* Get the Connection object.
*
* @since 3.7.0
*
* @return ConnectionInterface
*/
public function get_connection() {
return $this->connection;
}
}

View File

@@ -0,0 +1,86 @@
<?php
namespace WPMailSMTP\Providers;
use WPMailSMTP\MailCatcher;
use WPMailSMTP\MailCatcherV6;
/**
* Interface MailerInterface.
*
* @since 1.0.0
*/
interface MailerInterface {
/**
* Send the email.
*
* @since 1.0.0
*/
public function send();
/**
* Whether the email is sent or not.
* We basically check the response code from a request to provider.
* Might not be 100% correct, not guarantees that email is delivered.
*
* @since 1.0.0
*
* @return bool
*/
public function is_email_sent();
/**
* Whether the mailer supports the current PHP version or not.
*
* @since 1.0.0
*
* @return bool
*/
public function is_php_compatible();
/**
* Whether the mailer has all its settings correctly set up and saved.
*
* @since 1.4.0
*
* @return bool
*/
public function is_mailer_complete();
/**
* Get the email body.
*
* @since 1.0.0
*
* @return string|array
*/
public function get_body();
/**
* Get the email headers.
*
* @since 1.0.0
*
* @return array
*/
public function get_headers();
/**
* Get an array of all debug information relevant to the mailer.
*
* @since 1.2.0
*
* @return array
*/
public function get_debug_info();
/**
* Re-use the MailCatcher class methods and properties.
*
* @since 1.2.0
*
* @param MailCatcherInterface $phpmailer The MailCatcher object.
*/
public function process_phpmailer( $phpmailer );
}

View File

@@ -0,0 +1,468 @@
<?php
namespace WPMailSMTP\Providers\Mailgun;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Helpers\Helpers;
use WPMailSMTP\MailCatcherInterface;
use WPMailSMTP\Providers\MailerAbstract;
use WPMailSMTP\WP;
/**
* Class Mailer.
*
* @since 1.0.0
*/
class Mailer extends MailerAbstract {
/**
* Which response code from HTTP provider is considered to be successful?
*
* @since 1.0.0
*
* @var int
*/
protected $email_sent_code = 200;
/**
* API endpoint used for sites from all regions.
*
* @since 1.4.0
*
* @var string
*/
const API_BASE_US = 'https://api.mailgun.net/v3/';
/**
* API endpoint used for sites from EU region.
*
* @since 1.4.0
*
* @var string
*/
const API_BASE_EU = 'https://api.eu.mailgun.net/v3/';
/**
* URL to make an API request to.
*
* @since 1.0.0
*
* @var string
*/
protected $url = '';
/**
* Mailer constructor.
*
* @since 1.0.0
*
* @param MailCatcherInterface $phpmailer The MailCatcher object.
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $phpmailer, $connection = null ) {
// Default value should be defined before the parent class contructor fires.
$this->url = self::API_BASE_US;
// We want to prefill everything from MailCatcher class, which extends PHPMailer.
parent::__construct( $phpmailer, $connection );
// We have a special API URL to query in case of EU region.
if ( $this->connection_options->get( $this->mailer, 'region' ) === 'EU' ) {
$this->url = self::API_BASE_EU;
}
/*
* Append the url with a domain,
* to avoid passing the domain name as a query parameter with all requests.
*/
$this->url .= sanitize_text_field( $this->connection_options->get( $this->mailer, 'domain' ) . '/messages' );
$this->set_header( 'Authorization', 'Basic ' . base64_encode( 'api:' . $this->connection_options->get( $this->mailer, 'api_key' ) ) );
}
/**
* @inheritdoc
*/
public function set_from( $email, $name = '' ) {
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
return;
}
if ( ! empty( $name ) ) {
$this->set_body_param(
array(
'from' => $name . ' <' . $email . '>',
)
);
} else {
$this->set_body_param(
array(
'from' => $email,
)
);
}
}
/**
* @inheritdoc
*/
public function set_recipients( $recipients ) {
if ( empty( $recipients ) ) {
return;
}
$default = array( 'to', 'cc', 'bcc' );
foreach ( $recipients as $kind => $emails ) {
if (
! in_array( $kind, $default, true ) ||
empty( $emails ) ||
! is_array( $emails )
) {
continue;
}
$data = array();
foreach ( $emails as $email ) {
$addr = isset( $email[0] ) ? $email[0] : false;
$name = isset( $email[1] ) ? $email[1] : false;
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
continue;
}
if ( ! empty( $name ) ) {
$data[] = $name . ' <' . $addr . '>';
} else {
$data[] = $addr;
}
}
if ( ! empty( $data ) ) {
$this->set_body_param(
array(
$kind => implode( ', ', $data ),
)
);
}
}
}
/**
* @inheritdoc
*/
public function set_content( $content ) {
if ( is_array( $content ) ) {
$default = array( 'text', 'html' );
foreach ( $content as $type => $mail ) {
if (
! in_array( $type, $default, true ) ||
empty( $mail )
) {
continue;
}
$this->set_body_param(
array(
$type => $mail,
)
);
}
} else {
$type = 'html';
if ( $this->phpmailer->ContentType === 'text/plain' ) {
$type = 'text';
}
if ( ! empty( $content ) ) {
$this->set_body_param(
array(
$type => $content,
)
);
}
}
}
/**
* Redefine the way custom headers are process for this mailer - they should be in body.
*
* @since 1.5.0
*
* @param array $headers
*/
public function set_headers( $headers ) {
foreach ( $headers as $header ) {
$name = isset( $header[0] ) ? $header[0] : false;
$value = isset( $header[1] ) ? $header[1] : false;
$this->set_body_header( $name, $value );
}
// Add custom PHPMailer-specific header.
$this->set_body_header( 'X-Mailer', 'WPMailSMTP/Mailer/' . $this->mailer . ' ' . WPMS_PLUGIN_VER );
}
/**
* This mailer supports email-related custom headers inside a body of the message with a special prefix "h:".
*
* @since 1.5.0
*/
public function set_body_header( $name, $value ) {
$name = sanitize_text_field( $name );
$this->set_body_param(
array(
'h:' . $name => WP::sanitize_value( $value ),
)
);
}
/**
* It's the last one, so we can modify the whole body.
*
* @since 1.0.0
*
* @param array $attachments The array of attachments data.
*/
public function set_attachments( $attachments ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh, Generic.Metrics.NestingLevel.MaxExceeded
if ( empty( $attachments ) ) {
return;
}
$payload = '';
$data = [];
foreach ( $attachments as $attachment ) {
$file = $this->get_attachment_file_content( $attachment );
if ( $file === false ) {
continue;
}
$data[] = [
'content' => $file,
'name' => $this->get_attachment_file_name( $attachment ),
];
}
if ( ! empty( $data ) ) {
// First, generate a boundary for the multipart message.
$boundary = $this->phpmailer->generate_id();
// Iterate through pre-built params and build a payload.
foreach ( $this->body as $key => $value ) {
if ( is_array( $value ) ) {
foreach ( $value as $child_value ) {
$payload .= '--' . $boundary;
$payload .= "\r\n";
$payload .= 'Content-Disposition: form-data; name="' . $key . "\"\r\n\r\n";
$payload .= $child_value;
$payload .= "\r\n";
}
} else {
$payload .= '--' . $boundary;
$payload .= "\r\n";
$payload .= 'Content-Disposition: form-data; name="' . $key . '"' . "\r\n\r\n";
$payload .= $value;
$payload .= "\r\n";
}
}
// Now iterate through our attachments, and add them too.
foreach ( $data as $key => $attachment ) {
$payload .= '--' . $boundary;
$payload .= "\r\n";
$payload .= 'Content-Disposition: form-data; name="attachment[' . $key . ']"; filename="' . $attachment['name'] . '"' . "\r\n\r\n";
$payload .= $attachment['content'];
$payload .= "\r\n";
}
$payload .= '--' . $boundary . '--';
// Redefine the body the "dirty way".
$this->body = $payload;
$this->set_header( 'Content-Type', 'multipart/form-data; boundary=' . $boundary );
}
}
/**
* @inheritdoc
*/
public function set_reply_to( $reply_to ) {
if ( empty( $reply_to ) ) {
return;
}
$data = array();
foreach ( $reply_to as $key => $emails ) {
if (
empty( $emails ) ||
! is_array( $emails )
) {
continue;
}
$addr = isset( $emails[0] ) ? $emails[0] : false;
$name = isset( $emails[1] ) ? $emails[1] : false;
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
continue;
}
if ( ! empty( $name ) ) {
$data[] = $name . ' <' . $addr . '>';
} else {
$data[] = $addr;
}
}
if ( ! empty( $data ) ) {
$this->set_body_param(
array(
'h:Reply-To' => implode( ',', $data ),
)
);
}
}
/**
* @inheritdoc
*/
public function set_return_path( $email ) {
if (
$this->connection_options->get( 'mail', 'return_path' ) !== true ||
! filter_var( $email, FILTER_VALIDATE_EMAIL )
) {
return;
}
$this->set_body_param(
array(
'sender' => $email,
)
);
}
/**
* We might need to do something after the email was sent to the API.
* In this method we preprocess the response from the API.
*
* @since 2.5.0
*
* @param mixed $response Response data.
*/
protected function process_response( $response ) {
parent::process_response( $response );
if ( is_wp_error( $response ) ) {
return;
}
if ( ! empty( $this->response['body']->id ) ) {
$this->phpmailer->MessageID = $this->response['body']->id;
$this->verify_sent_status = true;
}
}
/**
* Whether the email is sent or not.
* We basically check the response code from a request to provider.
* Might not be 100% correct, not guarantees that email is delivered.
*
* In Mailgun's case it looks like we have to check if the response body has the message ID.
* All successful API responses should have `id` key in the response body.
*
* @since 2.2.0
*
* @return bool
*/
public function is_email_sent() {
$is_sent = false;
if (
wp_remote_retrieve_response_code( $this->response ) === $this->email_sent_code &&
! empty( $this->response['body']->id )
) {
$is_sent = true;
}
/** This filter is documented in src/Providers/MailerAbstract.php. */
return apply_filters( 'wp_mail_smtp_providers_mailer_is_email_sent', $is_sent, $this->mailer );
}
/**
* Get a Mailgun-specific response with a helpful error.
*
* @since 1.2.0
*
* @return string
*/
public function get_response_error() {
$error_text[] = $this->error_message;
if ( ! empty( $this->response ) ) {
$body = wp_remote_retrieve_body( $this->response );
if ( ! empty( $body->message ) ) {
$error_text[] = Helpers::format_error_message( $body->message );
} else {
$error_text[] = WP::wp_remote_get_response_error_message( $this->response );
}
}
return implode( WP::EOL, array_map( 'esc_textarea', array_filter( $error_text ) ) );
}
/**
* @inheritdoc
*/
public function get_debug_info() {
$mg_text = array();
$mailgun = $this->connection_options->get_group( $this->mailer );
$mg_text[] = '<strong>Api Key / Domain:</strong> ' . ( ! empty( $mailgun['api_key'] ) && ! empty( $mailgun['domain'] ) ? 'Yes' : 'No' );
return implode( '<br>', $mg_text );
}
/**
* @inheritdoc
*/
public function is_mailer_complete() {
$options = $this->connection_options->get_group( $this->mailer );
// API key is the only required option.
if (
! empty( $options['api_key'] ) &&
! empty( $options['domain'] )
) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,169 @@
<?php
namespace WPMailSMTP\Providers\Mailgun;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Providers\OptionsAbstract;
/**
* Class Option.
*
* @since 1.0.0
*/
class Options extends OptionsAbstract {
/**
* Mailgun constructor.
*
* @since 1.0.0
*
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $connection = null ) {
parent::__construct(
array(
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/mailgun.svg',
'slug' => 'mailgun',
'title' => esc_html__( 'Mailgun', 'wp-mail-smtp' ),
'description' => sprintf(
wp_kses(
/* translators: %1$s - URL to mailgun.com; %2$s - URL to Mailgun documentation on wpmailsmtp.com */
__( '<a href="%1$s" target="_blank" rel="noopener noreferrer">Mailgun</a> is a transactional email provider that offers a generous 3-month free trial. After that, it offers a \'Pay As You Grow\' plan that allows you to pay for what you use without committing to a fixed monthly rate.<br><br>To get started, read our <a href="%2$s" target="_blank" rel="noopener noreferrer">Mailgun documentation</a>.', 'wp-mail-smtp' ),
array(
'br' => array(),
'a' => array(
'href' => array(),
'rel' => array(),
'target' => array(),
),
)
),
'https://www.mailgun.com',
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-set-up-the-mailgun-mailer-in-wp-mail-smtp/', 'Mailgun documentation' ) )
),
),
$connection
);
}
/**
* @inheritdoc
*/
public function display_options() {
?>
<!-- API Key -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'Mailgun API Key', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php if ( $this->connection_options->is_const_defined( $this->get_slug(), 'api_key' ) ) : ?>
<input type="text" disabled value="****************************************"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php $this->display_const_set_message( 'WPMS_MAILGUN_API_KEY' ); ?>
<?php else : ?>
<input type="password" spellcheck="false"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'api_key' ) ); ?>"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php endif; ?>
<p class="desc">
<?php
echo wp_kses(
sprintf( /* translators: %s - API key URL. */
__( 'Follow this link to <a href="%s" target="_blank" rel="noopener noreferrer">get a Mailgun API Key</a>. Generate a key in the "Mailgun API Keys" section.', 'wp-mail-smtp' ),
'https://app.mailgun.com/settings/api_security'
),
[
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
);
?>
</p>
</div>
</div>
<!-- Domain -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-domain" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-domain"><?php esc_html_e( 'Domain Name', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][domain]" type="text"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'domain' ) ); ?>"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'domain' ) ? 'disabled' : ''; ?>
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-domain" spellcheck="false"
/>
<p class="desc">
<?php
printf(
/* translators: %s - Domain Name link. */
esc_html__( 'Follow this link to get a Domain Name from Mailgun: %s.', 'wp-mail-smtp' ),
'<a href="https://app.mailgun.com/app/sending/domains" target="_blank" rel="noopener noreferrer">' .
esc_html__( 'Get a Domain Name', 'wp-mail-smtp' ) .
'</a>'
);
?>
</p>
</div>
</div>
<!-- Region -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-region" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-radio wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'Region', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-region-us">
<input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-region-us"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][region]" value="US"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'region' ) ? 'disabled' : ''; ?>
<?php checked( 'US', $this->connection_options->get( $this->get_slug(), 'region' ) ); ?>
/>
<?php esc_html_e( 'US', 'wp-mail-smtp' ); ?>
</label>
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-region-eu">
<input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-region-eu"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][region]" value="EU"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'region' ) ? 'disabled' : ''; ?>
<?php checked( 'EU', $this->connection_options->get( $this->get_slug(), 'region' ) ); ?>
/>
<?php esc_html_e( 'EU', 'wp-mail-smtp' ); ?>
</label>
<p class="desc">
<?php esc_html_e( 'Define which endpoint you want to use for sending messages.', 'wp-mail-smtp' ); ?><br>
<?php esc_html_e( 'If you are operating under EU laws, you may be required to use EU region.', 'wp-mail-smtp' ); ?>
<?php
printf(
wp_kses(
/* translators: %s - URL to Mailgun.com page. */
__( '<a href="%s" rel="" target="_blank">More information</a> on Mailgun.com.', 'wp-mail-smtp' ),
array(
'a' => array(
'href' => array(),
'rel' => array(),
'target' => array(),
),
)
),
'https://www.mailgun.com/regions'
);
?>
</p>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,540 @@
<?php
namespace WPMailSMTP\Providers;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Helpers\UI;
use WPMailSMTP\Options;
/**
* Abstract Class ProviderAbstract to contain common providers functionality.
*
* @since 1.0.0
*/
abstract class OptionsAbstract implements OptionsInterface {
/**
* @var string
*/
private $logo_url = '';
/**
* @var string
*/
private $slug = '';
/**
* @var string
*/
private $title = '';
/**
* @var string
*/
private $description = '';
/**
* @since 1.6.0
*
* @var array
*/
private $notices = array();
/**
* @since 1.6.0
*
* @var bool
*/
private $recommended = false;
/**
* @since 1.7.0
*
* @var bool
*/
private $disabled = false;
/**
* @var string
*/
private $php = WPMS_PHP_VER;
/**
* @var Options
*/
protected $options;
/**
* An array with mailer supported setting fields.
*
* @since 2.3.0
*
* @var array
*/
protected $supports;
/**
* The Connection object.
*
* @since 3.7.0
*
* @var ConnectionInterface
*/
protected $connection;
/**
* The connection options object.
*
* @since 3.7.0
*
* @var Options
*/
protected $connection_options;
/**
* ProviderAbstract constructor.
*
* @since 1.0.0
* @since 2.3.0 Added supports parameter.
*
* @param array $params The mailer options parameters.
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $params, $connection = null ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
if ( ! is_null( $connection ) ) {
$this->connection = $connection;
} else {
$this->connection = wp_mail_smtp()->get_connections_manager()->get_primary_connection();
}
$this->connection_options = $this->connection->get_options();
if (
empty( $params['slug'] ) ||
empty( $params['title'] )
) {
return;
}
$this->slug = sanitize_key( $params['slug'] );
$this->title = sanitize_text_field( $params['title'] );
if ( ! empty( $params['description'] ) ) {
$this->description = wp_kses_post( $params['description'] );
}
if ( ! empty( $params['notices'] ) ) {
foreach ( (array) $params['notices'] as $key => $notice ) {
$key = sanitize_key( $key );
if ( empty( $key ) ) {
continue;
}
$notice = wp_kses(
$notice,
array(
'br' => true,
'strong' => true,
'em' => true,
'a' => array(
'href' => true,
'rel' => true,
'target' => true,
),
)
);
if ( empty( $notice ) ) {
continue;
}
$this->notices[ $key ] = $notice;
}
}
if ( isset( $params['recommended'] ) ) {
$this->recommended = (bool) $params['recommended'];
}
if ( isset( $params['disabled'] ) ) {
$this->disabled = (bool) $params['disabled'];
}
if ( ! empty( $params['php'] ) ) {
$this->php = sanitize_text_field( $params['php'] );
}
if ( ! empty( $params['logo_url'] ) ) {
$this->logo_url = esc_url_raw( $params['logo_url'] );
}
$this->supports = ( ! empty( $params['supports'] ) ) ? $params['supports'] : $this->get_supports_defaults();
$this->options = Options::init();
}
/**
* @inheritdoc
*/
public function get_logo_url() {
return apply_filters( 'wp_mail_smtp_providers_provider_get_logo_url', $this->logo_url, $this );
}
/**
* @inheritdoc
*/
public function get_slug() {
return apply_filters( 'wp_mail_smtp_providers_provider_get_slug', $this->slug, $this );
}
/**
* @inheritdoc
*/
public function get_title() {
return apply_filters( 'wp_mail_smtp_providers_provider_get_title', $this->title, $this );
}
/**
* @inheritdoc
*/
public function get_description() {
return apply_filters( 'wp_mail_smtp_providers_provider_get_description', $this->description, $this );
}
/**
* Some mailers may display a notice above its options.
*
* @since 1.6.0
*
* @param string $type
*
* @return string
*/
public function get_notice( $type ) {
$type = sanitize_key( $type );
return apply_filters( 'wp_mail_smtp_providers_provider_get_notice', isset( $this->notices[ $type ] ) ? $this->notices[ $type ] : '', $this );
}
/**
* @inheritdoc
*/
public function get_php_version() {
return apply_filters( 'wp_mail_smtp_providers_provider_get_php_version', $this->php, $this );
}
/**
* @inheritdoc
*/
public function display_options() {
?>
<!-- SMTP Host -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-host" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-host"><?php esc_html_e( 'SMTP Host', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][host]" type="text"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'host' ) ); ?>"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'host' ) ? 'disabled' : ''; ?>
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-host" spellcheck="false"
/>
</div>
</div>
<!-- SMTP Encryption -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-encryption" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-radio wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label><?php esc_html_e( 'Encryption', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-none">
<input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-none"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][encryption]" value="none"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'encryption' ) ? 'disabled' : ''; ?>
<?php checked( 'none', $this->connection_options->get( $this->get_slug(), 'encryption' ) ); ?>
/>
<?php esc_html_e( 'None', 'wp-mail-smtp' ); ?>
</label>
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-ssl">
<input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-ssl"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][encryption]" value="ssl"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'encryption' ) ? 'disabled' : ''; ?>
<?php checked( 'ssl', $this->connection_options->get( $this->get_slug(), 'encryption' ) ); ?>
/>
<?php esc_html_e( 'SSL', 'wp-mail-smtp' ); ?>
</label>
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-tls">
<input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-enc-tls"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][encryption]" value="tls"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'encryption' ) ? 'disabled' : ''; ?>
<?php checked( 'tls', $this->connection_options->get( $this->get_slug(), 'encryption' ) ); ?>
/>
<?php esc_html_e( 'TLS', 'wp-mail-smtp' ); ?>
</label>
<p class="desc">
<?php esc_html_e( 'For most servers TLS is the recommended option. If your SMTP provider offers both SSL and TLS options, we recommend using TLS.', 'wp-mail-smtp' ); ?>
</p>
</div>
</div>
<!-- SMTP Port -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-port" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-number wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-port"><?php esc_html_e( 'SMTP Port', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][port]" type="number"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'port' ) ); ?>"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'port' ) ? 'disabled' : ''; ?>
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-port" class="small-text" spellcheck="false"
/>
</div>
</div>
<!-- PHPMailer SMTPAutoTLS -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-autotls" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle wp-mail-smtp-clear <?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'encryption' ) || 'tls' === $this->connection_options->get( $this->get_slug(), 'encryption' ) ? 'inactive' : ''; ?>">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-autotls"><?php esc_html_e( 'Auto TLS', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[' . $this->get_slug() . '][autotls]',
'id' => 'wp-mail-smtp-setting-' . $this->get_slug() . '-autotls',
'checked' => (bool) $this->connection_options->get( $this->get_slug(), 'autotls' ),
'disabled' => $this->connection_options->is_const_defined( $this->get_slug(), 'autotls' ),
]
);
?>
<p class="desc">
<?php esc_html_e( 'By default, TLS encryption is automatically used if the server supports it (recommended). In some cases, due to server misconfigurations, this can cause issues and may need to be disabled.', 'wp-mail-smtp' ); ?>
</p>
</div>
</div>
<!-- SMTP Authentication -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-auth" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-checkbox-toggle wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-auth"><?php esc_html_e( 'Authentication', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php
UI::toggle(
[
'name' => 'wp-mail-smtp[' . $this->get_slug() . '][auth]',
'id' => 'wp-mail-smtp-setting-' . $this->get_slug() . '-auth',
'checked' => (bool) $this->connection_options->get( $this->get_slug(), 'auth' ),
'disabled' => $this->connection_options->is_const_defined( $this->get_slug(), 'auth' ),
]
);
?>
</div>
</div>
<!-- SMTP Username -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-user" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear <?php echo ! $this->connection_options->is_const_defined( $this->get_slug(), 'auth' ) && ! $this->connection_options->get( $this->get_slug(), 'auth' ) ? 'inactive' : ''; ?>">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-user"><?php esc_html_e( 'SMTP Username', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][user]" type="text"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'user' ) ); ?>"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'user' ) ? 'disabled' : ''; ?>
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-user" spellcheck="false" autocomplete="new-password"
/>
</div>
</div>
<!-- SMTP Password -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-pass" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-password wp-mail-smtp-clear <?php echo ! $this->connection_options->is_const_defined( $this->get_slug(), 'auth' ) && ! $this->connection_options->get( $this->get_slug(), 'auth' ) ? 'inactive' : ''; ?>">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-pass"><?php esc_html_e( 'SMTP Password', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php if ( $this->connection_options->is_const_defined( $this->get_slug(), 'pass' ) ) : ?>
<input type="text" value="*************" disabled id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-pass"/>
<?php $this->display_const_set_message( 'WPMS_SMTP_PASS' ); ?>
<p class="desc">
<?php
printf(
/* translators: %s - constant name: WPMS_SMTP_PASS. */
esc_html__( 'To change the password you need to change the value of the constant there: %s', 'wp-mail-smtp' ),
'<code>define( \'WPMS_SMTP_PASS\', \'your_old_password\' );</code>'
);
?>
<br>
<?php
printf(
/* translators: %1$s - wp-config.php file, %2$s - WPMS_ON constant name. */
esc_html__( 'If you want to disable the use of constants, find in %1$s file the constant %2$s and turn if off:', 'wp-mail-smtp' ),
'<code>wp-config.php</code>',
'<code>WPMS_ON</code>'
);
?>
</p>
<pre>
define( 'WPMS_ON', false );
</pre>
<p class="desc">
<?php esc_html_e( 'All the defined constants will stop working and you will be able to change all the values on this page.', 'wp-mail-smtp' ); ?>
</p>
<?php else : ?>
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][pass]" type="password"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'pass' ) ); ?>"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-pass" spellcheck="false" autocomplete="new-password"
/>
<p class="desc">
<?php esc_html_e( 'The password is encrypted in the database, but for improved security we recommend using your site\'s WordPress configuration file to set your password.', 'wp-mail-smtp' ); ?>
<br>
<?php
printf(
'<a href="%1$s" target="_blank" rel="noopener noreferrer"><strong>%2$s</strong></a>',
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-secure-smtp-settings-by-using-constants/', 'SMTP Password - Learn More' ) ),
esc_html__( 'Learn More', 'wp-mail-smtp' )
)
?>
</p>
<?php endif; ?>
</div>
</div>
<?php
}
/**
* Whether this mailer is recommended or not.
*
* @since 1.6.0
*
* @return bool
*/
public function is_recommended() {
return (bool) apply_filters( 'wp_mail_smtp_providers_provider_is_recommended', $this->recommended, $this );
}
/**
* Whether this mailer is disabled or not.
* Used for displaying Pro mailers inside Lite plugin.
*
* @since 1.7.0
*
* @return bool
*/
public function is_disabled() {
return (bool) apply_filters( 'wp_mail_smtp_providers_provider_is_disabled', $this->disabled, $this );
}
/**
* Check whether we can use this provider based on the PHP version.
* Valid for those, that use SDK.
*
* @since 1.0.0
*
* @return bool
*/
public function is_php_correct() {
return version_compare( phpversion(), $this->php, '>=' );
}
/**
* Display a helpful message to those users, that are using an outdated version of PHP,
* which is not supported by the currently selected Provider.
*
* @since 1.0.0
*/
protected function display_php_warning() {
?>
<blockquote>
<?php
printf(
/* translators: %1$s - Provider name; %2$s - PHP version required by Provider; %3$s - current PHP version. */
esc_html__( '%1$s requires PHP %2$s to work and does not support your current PHP version %3$s. Please contact your host and request a PHP upgrade to the latest one.', 'wp-mail-smtp' ),
esc_html( $this->get_title() ),
esc_html( $this->php ),
esc_html( phpversion() )
);
?>
<br>
<?php esc_html_e( 'Meanwhile you can switch to some other mailers.', 'wp-mail-smtp' ); ?>
</blockquote>
<?php
}
/**
* Display a helpful message to those users, that are using an outdated version of PHP,
* which is not supported by the currently selected Provider.
*
* @since 1.5.0
*/
protected function display_ssl_warning() {
?>
<blockquote>
<?php
printf(
wp_kses( /* translators: %s - Provider name */
__( '%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() )
);
?>
<br>
<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>
<?php
}
/**
* Display a message of a constant that was set inside wp-config.php file.
*
* @since 1.5.0
*
* @param string $constant Constant name.
*/
protected function display_const_set_message( $constant ) {
printf( '<p class="desc">%s</p>', $this->options->get_const_set_message( $constant ) ); //phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped
}
/**
* Return the defaults for the mailer supported settings.
*
* @since 2.3.0
*
* @return array
*/
public function get_supports_defaults() {
return [
'from_email' => true,
'from_name' => true,
'return_path' => true,
'from_email_force' => true,
'from_name_force' => true,
];
}
/**
* Get the mailer supported settings.
*
* @since 2.3.0
*
* @return array
*/
public function get_supports() {
return apply_filters( 'wp_mail_smtp_providers_provider_get_supports', $this->supports, $this );
}
}

View File

@@ -0,0 +1,71 @@
<?php
namespace WPMailSMTP\Providers;
/**
* Interface ProviderInterface, shared between all current and future providers.
* Defines required methods across all providers.
*
* @since 1.0.0
*/
interface OptionsInterface {
/**
* Get the mailer provider slug.
*
* @since 1.0.0
*
* @return string
*/
public function get_slug();
/**
* Get the mailer provider title (or name).
*
* @since 1.0.0
*
* @return string
*/
public function get_title();
/**
* Get the mailer provider description.
*
* @since 1.0.0
*
* @return string
*/
public function get_description();
/**
* Get the mailer provider minimum PHP version.
*
* @since 1.0.0
*
* @return string
*/
public function get_php_version();
/**
* Get the mailer provider logo URL.
*
* @since 1.0.0
*
* @return string
*/
public function get_logo_url();
/**
* Output the mailer provider options.
*
* @since 1.0.0
*/
public function display_options();
/**
* Get the mailer supported settings.
*
* @since 2.3.0
*/
public function get_supports();
}

View File

@@ -0,0 +1,44 @@
<?php
namespace WPMailSMTP\Providers\Outlook;
use WPMailSMTP\Providers\OptionsAbstract;
/**
* Class Options.
*
* @since 1.7.0
*/
class Options extends OptionsAbstract {
/**
* Outlook Options constructor.
*
* @since 1.7.0
*/
public function __construct() {
parent::__construct(
array(
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/microsoft.svg',
'slug' => 'outlook',
'title' => esc_html__( '365 / Outlook', 'wp-mail-smtp' ),
'disabled' => true,
)
);
}
/**
* @inheritdoc
*/
public function display_options() {
?>
<div class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-content wp-mail-smtp-clear section-heading">
<p>
<?php esc_html_e( 'We\'re sorry, the Microsoft Outlook mailer is not available on your plan. Please upgrade to the PRO plan to unlock all these awesome features.', 'wp-mail-smtp' ); ?>
</p>
</div>
<?php
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace WPMailSMTP\Providers\Pepipost;
use WPMailSMTP\Providers\MailerAbstract;
/**
* Class Mailer inherits everything from parent abstract class.
* This file is required for a proper work of Loader and \ReflectionClass.
*
* @package WPMailSMTP\Providers\Pepipost
*/
class Mailer extends MailerAbstract {
/**
* @inheritdoc
*/
public function is_mailer_complete() {
$options = $this->options->get_group( $this->mailer );
// Host and Port are the only really required options.
if (
! empty( $options['host'] ) &&
! empty( $options['port'] )
) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,29 @@
<?php
namespace WPMailSMTP\Providers\Pepipost;
use WPMailSMTP\Providers\OptionsAbstract;
/**
* Class Options.
*
* @since 1.0.0
*/
class Options extends OptionsAbstract {
/**
* Pepipost constructor.
*
* @since 1.0.0
*/
public function __construct() {
parent::__construct(
array(
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/pepipost-smtp.png',
'slug' => 'pepipost',
'title' => esc_html__( 'Pepipost SMTP', 'wp-mail-smtp' ),
)
);
}
}

View File

@@ -0,0 +1,477 @@
<?php
namespace WPMailSMTP\Providers\PepipostAPI;
use WPMailSMTP\MailCatcherInterface;
use WPMailSMTP\Options as PluginOptions;
use WPMailSMTP\Providers\MailerAbstract;
use WPMailSMTP\WP;
/**
* Pepipost API mailer.
*
* @since 1.8.0 Pepipost - SendGrid migration API.
* @since 2.2.0 Rewrote this class to use native Pepipost API.
*/
class Mailer extends MailerAbstract {
/**
* Which response code from HTTP provider is considered to be successful?
*
* @since 1.8.0
*
* @var int
*/
protected $email_sent_code = 202;
/**
* URL to make an API request to.
*
* @since 1.8.0
* @since 2.2.0 Changed the API url to Pepipost API v5.
*
* @var string
*/
protected $url = 'https://api.pepipost.com/v5/mail/send';
/**
* Mailer constructor.
*
* @since 1.8.0
* @since 2.2.0 Changed the API key header (API v5 changes).
*
* @param MailCatcherInterface $phpmailer The MailCatcher instance.
*/
public function __construct( $phpmailer ) {
// We want to prefill everything from MailCatcher class, which extends PHPMailer.
parent::__construct( $phpmailer );
$this->set_header( 'api_key', $this->options->get( $this->mailer, 'api_key' ) );
$this->set_header( 'content-type', 'application/json' );
}
/**
* Redefine the way email body is returned.
* By default we are sending an array of data.
* Pepipost requires a JSON, so we encode the body.
*
* @since 1.8.0
*
* @return string
*/
public function get_body() {
$body = parent::get_body();
return wp_json_encode( $body );
}
/**
* Set the FROM header of the email.
*
* @since 1.8.0
* @since 2.2.0 Changed the attribute names (API v5 changes).
*
* @param string $email From mail.
* @param string $name From name.
*/
public function set_from( $email, $name = '' ) {
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
return;
}
$from['email'] = $email;
if ( ! empty( $name ) ) {
$from['name'] = $name;
}
$this->set_body_param(
[
'from' => $from,
]
);
}
/**
* Set the names/emails of people who will receive the email.
*
* @since 1.8.0
* @since 2.2.0 change the attribute names (API v5 changes).
*
* @param array $recipients List of recipients: cc/bcc/to.
*/
public function set_recipients( $recipients ) {
if ( empty( $recipients ) ) {
return;
}
$data = [];
if ( ! empty( $recipients['to'] ) ) {
$data['to'] = $this->prepare_list_of_to_emails( $recipients['to'] );
}
if ( ! empty( $recipients['cc'] ) ) {
$data['cc'] = $this->prepare_list_of_emails( $recipients['cc'] );
}
if ( ! empty( $recipients['bcc'] ) ) {
$data['bcc'] = $this->prepare_list_of_emails( $recipients['bcc'] );
}
$this->set_body_personalizations( $data );
}
/**
* Set the email content.
* Pepipost API only supports HTML emails, so we have to replace new lines in plain text emails with <br>.
*
* @since 1.8.0
* @since 2.2.0 Change the way the content is prepared (API v5 changes).
*
* @param array|string $content Email content.
*/
public function set_content( $content ) {
if ( empty( $content ) ) {
return;
}
$html = '';
if ( ! is_array( $content ) ) {
$html = $content;
if ( $this->phpmailer->ContentType === 'text/plain' ) {
$html = nl2br( $html );
}
} else {
if ( ! empty( $content['html'] ) ) {
$html = $content['html'];
} elseif ( ! empty( $content['text'] ) ) {
$html = nl2br( $content['text'] );
}
}
$this->set_body_param(
[
'content' => [
[
'type' => 'html',
'value' => $html,
],
],
]
);
}
/**
* Redefine the way custom headers are processed for this mailer - they should be in body (personalizations).
*
* @since 1.8.0
* @since 2.2.0 Change the way the headers are processed (API v5 changes).
*
* @param array $headers The email headers to be applied.
*/
public function set_headers( $headers ) {
$valid_headers = [];
foreach ( $headers as $header ) {
$name = isset( $header[0] ) ? $header[0] : false;
$value = isset( $header[1] ) ? $header[1] : false;
$valid_headers[ $name ] = WP::sanitize_value( $value );
}
// Add custom PHPMailer-specific header.
$valid_headers['X-Mailer'] = WP::sanitize_value( 'WPMailSMTP/Mailer/' . $this->mailer . ' ' . WPMS_PLUGIN_VER );
if ( ! empty( $valid_headers ) ) {
$this->set_body_personalizations( [ 'headers' => $valid_headers ] );
}
}
/**
* Pepipost API accepts an array of files content in body, so we will include all files and send.
* Doesn't handle exceeding the limits etc, as this will be reported by the API response.
*
* @since 1.8.0
* @since 2.2.0 Change the way the attachments are processed (API v5 changes).
*
* @param array $attachments The list of attachments data.
*/
public function set_attachments( $attachments ) {
if ( empty( $attachments ) ) {
return;
}
$data = $this->prepare_attachments( $attachments );
if ( ! empty( $data ) ) {
$this->set_body_param(
[
'attachments' => $data,
]
);
}
}
/**
* Prepare the attachments data for Pepipost API.
*
* @since 2.2.0
*
* @param array $attachments Array of attachments.
*
* @return array
*/
protected function prepare_attachments( $attachments ) {
$data = [];
foreach ( $attachments as $attachment ) {
$file = false;
/*
* We are not using WP_Filesystem API as we can't reliably work with it.
* It is not always available, same as credentials for FTP.
*/
try {
if ( is_file( $attachment[0] ) && is_readable( $attachment[0] ) ) {
$file = file_get_contents( $attachment[0] );
}
} catch ( \Exception $e ) {
$file = false;
}
if ( $file === false ) {
continue;
}
$data[] = [
'content' => base64_encode( $file ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
'name' => $attachment[2],
];
}
return $data;
}
/**
* Set the reply-to property of the email.
* Pepipost API only supports one reply_to email, so we take the first one and discard the rest.
*
* @since 1.8.0
* @since 2.2.0 Change the way the reply_to is processed (API v5 changes).
*
* @param array $reply_to Name/email for reply-to feature.
*/
public function set_reply_to( $reply_to ) {
if ( empty( $reply_to ) ) {
return;
}
$email_array = array_shift( $reply_to );
if ( empty( $email_array[0] ) ) {
return;
}
$email = $email_array[0];
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
return;
}
if ( ! empty( $email ) ) {
$this->set_body_param(
[
'reply_to' => $email,
]
);
}
}
/**
* Pepipost API doesn't support sender or return_path params.
* So we do nothing.
*
* @since 1.8.0
*
* @param string $from_email The from email address.
*/
public function set_return_path( $from_email ) {}
/**
* Get a Pepipost-specific response with a helpful error.
*
* @see https://developers.pepipost.com/email-api/email-api/sendemail#responses
*
* @since 1.8.0
* @since 2.2.0 Change the way the response error message is processed (API v5 changes).
*
* @return string
*/
public function get_response_error() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.MaxExceeded
$body = (array) wp_remote_retrieve_body( $this->response );
$error = ! empty( $body['error'] ) ? $body['error'] : '';
$info = ! empty( $body['info'] ) ? $body['info'] : '';
$message = '';
if ( ! empty( $this->error_message ) ) {
$message = $this->error_message;
} elseif ( is_string( $error ) ) {
$message = $error . ( ( ! empty( $info ) ) ? ' - ' . $info : '' );
} elseif ( is_array( $error ) ) {
$message = '';
foreach ( $error as $item ) {
$message .= sprintf(
'%1$s (%2$s - %3$s)',
! empty( $item->description ) ? $item->description : esc_html__( 'General error', 'wp-mail-smtp' ),
! empty( $item->message ) ? $item->message : esc_html__( 'Error', 'wp-mail-smtp' ),
! empty( $item->field ) ? $item->field : ''
) . PHP_EOL;
}
}
return $message;
}
/**
* Get mailer debug information, that is helpful during support.
*
* @since 1.8.0
*
* @return string
*/
public function get_debug_info() {
$sendgrid_text[] = '<strong>Api Key:</strong> ' . ( $this->is_mailer_complete() ? 'Yes' : 'No' );
return implode( '<br>', $sendgrid_text );
}
/**
* Whether the mailer has all its settings correctly set up and saved.
*
* @since 1.8.0
*
* @return bool
*/
public function is_mailer_complete() {
$options = $this->options->get_group( $this->mailer );
// API key is the only required option.
if ( ! empty( $options['api_key'] ) ) {
return true;
}
return false;
}
/**
* A special set method for Pepipost API "personalizations" attribute.
* We are sending one email at a time, so we should set just the first
* personalization item.
*
* Mainly used in set_headers and set_recipients.
*
* @see https://developers.pepipost.com/email-api/email-api/sendemail
*
* @since 2.2.0
*
* @param array $data The personalizations array of data (array of arrays).
*/
private function set_body_personalizations( $data ) {
if ( empty( $data ) ) {
return;
}
if ( ! empty( $this->body['personalizations'][0] ) ) {
$this->body['personalizations'][0] = PluginOptions::array_merge_recursive(
$this->body['personalizations'][0],
$data
);
} else {
$this->set_body_param(
[
'personalizations' => [
$data,
],
]
);
}
}
/**
* Prepare list of emails by filtering valid emails first.
*
* @since 2.2.0
*
* @param array $items A 2D array of email and name pair items (0 = email, 1 = name).
*
* @return array 2D array with 'email' keys.
*/
private function prepare_list_of_emails( $items ) {
$valid_emails = array_filter(
array_column( $items, 0 ),
function ( $email ) {
return filter_var( $email, FILTER_VALIDATE_EMAIL );
}
);
return array_map(
function( $email ) {
return [ 'email' => $email ];
},
$valid_emails
);
}
/**
* Prepare list of TO emails by filtering valid emails first
* and returning array of arrays (email, name).
*
* @since 2.2.0
*
* @param array $items A 2D array of email and name pair items (0 = email, 1 = name).
*
* @return array 2D array with 'email' and optional 'name' attributes.
*/
private function prepare_list_of_to_emails( $items ) {
$data = [];
foreach ( $items as $item ) {
$email = filter_var( $item[0], FILTER_VALIDATE_EMAIL );
if ( empty( $email ) ) {
continue;
}
$pair['email'] = $email;
if ( ! empty( $item[1] ) ) {
$pair['name'] = $item[1];
}
$data[] = $pair;
}
return $data;
}
}

View File

@@ -0,0 +1,127 @@
<?php
namespace WPMailSMTP\Providers\PepipostAPI;
use WPMailSMTP\Providers\OptionsAbstract;
use WPMailSMTP\Options as PluginOptions;
/**
* Class Options.
*
* @since 1.8.0
*/
class Options extends OptionsAbstract {
/**
* Mailer slug.
*
* @since 1.8.0
*/
const SLUG = 'pepipostapi';
/**
* Options constructor.
*
* @since 1.8.0
* @since 2.3.0 Added 'supports' parameter.
*/
public function __construct() {
$description = sprintf(
wp_kses( /* translators: %1$s - URL to pepipost.com site. */
__( '<a href="%1$s" target="_blank" rel="noopener noreferrer">Pepipost</a> is a transactional email service. Every month Pepipost delivers over 8 billion emails from 20,000+ customers. Their mission is to reliably send emails in the most efficient way and at the most disruptive pricing ever. Pepipost provides users 30,000 free emails the first 30 days.', 'wp-mail-smtp' ) .
'<br><br>' .
/* translators: %1$s - URL to wpmailsmtp.com doc. */
__( 'Read our <a href="%2$s" target="_blank" rel="noopener noreferrer">Pepipost documentation</a> to learn how to configure Pepipost and improve your email deliverability.', 'wp-mail-smtp' ),
array(
'br' => true,
'a' => array(
'href' => true,
'rel' => true,
'target' => true,
),
)
),
'https://wpmailsmtp.com/go/pepipost/',
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-set-up-the-pepipost-mailer-in-wp-mail-smtp/', 'Pepipost documentation' ) )
);
$api_key = PluginOptions::init()->get( self::SLUG, 'api_key' );
if ( empty( $api_key ) ) {
$description .= sprintf(
'</p><p class="buttonned"><a href="%1$s" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-blueish">%2$s</a></p>',
'https://wpmailsmtp.com/go/pepipost/',
esc_html__( 'Get Started with Pepipost', 'wp-mail-smtp' )
);
}
parent::__construct(
[
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/pepipost.png',
'slug' => self::SLUG,
'title' => esc_html__( 'Pepipost', 'wp-mail-smtp' ),
'description' => $description,
'php' => '5.3',
'supports' => [
'from_email' => true,
'from_name' => true,
'return_path' => false,
'from_email_force' => true,
'from_name_force' => true,
],
]
);
}
/**
* Output the mailer provider options.
*
* @since 1.8.0
*/
public function display_options() {
// Do not display options if PHP version is not correct.
if ( ! $this->is_php_correct() ) {
$this->display_php_warning();
return;
}
?>
<!-- API Key -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_id"
class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'API Key', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php if ( $this->connection_options->is_const_defined( $this->get_slug(), 'api_key' ) ) : ?>
<input type="text" disabled value="****************************************"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php $this->display_const_set_message( 'WPMS_PEPIPOST_API_KEY' ); ?>
<?php else : ?>
<input type="password" spellcheck="false"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'api_key' ) ); ?>"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php endif; ?>
<p class="desc">
<?php
printf( /* translators: %s - link to get an API Key. */
esc_html__( 'Follow this link to get an API Key: %s.', 'wp-mail-smtp' ),
'<a href="https://app.pepipost.com/app/settings/integration" target="_blank" rel="noopener noreferrer">' .
esc_html__( 'Get the API Key', 'wp-mail-smtp' ) .
'</a>'
);
?>
</p>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,469 @@
<?php
namespace WPMailSMTP\Providers\Postmark;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Helpers\Helpers;
use WPMailSMTP\WP;
use WPMailSMTP\MailCatcherInterface;
use WPMailSMTP\Providers\MailerAbstract;
/**
* Class Mailer.
*
* @since 3.1.0
*/
class Mailer extends MailerAbstract {
/**
* URL to make an API request to.
*
* @since 3.1.0
*
* @var string
*/
protected $url = 'https://api.postmarkapp.com/email';
/**
* Mailer constructor.
*
* @since 3.1.0
*
* @param MailCatcherInterface $phpmailer The MailCatcher object.
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $phpmailer, $connection = null ) {
// We want to prefill everything from MailCatcher class, which extends PHPMailer.
parent::__construct( $phpmailer, $connection );
// Set mailer specific headers.
$this->set_header( 'X-Postmark-Server-Token', $this->connection_options->get( $this->mailer, 'server_api_token' ) );
$this->set_header( 'Accept', 'application/json' );
$this->set_header( 'Content-Type', 'application/json' );
// Set mailer specific body parameters.
$message_stream = $this->get_message_stream();
if ( ! empty( $message_stream ) ) {
$this->set_body_param(
[
'MessageStream' => $message_stream,
]
);
}
}
/**
* Redefine the way custom headers are processed for this mailer - they should be in body.
*
* @since 3.1.0
*
* @param array $headers Headers array.
*/
public function set_headers( $headers ) {
foreach ( $headers as $header ) {
$name = isset( $header[0] ) ? $header[0] : false;
$value = isset( $header[1] ) ? $header[1] : false;
$this->set_body_header( $name, $value );
}
// Add custom PHPMailer-specific header.
$this->set_body_header( 'X-Mailer', 'WPMailSMTP/Mailer/' . $this->mailer . ' ' . WPMS_PLUGIN_VER );
$this->set_body_header( 'Message-ID', $this->phpmailer->getLastMessageID() );
}
/**
* This mailer supports email-related custom headers inside a body of the message.
*
* @since 3.1.0
*
* @param string $name Header name.
* @param string $value Header value.
*/
public function set_body_header( $name, $value ) {
$name = sanitize_text_field( $name );
if ( empty( $name ) ) {
return;
}
$headers = isset( $this->body['Headers'] ) ? (array) $this->body['Headers'] : [];
if ( $name !== 'Message-ID' ) {
$value = WP::sanitize_value( $value );
}
// Prevent duplicates.
$key = array_search( $name, array_column( $headers, 'Name' ), true );
if ( $key !== false ) {
unset( $headers[ $key ] );
}
$headers[] = [
'Name' => $name,
'Value' => $value,
];
$this->body['Headers'] = array_values( $headers );
}
/**
* Set the From information for an email.
*
* @since 3.1.0
*
* @param string $email The sender email address.
* @param string $name The sender name.
*/
public function set_from( $email, $name ) {
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
return;
}
$this->set_body_param(
[
'From' => $this->phpmailer->addrFormat( [ $email, $name ] ),
]
);
}
/**
* Set email recipients: to, cc, bcc.
*
* @since 3.1.0
*
* @param array $recipients Email recipients.
*/
public function set_recipients( $recipients ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
if ( empty( $recipients ) ) {
return;
}
$default = [ 'to', 'cc', 'bcc' ];
foreach ( $recipients as $type => $emails ) {
if (
! in_array( $type, $default, true ) ||
empty( $emails ) ||
! is_array( $emails )
) {
continue;
}
$data = [];
foreach ( $emails as $email ) {
$addr = isset( $email[0] ) ? $email[0] : false;
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
continue;
}
$data[] = $this->phpmailer->addrFormat( $email );
}
if ( ! empty( $data ) ) {
$this->set_body_param(
[
ucfirst( $type ) => implode( ',', $data ),
]
);
}
}
}
/**
* Set the Reply To information for an email.
*
* @since 3.1.0
*
* @param array $emails Reply To email addresses.
*/
public function set_reply_to( $emails ) {
if ( empty( $emails ) ) {
return;
}
$data = [];
foreach ( $emails as $email ) {
$addr = isset( $email[0] ) ? $email[0] : false;
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
continue;
}
$data[] = $this->phpmailer->addrFormat( $email );
}
if ( ! empty( $data ) ) {
$this->set_body_param(
[
'ReplyTo' => implode( ',', $data ),
]
);
}
}
/**
* Set email subject.
*
* @since 3.1.0
*
* @param string $subject Email subject.
*/
public function set_subject( $subject ) {
$this->set_body_param(
[
'Subject' => $subject,
]
);
}
/**
* Set email content.
*
* @since 3.1.0
*
* @param string|array $content Email content.
*/
public function set_content( $content ) {
if ( empty( $content ) ) {
return;
}
if ( is_array( $content ) ) {
if ( ! empty( $content['text'] ) ) {
$this->set_body_param(
[
'TextBody' => $content['text'],
]
);
}
if ( ! empty( $content['html'] ) ) {
$this->set_body_param(
[
'HtmlBody' => $content['html'],
]
);
}
} else {
if ( $this->phpmailer->ContentType === 'text/plain' ) {
$this->set_body_param(
[
'TextBody' => $content,
]
);
} else {
$this->set_body_param(
[
'HtmlBody' => $content,
]
);
}
}
}
/**
* Set attachments for an email.
*
* @since 3.1.0
*
* @param array $attachments Attachments array.
*/
public function set_attachments( $attachments ) {
if ( empty( $attachments ) ) {
return;
}
$data = $this->prepare_attachments( $attachments );
if ( ! empty( $data ) ) {
$this->set_body_param(
[
'Attachments' => $data,
]
);
}
}
/**
* Prepare attachments data for Postmark API.
*
* @since 3.1.0
*
* @param array $attachments Array of attachments.
*
* @return array
*/
protected function prepare_attachments( $attachments ) {
$data = [];
foreach ( $attachments as $attachment ) {
$file = $this->get_attachment_file_content( $attachment );
if ( $file === false ) {
continue;
}
$data[] = [
'Name' => $this->get_attachment_file_name( $attachment ),
'Content' => base64_encode( $file ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
'ContentType' => $attachment[4],
];
}
return $data;
}
/**
* Doesn't support this.
* Return path can be configured in Postmark account.
*
* @since 3.1.0
*
* @param string $email Return Path email address.
*/
public function set_return_path( $email ) { }
/**
* Redefine the way email body is returned.
* By default, we are sending an array of data.
* Postmark requires a JSON, so we encode the body.
*
* @since 3.1.0
*/
public function get_body() {
$body = parent::get_body();
return wp_json_encode( $body );
}
/**
* We might need to do something after the email was sent to the API.
* In this method we preprocess the response from the API.
*
* @since 3.1.0
*
* @param mixed $response Response data.
*/
protected function process_response( $response ) {
parent::process_response( $response );
if (
! is_wp_error( $response ) &&
! empty( $this->response['body']->MessageID )
) {
$this->phpmailer->addCustomHeader( 'X-Msg-ID', $this->response['body']->MessageID );
$this->verify_sent_status = true;
}
}
/**
* Get a Postmark-specific response with a helpful error.
*
* @since 3.1.0
*
* @return string
*/
public function get_response_error() {
$error_text[] = $this->error_message;
if ( ! empty( $this->response ) ) {
$body = wp_remote_retrieve_body( $this->response );
// phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
if ( ! empty( $body->Message ) ) {
$message = $body->Message;
$code = ! empty( $body->ErrorCode ) ? $body->ErrorCode : '';
$error_text[] = Helpers::format_error_message( $message, $code );
} else {
$error_text[] = WP::wp_remote_get_response_error_message( $this->response );
}
// phpcs:enable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
}
return implode( WP::EOL, array_map( 'esc_textarea', array_filter( $error_text ) ) );
}
/**
* Get mailer debug information, that is helpful during support.
*
* @since 3.1.0
*
* @return string
*/
public function get_debug_info() {
$options = $this->connection_options->get_group( $this->mailer );
$text[] = '<strong>' . esc_html__( 'Server API Token:', 'wp-mail-smtp' ) . '</strong> ' .
( ! empty( $options['server_api_token'] ) ? 'Yes' : 'No' );
$text[] = '<strong>' . esc_html__( 'Message Stream ID:', 'wp-mail-smtp' ) . '</strong> ' .
( ! empty( $this->get_message_stream() ) ? esc_html( $this->get_message_stream() ) : 'No' );
return implode( '<br>', $text );
}
/**
* Get the Message Stream ID.
*
* @since 3.1.0
*
* @link https://postmarkapp.com/message-streams
*
* @return string
*/
private function get_message_stream() {
$message_stream = $this->connection_options->get( $this->mailer, 'message_stream' );
/**
* Filters Message Stream ID.
*
* @since 3.1.0
*
* @link https://postmarkapp.com/message-streams
*
* @param string $message_stream Message Stream ID.
*/
return apply_filters( 'wp_mail_smtp_providers_postmark_mailer_get_message_stream', $message_stream );
}
/**
* Whether the mailer has all its settings correctly set up and saved.
*
* This mailer is configured when `server_api_token` setting is defined.
*
* @since 3.1.0
*
* @return bool
*/
public function is_mailer_complete() {
$options = $this->connection_options->get_group( $this->mailer );
if ( ! empty( $options['server_api_token'] ) ) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,154 @@
<?php
namespace WPMailSMTP\Providers\Postmark;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Providers\OptionsAbstract;
/**
* Class Options.
*
* @since 3.1.0
*/
class Options extends OptionsAbstract {
/**
* Mailer slug.
*
* @since 3.1.0
*/
const SLUG = 'postmark';
/**
* Options constructor.
*
* @since 3.1.0
*
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $connection = null ) {
$description = sprintf(
wp_kses( /* translators: %1$s - URL to postmarkapp.com site. */
__( '<a href="%1$s" target="_blank" rel="noopener noreferrer">Postmark</a> is a transactional email provider that offers great deliverability and accessible pricing for any business. You can start out with the free trial that allows you to send 100 test emails each month via its secure API.', 'wp-mail-smtp' ) .
'<br><br>' .
/* translators: %2$s - URL to wpmailsmtp.com doc. */
__( 'To get started, read our <a href="%2$s" target="_blank" rel="noopener noreferrer">Postmark documentation</a>.', 'wp-mail-smtp' ),
[
'strong' => true,
'br' => true,
'a' => [
'href' => true,
'rel' => true,
'target' => true,
],
]
),
'https://postmarkapp.com',
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-set-up-the-postmark-mailer-in-wp-mail-smtp/', 'Postmark documentation' ) )
);
parent::__construct(
[
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/postmark.svg',
'slug' => self::SLUG,
'title' => esc_html__( 'Postmark', 'wp-mail-smtp' ),
'php' => '5.6',
'description' => $description,
'supports' => [
'from_email' => true,
'from_name' => true,
'return_path' => false,
'from_email_force' => true,
'from_name_force' => true,
],
'recommended' => false,
],
$connection
);
}
/**
* Output the mailer provider options.
*
* @since 3.1.0
*/
public function display_options() {
// Do not display options if PHP version is not correct.
if ( ! $this->is_php_correct() ) {
$this->display_php_warning();
return;
}
?>
<!-- Server API Token -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-server_api_token" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-server_api_token"><?php esc_html_e( 'Server API Token', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php if ( $this->connection_options->is_const_defined( $this->get_slug(), 'server_api_token' ) ) : ?>
<input type="text" disabled value="****************************************"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-server_api_token"/>
<?php $this->display_const_set_message( 'WPMS_POSTMARK_SERVER_API_TOKEN' ); ?>
<?php else : ?>
<input type="password" spellcheck="false"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][server_api_token]"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'server_api_token' ) ); ?>"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-server_api_token"/>
<?php endif; ?>
<p class="desc">
<?php
printf( /* translators: %s - Server API Token link. */
esc_html__( 'Follow this link to get a Server API Token from Postmark: %s.', 'wp-mail-smtp' ),
'<a href="https://account.postmarkapp.com/api_tokens" target="_blank" rel="noopener noreferrer">' .
esc_html__( 'Get Server API Token', 'wp-mail-smtp' ) .
'</a>'
);
?>
</p>
</div>
</div>
<!-- Message Stream ID -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-message_stream" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-message_stream"><?php esc_html_e( 'Message Stream ID', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][message_stream]" type="text"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'message_stream' ) ); ?>"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'message_stream' ) ? 'disabled' : ''; ?>
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-message_stream" spellcheck="false"/>
<?php
if ( $this->connection_options->is_const_defined( $this->get_slug(), 'message_stream' ) ) {
$this->display_const_set_message( 'WPMS_POSTMARK_MESSAGE_STREAM' );
}
?>
<p class="desc">
<?php
printf(
wp_kses(
/* translators: %s - URL to Postmark documentation on wpmailsmtp.com */
__( 'Message Stream ID is <strong>optional</strong>. By default <strong>outbound</strong> (Default Transactional Stream) will be used. More information can be found in our <a href="%s" target="_blank" rel="noopener noreferrer">Postmark documentation</a>.', 'wp-mail-smtp' ),
[
'strong' => [],
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-set-up-the-postmark-mailer-in-wp-mail-smtp/#message-stream', 'Postmark documentation - message stream' ) )
);
?>
</p>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,32 @@
<?php
namespace WPMailSMTP\Providers\SMTP;
use WPMailSMTP\Providers\MailerAbstract;
/**
* Class Mailer inherits everything from parent abstract class.
* This file is required for a proper work of Loader and \ReflectionClass.
*
* @package WPMailSMTP\Providers\SMTP
*/
class Mailer extends MailerAbstract {
/**
* @inheritdoc
*/
public function is_mailer_complete() {
$options = $this->connection_options->get_group( $this->mailer );
// Host and Port are the only really required options.
if (
! empty( $options['host'] ) &&
! empty( $options['port'] )
) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,48 @@
<?php
namespace WPMailSMTP\Providers\SMTP;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Providers\OptionsAbstract;
/**
* Class SMTP.
*
* @since 1.0.0
*/
class Options extends OptionsAbstract {
/**
* SMTP constructor.
*
* @since 1.0.0
*
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $connection = null ) {
parent::__construct(
[
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/smtp.svg',
'slug' => 'smtp',
'title' => esc_html__( 'Other SMTP', 'wp-mail-smtp' ),
'description' => sprintf(
wp_kses(
/* translators: %s - URL to SMTP documentation. */
__( 'The Other SMTP option lets you send emails through an SMTP server instead of using a provider\'s API. This is easy and convenient, but it\'s less secure than the other mailers. Please note that your provider may not allow you to send a large number of emails. In that case, please use a different mailer.<br><br>To get started, read our <a href="%s" target="_blank" rel="noopener noreferrer">Other SMTP documentation</a>.', 'wp-mail-smtp' ),
[
'br' => [],
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-set-up-the-other-smtp-mailer-in-wp-mail-smtp/', 'Other SMTP documentation' ) )
),
],
$connection
);
}
}

View File

@@ -0,0 +1,478 @@
<?php
namespace WPMailSMTP\Providers\SMTPcom;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Helpers\Helpers;
use WPMailSMTP\MailCatcherInterface;
use WPMailSMTP\Providers\MailerAbstract;
use WPMailSMTP\WP;
/**
* Class Mailer for SMTP.com integration.
*
* @see https://www.smtp.com/smtp-api-documentation/ for the API documentation.
*
* @since 2.0.0
*/
class Mailer extends MailerAbstract {
/**
* Which response code from HTTP provider is considered to be successful?
*
* @since 2.0.0
*
* @var int
*/
protected $email_sent_code = 200;
/**
* URL to make an API request to.
*
* @since 2.0.0
*
* @var string
*/
protected $url = 'https://api.smtp.com/v4/messages';
/**
* Mailer constructor.
*
* @since 2.0.0
*
* @param MailCatcherInterface $phpmailer The MailCatcher object.
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $phpmailer, $connection = null ) {
// We want to prefill everything from MailCatcher class, which extends PHPMailer.
parent::__construct( $phpmailer, $connection );
// Set mailer specific headers.
$this->set_header( 'Authorization', 'Bearer ' . $this->connection_options->get( $this->mailer, 'api_key' ) );
$this->set_header( 'Accept', 'application/json' );
$this->set_header( 'content-type', 'application/json' );
// Set mailer specific body parameters.
$this->set_body_param(
array(
'channel' => $this->connection_options->get( $this->mailer, 'channel' ),
)
);
}
/**
* Redefine the way email body is returned.
* By default we are sending an array of data.
* SMTP.com requires a JSON, so we encode the body.
*
* @since 2.0.0
*/
public function get_body() {
$body = parent::get_body();
return wp_json_encode( $body );
}
/**
* Define the FROM (name and email).
*
* @since 2.0.0
*
* @param string $email From Email address.
* @param string $name From Name.
*/
public function set_from( $email, $name = '' ) {
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
return;
}
$from['address'] = $email;
if ( ! empty( $name ) ) {
$from['name'] = $name;
}
$this->set_body_param(
array(
'originator' => array(
'from' => $from,
),
)
);
}
/**
* Define the CC/BCC/TO (with names and emails).
*
* @since 2.0.0
*
* @param array $recipients
*/
public function set_recipients( $recipients ) {
if ( empty( $recipients ) ) {
return;
}
// Allow only these recipient types.
$allowed_types = array( 'to', 'cc', 'bcc' );
$data = array();
foreach ( $recipients as $type => $emails ) {
if (
! in_array( $type, $allowed_types, true ) ||
empty( $emails ) ||
! is_array( $emails )
) {
continue;
}
$data[ $type ] = array();
// Iterate over all emails for each type.
// There might be multiple cc/to/bcc emails.
foreach ( $emails as $email ) {
$holder = array();
$address = isset( $email[0] ) ? $email[0] : false;
$name = isset( $email[1] ) ? $email[1] : false;
if ( ! filter_var( $address, FILTER_VALIDATE_EMAIL ) ) {
continue;
}
$holder['address'] = $address;
if ( ! empty( $name ) ) {
$holder['name'] = $name;
}
array_push( $data[ $type ], $holder );
}
}
if ( ! empty( $data ) ) {
$this->set_body_param(
array(
'recipients' => $data,
)
);
}
}
/**
* Set the email content.
*
* @since 2.0.0
*
* @param array|string $content String when text/plain, array otherwise.
*/
public function set_content( $content ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
if ( empty( $content ) ) {
return;
}
$parts = [];
if ( is_array( $content ) ) {
$allowed = [ 'text', 'html' ];
foreach ( $content as $type => $body ) {
if (
! in_array( $type, $allowed, true ) ||
empty( $body )
) {
continue;
}
$content_type = 'text/plain';
$content_value = $body;
if ( $type === 'html' ) {
$content_type = 'text/html';
}
$parts[] = [
'type' => $content_type,
'content' => $content_value,
'charset' => $this->phpmailer->CharSet,
];
}
} else {
$content_type = 'text/html';
$content_value = $content;
if ( $this->phpmailer->ContentType === 'text/plain' ) {
$content_type = 'text/plain';
}
$parts[] = [
'type' => $content_type,
'content' => $content_value,
'charset' => $this->phpmailer->CharSet,
];
}
$this->set_body_param(
[
'body' => [
'parts' => $parts,
],
]
);
}
/**
* Redefine the way custom headers are processed for this mailer - they should be in body.
*
* @since 2.0.0
*
* @param array $headers
*/
public function set_headers( $headers ) {
foreach ( $headers as $header ) {
$name = isset( $header[0] ) ? $header[0] : false;
$value = isset( $header[1] ) ? $header[1] : false;
$this->set_body_header( $name, $value );
}
// Add custom PHPMailer-specific header.
$this->set_body_header( 'X-Mailer', 'WPMailSMTP/Mailer/' . $this->mailer . ' ' . WPMS_PLUGIN_VER );
}
/**
* This mailer supports email-related custom headers inside a body of the message.
*
* @since 2.0.0
*
* @param string $name
* @param string $value
*/
public function set_body_header( $name, $value ) {
$name = sanitize_text_field( $name );
if ( empty( $name ) ) {
return;
}
$headers = isset( $this->body['custom_headers'] ) ? (array) $this->body['custom_headers'] : array();
$headers[ $name ] = WP::sanitize_value( $value );
$this->set_body_param(
array(
'custom_headers' => $headers,
)
);
}
/**
* SMTP.com accepts an array of attachments in body.attachments section of the JSON payload.
*
* @since 2.0.0
*
* @param array $attachments The array of attachments data.
*/
public function set_attachments( $attachments ) {
if ( empty( $attachments ) ) {
return;
}
$data = [];
foreach ( $attachments as $attachment ) {
$file = $this->get_attachment_file_content( $attachment );
if ( $file === false ) {
continue;
}
$filetype = str_replace( ';', '', trim( $attachment[4] ) );
$data[] = [
'content' => chunk_split( base64_encode( $file ) ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
'type' => $filetype,
'encoding' => 'base64',
'filename' => $this->get_attachment_file_name( $attachment ),
'disposition' => in_array( $attachment[6], [ 'inline', 'attachment' ], true ) ? $attachment[6] : 'attachment', // either inline or attachment.
'cid' => empty( $attachment[7] ) ? '' : trim( (string) $attachment[7] ),
];
}
if ( ! empty( $data ) ) {
$this->set_body_param(
[
'body' => [
'attachments' => $data,
],
]
);
}
}
/**
* Set Reply-To part of the message.
*
* @since 2.0.0
*
* @param array $reply_to
*/
public function set_reply_to( $reply_to ) {
if ( empty( $reply_to ) ) {
return;
}
$data = array();
foreach ( $reply_to as $key => $emails ) {
if (
empty( $emails ) ||
! is_array( $emails )
) {
continue;
}
$address = isset( $emails[0] ) ? $emails[0] : false;
$name = isset( $emails[1] ) ? $emails[1] : false;
if ( ! filter_var( $address, FILTER_VALIDATE_EMAIL ) ) {
continue;
}
$data['address'] = $address;
if ( ! empty( $name ) ) {
$data['name'] = $name;
}
// Let the first valid email from the passed $reply_to serve as the reply_to parameter in STMP.com API.
// Only one email address and name is allowed in the `reply_to` parameter in the SMTP.com API payload.
break;
}
if ( ! empty( $data ) ) {
$this->set_body_param(
array(
'originator' => array(
'reply_to' => $data,
),
)
);
}
}
/**
* SMTP.com doesn't support return_path params.
* So we do nothing.
*
* @since 2.0.0
*
* @param string $from_email
*/
public function set_return_path( $from_email ) {}
/**
* We might need to do something after the email was sent to the API.
* In this method we preprocess the response from the API.
*
* @since 2.5.0
*
* @param mixed $response Response data.
*/
protected function process_response( $response ) {
parent::process_response( $response );
if (
! is_wp_error( $response ) &&
! empty( $this->response['body']->data->message )
) {
preg_match( '/msg_id: (.*)/', $this->response['body']->data->message, $output );
if ( ! empty( $output[1] ) ) {
$this->phpmailer->addCustomHeader( 'X-Msg-ID', $output[1] );
$this->verify_sent_status = true;
}
}
}
/**
* Get a SMTP.com-specific response with a helpful error.
*
* SMTP.com API error response (non 200 error code responses) is:
* {
* "status": "fail",
* "data": {
* "error_key": "short error message",
* }
* }
*
* It's good to combine the error_key and the message together for the best error explanation.
*
* @since 2.0.0
*
* @return string
*/
public function get_response_error() {
$error_text[] = $this->error_message;
if ( ! empty( $this->response ) ) {
$body = wp_remote_retrieve_body( $this->response );
if ( ! empty( $body->data ) ) {
foreach ( (array) $body->data as $error_key => $error_message ) {
$error_text[] = Helpers::format_error_message( $error_message, $error_key );
}
} else {
$error_text[] = WP::wp_remote_get_response_error_message( $this->response );
}
}
return implode( WP::EOL, array_map( 'esc_textarea', array_filter( $error_text ) ) );
}
/**
* Get mailer debug information, that is helpful during support.
*
* @since 2.0.0
*
* @return string
*/
public function get_debug_info() {
$options = $this->connection_options->get_group( $this->mailer );
$text[] = '<strong>' . esc_html__( 'Api Key:', 'wp-mail-smtp' ) . '</strong> ' .
( ! empty( $options['api_key'] ) ? 'Yes' : 'No' );
$text[] = '<strong>' . esc_html__( 'Channel:', 'wp-mail-smtp' ) . '</strong> ' .
( ! empty( $options['channel'] ) ? 'Yes' : 'No' );
return implode( '<br>', $text );
}
/**
* Whether the mailer has all its settings correctly set up and saved.
*
* This mailer is configured when `api_key` and `channel` settings are defined.
*
* @since 2.0.0
*
* @return bool
*/
public function is_mailer_complete() {
$options = $this->connection_options->get_group( $this->mailer );
if ( ! empty( $options['api_key'] ) && ! empty( $options['channel'] ) ) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,165 @@
<?php
namespace WPMailSMTP\Providers\SMTPcom;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Providers\OptionsAbstract;
/**
* Class Options.
*
* @since 2.0.0
*/
class Options extends OptionsAbstract {
/**
* Mailer slug.
*
* @since 2.0.0
*/
const SLUG = 'smtpcom';
/**
* Options constructor.
*
* @since 2.0.0
* @since 2.3.0 Added supports parameter.
*
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $connection = null ) {
if ( is_null( $connection ) ) {
$connection = wp_mail_smtp()->get_connections_manager()->get_primary_connection();
}
$allowed_kses_html = array(
'strong' => array(),
'br' => array(),
'a' => array(
'href' => array(),
'rel' => array(),
'target' => array(),
),
);
$description = sprintf(
wp_kses( /* translators: %s - URL to smtp.com site. */
__( '<strong><a href="%s" target="_blank" rel="noopener noreferrer">SMTP.com</a> is one of our recommended mailers.</strong> It\'s a transactional email provider that\'s currently used by 100,000+ businesses. SMTP.com is an established brand that\'s been offering email services for more than 20 years.<br><br>SMTP.com offers a free 30-day trial that allows you to send up to 50,000 emails.', 'wp-mail-smtp' ),
$allowed_kses_html
),
'https://wpmailsmtp.com/go/smtp/'
);
$description .= '<br><br>';
$description .= sprintf(
wp_kses( /* translators: %s - URL to wpmailsmtp.com doc page for stmp.com. */
__( 'To get started, read our <a href="%s" target="_blank" rel="noopener noreferrer">SMTP.com documentation</a>.', 'wp-mail-smtp' ),
$allowed_kses_html
),
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-set-up-the-smtp-com-mailer-in-wp-mail-smtp/', 'SMTP.com documentation' ) )
);
$mailer_options = $connection->get_options()->get_group( self::SLUG );
if ( empty( $mailer_options['api_key'] ) && empty( $mailer_options['channel'] ) ) {
$description .= sprintf(
'</p><p class="buttonned"><a href="%1$s" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-blueish">%2$s</a></p>',
'https://wpmailsmtp.com/go/smtp/',
esc_html__( 'Get Started with SMTP.com', 'wp-mail-smtp' )
);
}
$description .= '<p class="wp-mail-smtp-tooltip">' .
esc_html__( 'Transparency and Disclosure', 'wp-mail-smtp' ) .
'<span class="wp-mail-smtp-tooltip-text">' .
esc_html__( 'We believe in full transparency. The SMTP.com links above are tracking links as part of our partnership with SMTP (j2 Global). We can recommend just about any SMTP service, but we only recommend products that we believe will add value to our users.', 'wp-mail-smtp' ) .
'</span></p>';
parent::__construct(
[
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/smtp-com.svg',
'slug' => self::SLUG,
'title' => esc_html__( 'SMTP.com', 'wp-mail-smtp' ),
'description' => $description,
'recommended' => true,
'supports' => [
'from_email' => true,
'from_name' => true,
'return_path' => false,
'from_email_force' => true,
'from_name_force' => true,
],
],
$connection
);
}
/**
* @inheritdoc
*/
public function display_options() {
?>
<!-- API Key -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'API Key', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php if ( $this->connection_options->is_const_defined( $this->get_slug(), 'api_key' ) ) : ?>
<input type="text" disabled value="****************************************"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php $this->display_const_set_message( 'WPMS_SMTPCOM_API_KEY' ); ?>
<?php else : ?>
<input type="password" spellcheck="false"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'api_key' ) ); ?>"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php endif; ?>
<p class="desc">
<?php
printf( /* translators: %s - API key link. */
esc_html__( 'Follow this link to get an API Key from SMTP.com: %s.', 'wp-mail-smtp' ),
'<a href="https://my.smtp.com/settings/api" target="_blank" rel="noopener noreferrer">' .
esc_html__( 'Get API Key', 'wp-mail-smtp' ) .
'</a>'
);
?>
</p>
</div>
</div>
<!-- Channel/Sender -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-channel" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-channel"><?php esc_html_e( 'Sender Name', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][channel]" type="text"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'channel' ) ); ?>"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'channel' ) ? 'disabled' : ''; ?>
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-channel" spellcheck="false"
/>
<?php
if ( $this->connection_options->is_const_defined( $this->get_slug(), 'channel' ) ) {
$this->display_const_set_message( 'WPMS_SMTPCOM_CHANNEL' );
}
?>
<p class="desc">
<?php
printf( /* translators: %s - Channel/Sender Name link for smtp.com documentation. */
esc_html__( 'Follow this link to get a Sender Name from SMTP.com: %s.', 'wp-mail-smtp' ),
'<a href="https://my.smtp.com/senders/" target="_blank" rel="noopener noreferrer">' .
esc_html__( 'Get Sender Name', 'wp-mail-smtp' ) .
'</a>'
);
?>
</p>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,398 @@
<?php
namespace WPMailSMTP\Providers\Sendgrid;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Helpers\Helpers;
use WPMailSMTP\MailCatcherInterface;
use WPMailSMTP\Providers\MailerAbstract;
use WPMailSMTP\WP;
/**
* Class Mailer.
*
* @since 1.0.0
*/
class Mailer extends MailerAbstract {
/**
* Which response code from HTTP provider is considered to be successful?
*
* @since 1.0.0
*
* @var int
*/
protected $email_sent_code = 202;
/**
* URL to make an API request to.
*
* @since 1.0.0
*
* @var string
*/
protected $url = 'https://api.sendgrid.com/v3/mail/send';
/**
* Mailer constructor.
*
* @since 1.0.0
*
* @param MailCatcherInterface $phpmailer The MailCatcher object.
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $phpmailer, $connection = null ) {
// We want to prefill everything from MailCatcher class, which extends PHPMailer.
parent::__construct( $phpmailer, $connection );
$this->set_header( 'Authorization', 'Bearer ' . $this->connection_options->get( $this->mailer, 'api_key' ) );
$this->set_header( 'content-type', 'application/json' );
}
/**
* Redefine the way email body is returned.
* By default we are sending an array of data.
* SendGrid requires a JSON, so we encode the body.
*
* @since 1.0.0
*/
public function get_body() {
$body = parent::get_body();
return wp_json_encode( $body );
}
/**
* @inheritdoc
*/
public function set_from( $email, $name = '' ) {
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
return;
}
$from['email'] = $email;
if ( ! empty( $name ) ) {
$from['name'] = $name;
}
$this->set_body_param(
array(
'from' => $from,
)
);
}
/**
* @inheritdoc
*/
public function set_recipients( $recipients ) {
if ( empty( $recipients ) ) {
return;
}
// Allow for now only these recipient types.
$default = array( 'to', 'cc', 'bcc' );
$data = array();
foreach ( $recipients as $type => $emails ) {
if (
! in_array( $type, $default, true ) ||
empty( $emails ) ||
! is_array( $emails )
) {
continue;
}
$data[ $type ] = array();
// Iterate over all emails for each type.
// There might be multiple cc/to/bcc emails.
foreach ( $emails as $email ) {
$holder = array();
$addr = isset( $email[0] ) ? $email[0] : false;
$name = isset( $email[1] ) ? $email[1] : false;
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
continue;
}
$holder['email'] = $addr;
if ( ! empty( $name ) ) {
$holder['name'] = $name;
}
array_push( $data[ $type ], $holder );
}
}
if ( ! empty( $data ) ) {
$this->set_body_param(
array(
'personalizations' => array( $data ),
)
);
}
}
/**
* @inheritdoc
*/
public function set_content( $content ) {
if ( empty( $content ) ) {
return;
}
if ( is_array( $content ) ) {
$default = array( 'text', 'html' );
$data = array();
foreach ( $content as $type => $body ) {
if (
! in_array( $type, $default, true ) ||
empty( $body )
) {
continue;
}
$content_type = 'text/plain';
$content_value = $body;
if ( $type === 'html' ) {
$content_type = 'text/html';
}
$data[] = array(
'type' => $content_type,
'value' => $content_value,
);
}
$this->set_body_param(
array(
'content' => $data,
)
);
} else {
$data['type'] = 'text/html';
$data['value'] = $content;
if ( $this->phpmailer->ContentType === 'text/plain' ) {
$data['type'] = 'text/plain';
}
$this->set_body_param(
array(
'content' => array( $data ),
)
);
}
}
/**
* Redefine the way custom headers are processed for this mailer - they should be in body.
*
* @since 1.5.0
*
* @param array $headers
*/
public function set_headers( $headers ) {
foreach ( $headers as $header ) {
$name = isset( $header[0] ) ? $header[0] : false;
$value = isset( $header[1] ) ? $header[1] : false;
$this->set_body_header( $name, $value );
}
// Add custom PHPMailer-specific header.
$this->set_body_header( 'X-Mailer', 'WPMailSMTP/Mailer/' . $this->mailer . ' ' . WPMS_PLUGIN_VER );
}
/**
* This mailer supports email-related custom headers inside a body of the message.
*
* @since 1.5.0
*
* @param string $name
* @param string $value
*/
public function set_body_header( $name, $value ) {
$name = sanitize_text_field( $name );
if ( empty( $name ) ) {
return;
}
$headers = isset( $this->body['headers'] ) ? (array) $this->body['headers'] : array();
$headers[ $name ] = WP::sanitize_value( $value );
$this->set_body_param(
array(
'headers' => $headers,
)
);
}
/**
* SendGrid accepts an array of files content in body, so we will include all files and send.
* Doesn't handle exceeding the limits etc, as this is done and reported by SendGrid API.
*
* @since 1.0.0
*
* @param array $attachments The array of attachments data.
*/
public function set_attachments( $attachments ) {
if ( empty( $attachments ) ) {
return;
}
$data = [];
foreach ( $attachments as $attachment ) {
$file = $this->get_attachment_file_content( $attachment );
if ( $file === false ) {
continue;
}
$filetype = str_replace( ';', '', trim( $attachment[4] ) );
$data[] = [
'content' => base64_encode( $file ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
'type' => $filetype, // string, no ;, no CRLF.
'filename' => $this->get_attachment_file_name( $attachment ), // required string, no CRLF.
'disposition' => in_array( $attachment[6], [ 'inline', 'attachment' ], true ) ? $attachment[6] : 'attachment', // either inline or attachment.
'content_id' => empty( $attachment[7] ) ? '' : trim( (string) $attachment[7] ), // string, no CRLF.
];
}
if ( ! empty( $data ) ) {
$this->set_body_param(
[
'attachments' => $data,
]
);
}
}
/**
* @inheritdoc
*/
public function set_reply_to( $reply_to ) {
if ( empty( $reply_to ) ) {
return;
}
$data = array();
foreach ( $reply_to as $key => $emails ) {
if (
empty( $emails ) ||
! is_array( $emails )
) {
continue;
}
$addr = isset( $emails[0] ) ? $emails[0] : false;
$name = isset( $emails[1] ) ? $emails[1] : false;
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
continue;
}
$data['email'] = $addr;
if ( ! empty( $name ) ) {
$data['name'] = $name;
}
}
if ( ! empty( $data ) ) {
$this->set_body_param(
array(
'reply_to' => $data,
)
);
}
}
/**
* SendGrid doesn't support sender or return_path params.
* So we do nothing.
*
* @since 1.0.0
*
* @param string $from_email
*/
public function set_return_path( $from_email ) {}
/**
* Get a SendGrid-specific response with a helpful error.
*
* @since 1.2.0
*
* @return string
*/
public function get_response_error() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh, Generic.Metrics.NestingLevel.MaxExceeded
$error_text[] = $this->error_message;
if ( ! empty( $this->response ) ) {
$body = wp_remote_retrieve_body( $this->response );
if ( ! empty( $body->errors ) && is_array( $body->errors ) ) {
foreach ( $body->errors as $error ) {
if ( ! empty( $error->message ) ) {
$message = $error->message;
$code = ! empty( $error->field ) ? $error->field : '';
$description = ! empty( $error->help ) ? $error->help : '';
$error_text[] = Helpers::format_error_message( $message, $code, $description );
}
}
} else {
$error_text[] = WP::wp_remote_get_response_error_message( $this->response );
}
}
return implode( WP::EOL, array_map( 'esc_textarea', array_filter( $error_text ) ) );
}
/**
* Get mailer debug information, that is helpful during support.
*
* @since 1.2.0
*
* @return string
*/
public function get_debug_info() {
$sendgrid_text[] = '<strong>Api Key:</strong> ' . ( $this->is_mailer_complete() ? 'Yes' : 'No' );
return implode( '<br>', $sendgrid_text );
}
/**
* @inheritdoc
*/
public function is_mailer_complete() {
$options = $this->connection_options->get_group( $this->mailer );
// API key is the only required option.
if ( ! empty( $options['api_key'] ) ) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,139 @@
<?php
namespace WPMailSMTP\Providers\Sendgrid;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Providers\OptionsAbstract;
/**
* Class Option.
*
* @since 1.0.0
*/
class Options extends OptionsAbstract {
/**
* Options constructor.
*
* @since 1.0.0
* @since 2.3.0 Added supports parameter.
*
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $connection = null ) {
parent::__construct(
[
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/sendgrid.svg',
'slug' => 'sendgrid',
'title' => esc_html__( 'SendGrid', 'wp-mail-smtp' ),
'description' => sprintf(
wp_kses(
/* translators: %1$s - URL to sendgrid.com; %2$s - URL to Sendgrid documentation on wpmailsmtp.com */
__( '<a href="%1$s" target="_blank" rel="noopener noreferrer">SendGrid</a> is a popular transactional email provider that sends more than 35 billion emails every month. If you\'re just starting out, the free plan allows you to send up to 100 emails each day without entering your credit card details.<br><br>To get started, read our <a href="%2$s" target="_blank" rel="noopener noreferrer">SendGrid documentation</a>.', 'wp-mail-smtp' ),
[
'br' => [],
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
'https://sendgrid.com',
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-set-up-the-sendgrid-mailer-in-wp-mail-smtp/', 'SendGrid documentation' ) )
),
'supports' => [
'from_email' => true,
'from_name' => true,
'return_path' => false,
'from_email_force' => true,
'from_name_force' => true,
],
],
$connection
);
}
/**
* @inheritdoc
*/
public function display_options() {
?>
<!-- API Key -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'API Key', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php if ( $this->connection_options->is_const_defined( $this->get_slug(), 'api_key' ) ) : ?>
<input type="text" disabled value="****************************************"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php $this->display_const_set_message( 'WPMS_SENDGRID_API_KEY' ); ?>
<?php else : ?>
<input type="password" spellcheck="false"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'api_key' ) ); ?>"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php endif; ?>
<p class="desc">
<?php
printf(
/* translators: %s - API key link. */
esc_html__( 'Follow this link to get an API Key from SendGrid: %s.', 'wp-mail-smtp' ),
'<a href="https://app.sendgrid.com/settings/api_keys" target="_blank" rel="noopener noreferrer">' .
esc_html__( 'Create API Key', 'wp-mail-smtp' ) .
'</a>'
);
?>
<br/>
<?php
printf(
/* translators: %s - SendGrid access level. */
esc_html__( 'To send emails you will need only a %s access level for this API key.', 'wp-mail-smtp' ),
'<code>Mail Send</code>'
);
?>
</p>
</div>
</div>
<!-- Sending Domain -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-domain" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-domain"><?php esc_html_e( 'Sending Domain', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][domain]" type="text"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'domain' ) ); ?>"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'domain' ) ? 'disabled' : ''; ?>
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-domain" spellcheck="false"
/>
<p class="desc">
<?php
printf(
wp_kses(
/* translators: %s - URL to SendGrid documentation on wpmailsmtp.com */
__( 'Please input the sending domain/subdomain you configured in your SendGrid dashboard. More information can be found in our <a href="%s" target="_blank" rel="noopener noreferrer">SendGrid documentation</a>.', 'wp-mail-smtp' ),
[
'br' => [],
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-set-up-the-sendgrid-mailer-in-wp-mail-smtp/#setup', 'SendGrid documentation - setup' ) )
);
?>
</p>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,115 @@
<?php
namespace WPMailSMTP\Providers\Sendinblue;
use WPMailSMTP\ConnectionInterface;
/**
* Class Api is a wrapper for Sendinblue library with handy methods.
*
* @since 1.6.0
*/
class Api {
/**
* The Connection object.
*
* @since 3.7.0
*
* @var ConnectionInterface
*/
private $connection;
/**
* Contains mailer options, constants + DB values.
*
* @since 1.6.0
*
* @var array
*/
private $options;
/**
* API constructor that inits defaults and retrieves options.
*
* @since 1.6.0
*
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $connection = null ) {
if ( ! is_null( $connection ) ) {
$this->connection = $connection;
} else {
$this->connection = wp_mail_smtp()->get_connections_manager()->get_primary_connection();
}
$this->options = $this->connection->get_options()->get_group( Options::SLUG );
}
/**
* Configure API key authorization: api-key.
*
* @since 1.6.0
* @deprecated 3.9.0 We are no longer using the Sendinblue SDK.
*
* @return null
*/
protected function get_api_config() {
_deprecated_function( __METHOD__, '3.9.0' );
return null;
}
/**
* Get the mailer client instance for Account API.
*
* @since 1.6.0
* @deprecated 3.9.0 We are no longer using the Sendinblue SDK.
*/
public function get_account_client() {
_deprecated_function( __METHOD__, '3.9.0' );
return null;
}
/**
* Get the mailer client instance for Sender API.
*
* @since 1.6.0
* @deprecated 3.9.0 We are no longer using the Sendinblue SDK.
*/
public function get_sender_client() {
_deprecated_function( __METHOD__, '3.9.0' );
return null;
}
/**
* Get the mailer client instance for SMTP API.
*
* @since 1.6.0
* @deprecated 3.9.0 We are no longer using the Sendinblue SDK.
*/
public function get_smtp_client() {
_deprecated_function( __METHOD__, '3.9.0' );
return null;
}
/**
* Whether the mailer is ready to be used in API calls.
*
* @since 1.6.0
*
* @return bool
*/
public function is_ready() {
return ! empty( $this->options['api_key'] );
}
}

View File

@@ -0,0 +1,454 @@
<?php
namespace WPMailSMTP\Providers\Sendinblue;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Helpers\Helpers;
use WPMailSMTP\MailCatcherInterface;
use WPMailSMTP\Providers\MailerAbstract;
use WPMailSMTP\WP;
/**
* Class Mailer.
*
* @since 1.6.0
*/
class Mailer extends MailerAbstract {
/**
* Which response code from HTTP provider is considered to be successful?
*
* @since 1.6.0
*
* @var int
*/
protected $email_sent_code = 201;
/**
* Response code for scheduled email.
*
* @since 3.9.0
*
* @var int
*/
protected $email_scheduled_code = 202;
/**
* URL to make an API request to.
*
* @since 1.6.0
* @since 3.9.0 Update to use Brevo API.
*
* @var string
*/
protected $url = 'https://api.brevo.com/v3/smtp/email';
/**
* Mailer constructor.
*
* @since 3.9.0
*
* @param MailCatcherInterface $phpmailer The MailCatcher object.
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $phpmailer, $connection = null ) {
parent::__construct( $phpmailer, $connection );
$this->set_header( 'api-key', $this->connection_options->get( $this->mailer, 'api_key' ) );
$this->set_header( 'Accept', 'application/json' );
$this->set_header( 'content-type', 'application/json' );
}
/**
* The list of allowed attachment files extensions.
*
* @see https://developers.sendinblue.com/reference#sendTransacEmail_attachment__title
*
* @since 1.6.0
*
* @var array
*/
// @formatter:off
protected $allowed_attach_ext = array( 'xlsx', 'xls', 'ods', 'docx', 'docm', 'doc', 'csv', 'pdf', 'txt', 'gif', 'jpg', 'jpeg', 'png', 'tif', 'tiff', 'rtf', 'bmp', 'cgm', 'css', 'shtml', 'html', 'htm', 'zip', 'xml', 'ppt', 'pptx', 'tar', 'ez', 'ics', 'mobi', 'msg', 'pub', 'eps', 'odt', 'mp3', 'm4a', 'm4v', 'wma', 'ogg', 'flac', 'wav', 'aif', 'aifc', 'aiff', 'mp4', 'mov', 'avi', 'mkv', 'mpeg', 'mpg', 'wmv' );
// @formatter:on
/**
* Redefine the way custom headers are processed for this mailer - they should be in body.
*
* @since 3.9.0
*
* @param array $headers List of key=>value pairs.
*/
public function set_headers( $headers ) {
foreach ( $headers as $header ) {
$name = isset( $header[0] ) ? $header[0] : false;
$value = isset( $header[1] ) ? $header[1] : false;
$this->set_body_header( $name, $value );
}
// Add custom PHPMailer-specific header.
$this->set_body_header( 'X-Mailer', 'WPMailSMTP/Mailer/' . $this->mailer . ' ' . WPMS_PLUGIN_VER );
}
/**
* This mailer supports email-related custom headers inside a body of the message.
*
* @since 3.9.0
*
* @param string $name Key.
* @param string $value Value.
*/
public function set_body_header( $name, $value ) {
$name = sanitize_text_field( $name );
if ( empty( $name ) ) {
return;
}
$headers = isset( $this->body['headers'] ) ? (array) $this->body['headers'] : [];
$headers[ $name ] = WP::sanitize_value( $value );
$this->set_body_param(
[
'headers' => $headers,
]
);
}
/**
* Set the From information for an email.
*
* @since 1.6.0
*
* @param string $email
* @param string $name
*/
public function set_from( $email, $name ) {
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
return;
}
$this->body['sender'] = array(
'email' => $email,
'name' => ! empty( $name ) ? WP::sanitize_value( $name ) : '',
);
}
/**
* Set email recipients: to, cc, bcc.
*
* @since 1.6.0
*
* @param array $recipients
*/
public function set_recipients( $recipients ) {
if ( empty( $recipients ) ) {
return;
}
// Allow for now only these recipient types.
$default = array( 'to', 'cc', 'bcc' );
$data = array();
foreach ( $recipients as $type => $emails ) {
if (
! in_array( $type, $default, true ) ||
empty( $emails ) ||
! is_array( $emails )
) {
continue;
}
$data[ $type ] = array();
// Iterate over all emails for each type.
// There might be multiple cc/to/bcc emails.
foreach ( $emails as $email ) {
$holder = array();
$addr = isset( $email[0] ) ? $email[0] : false;
$name = isset( $email[1] ) ? $email[1] : false;
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
continue;
}
$holder['email'] = $addr;
if ( ! empty( $name ) ) {
$holder['name'] = $name;
}
array_push( $data[ $type ], $holder );
}
}
foreach ( $data as $type => $type_recipients ) {
$this->body[ $type ] = $type_recipients;
}
}
/**
* @inheritDoc
*
* @since 1.6.0
*/
public function set_subject( $subject ) {
$this->body['subject'] = $subject;
}
/**
* Set email content.
*
* @since 1.6.0
*
* @param string|array $content
*/
public function set_content( $content ) {
if ( empty( $content ) ) {
return;
}
if ( is_array( $content ) ) {
if ( ! empty( $content['text'] ) ) {
$this->body['textContent'] = $content['text'];
}
if ( ! empty( $content['html'] ) ) {
$this->body['htmlContent'] = $content['html'];
}
} else {
if ( $this->phpmailer->ContentType === 'text/plain' ) {
$this->body['textContent'] = $content;
} else {
$this->body['htmlContent'] = $content;
}
}
}
/**
* Doesn't support this.
*
* @since 1.6.0
*
* @param string $email
*/
public function set_return_path( $email ) {
}
/**
* Set the Reply To headers if not set already.
*
* @since 1.6.0
*
* @param array $emails
*/
public function set_reply_to( $emails ) {
if ( empty( $emails ) ) {
return;
}
$data = array();
foreach ( $emails as $user ) {
$holder = array();
$addr = isset( $user[0] ) ? $user[0] : false;
$name = isset( $user[1] ) ? $user[1] : false;
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
continue;
}
$holder['email'] = $addr;
if ( ! empty( $name ) ) {
$holder['name'] = $name;
}
$data[] = $holder;
}
if ( ! empty( $data ) ) {
$this->body['replyTo'] = $data[0];
}
}
/**
* Set attachments for an email.
*
* @since 1.6.0
*
* @param array $attachments The array of attachments data.
*/
public function set_attachments( $attachments ) {
if ( empty( $attachments ) ) {
return;
}
foreach ( $attachments as $attachment ) {
$ext = pathinfo( $attachment[1], PATHINFO_EXTENSION );
if ( ! in_array( $ext, $this->allowed_attach_ext, true ) ) {
continue;
}
$file = $this->get_attachment_file_content( $attachment );
if ( $file === false ) {
continue;
}
$this->body['attachment'][] = [
'name' => $this->get_attachment_file_name( $attachment ),
'content' => base64_encode( $file ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
];
}
}
/**
* Get the email body.
*
* @since 1.6.0
* @since 3.9.0 Returns email body array instead of `SendSmtpEmail` object.
* @since 3.10.0 Returns JSON encoded email body instead of array.
*
* @return string
*/
public function get_body() {
/**
* Filters Sendinblue email body.
*
* @since 3.5.0
*
* @param array $body Email body.
*/
$body = apply_filters( 'wp_mail_smtp_providers_sendinblue_mailer_get_body', $this->body );
return wp_json_encode( $body );
}
/**
* We might need to do something after the email was sent to the API.
* In this method we preprocess the response from the API.
*
* @since 1.6.0
* @since 3.9.0 Expect a generic class object instead of `CreateSmtpEmail`.
*
* @param mixed $response Response from the API.
*/
protected function process_response( $response ) {
parent::process_response( $response );
if ( $this->has_message_id() ) {
$this->phpmailer->MessageID = $this->response['body']->messageId;
$this->verify_sent_status = true;
}
}
/**
* Get a Sendinblue-specific response with a helpful error.
*
* @since 3.9.0
*
* @return string
*/
public function get_response_error() {
$error_text = [];
if ( ! empty( $this->error_message ) ) {
$error_text[] = $this->error_message;
}
if ( ! empty( $this->response ) ) {
$body = wp_remote_retrieve_body( $this->response );
if ( ! empty( $body->message ) ) {
$error_text[] = Helpers::format_error_message( $body->message, ! empty( $body->code ) ? $body->code : '' );
} else {
$error_text[] = WP::wp_remote_get_response_error_message( $this->response );
}
}
return implode( WP::EOL, array_map( 'esc_textarea', array_filter( $error_text ) ) );
}
/**
* Check whether the response has `messageId` property.
*
* @since 3.9.0
*
* @return bool
*/
private function has_message_id() {
if (
! in_array(
wp_remote_retrieve_response_code( $this->response ),
[ $this->email_sent_code, $this->email_scheduled_code ],
true
) ||
empty( $this->response['body']->messageId )
) {
return false;
}
return true;
}
/**
* Check whether the email was sent.
*
* @since 1.6.0
* @since 3.9.0 Check if `$this->response` has `messageId` property to check if the email was sent.
*
* @return bool
*/
public function is_email_sent() {
/** This filter is documented in src/Providers/MailerAbstract.php. */
return apply_filters( 'wp_mail_smtp_providers_mailer_is_email_sent', $this->has_message_id(), $this->mailer ); // phpcs:ignore WPForms.PHP.ValidateHooks.InvalidHookName
}
/**
* @inheritdoc
*
* @since 1.6.0
*/
public function get_debug_info() {
$mailjet_text[] = '<strong>API Key:</strong> ' . ( $this->is_mailer_complete() ? 'Yes' : 'No' );
return implode( '<br>', $mailjet_text );
}
/**
* @inheritdoc
*
* @since 1.6.0
*/
public function is_mailer_complete() {
$options = $this->connection_options->get_group( $this->mailer );
// API key is the only required option.
if ( ! empty( $options['api_key'] ) ) {
return true;
}
return false;
}
}

View File

@@ -0,0 +1,175 @@
<?php
namespace WPMailSMTP\Providers\Sendinblue;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Providers\OptionsAbstract;
/**
* Class Options.
*
* @since 1.6.0
*/
class Options extends OptionsAbstract {
/**
* Mailer slug.
*
* @since 1.6.0
*/
const SLUG = 'sendinblue';
/**
* Options constructor.
*
* @since 1.6.0
* @since 2.3.0 Added supports parameter.
*
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $connection = null ) {
if ( is_null( $connection ) ) {
$connection = wp_mail_smtp()->get_connections_manager()->get_primary_connection();
}
$description = sprintf(
wp_kses( /* translators: %1$s - URL to brevo.com site. */
__( '<strong><a href="%1$s" target="_blank" rel="noopener noreferrer">Brevo</a> (formerly Sendinblue) is one of our recommended mailers.</strong> It\'s a transactional email provider with scalable price plans, so it\'s suitable for any size of business.<br><br>If you\'re just starting out, you can use Brevo\'s free plan to send up to 300 emails a day. You don\'t need to use a credit card to try it out. When you\'re ready, you can upgrade to a higher plan to increase your sending limits.', 'wp-mail-smtp' ) .
'<br><br>' .
/* translators: %2$s - URL to wpmailsmtp.com doc. */
__( 'To get started, read our <a href="%2$s" target="_blank" rel="noopener noreferrer">Brevo documentation</a>.', 'wp-mail-smtp' ),
[
'strong' => true,
'br' => true,
'a' => [
'href' => true,
'rel' => true,
'target' => true,
],
]
),
'https://wpmailsmtp.com/go/sendinblue/',
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-set-up-the-sendinblue-mailer-in-wp-mail-smtp/', 'Brevo documentation' ) )
);
$api_key = $connection->get_options()->get( self::SLUG, 'api_key' );
if ( empty( $api_key ) ) {
$description .= sprintf(
'</p><p class="buttonned"><a href="%1$s" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-blueish">%2$s</a></p>',
'https://wpmailsmtp.com/go/sendinblue/',
esc_html__( 'Get Brevo Now (Free)', 'wp-mail-smtp' )
);
}
$description .= '<p class="wp-mail-smtp-tooltip">' .
esc_html__( 'Transparency and Disclosure', 'wp-mail-smtp' ) .
'<span class="wp-mail-smtp-tooltip-text">' .
esc_html__( 'We believe in full transparency. The Brevo (formerly Sendinblue) links above are tracking links as part of our partnership with Brevo. We can recommend just about any SMTP service, but we only recommend products that we believe will add value to our users.', 'wp-mail-smtp' ) .
'</span></p>';
parent::__construct(
[
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/brevo.svg',
'slug' => self::SLUG,
'title' => esc_html__( 'Brevo', 'wp-mail-smtp' ),
'php' => '5.6',
'description' => $description,
'supports' => [
'from_email' => true,
'from_name' => true,
'return_path' => false,
'from_email_force' => true,
'from_name_force' => true,
],
'recommended' => true,
],
$connection
);
}
/**
* Output the mailer provider options.
*
* @since 1.6.0
*/
public function display_options() {
// Do not display options if PHP version is not correct.
if ( ! $this->is_php_correct() ) {
$this->display_php_warning();
return;
}
?>
<!-- API Key -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-client_id"
class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'API Key', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php if ( $this->connection_options->is_const_defined( $this->get_slug(), 'api_key' ) ) : ?>
<input type="text" disabled value="****************************************"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php $this->display_const_set_message( 'WPMS_SENDINBLUE_API_KEY' ); ?>
<?php else : ?>
<input type="password" spellcheck="false"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'api_key' ) ); ?>"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php endif; ?>
<p class="desc">
<?php
printf( /* translators: %s - link to get an API Key. */
esc_html__( 'Follow this link to get an API Key: %s.', 'wp-mail-smtp' ),
'<a href="https://app.brevo.com/settings/keys/api" target="_blank" rel="noopener noreferrer">' .
esc_html__( 'Get v3 API Key', 'wp-mail-smtp' ) .
'</a>'
);
?>
</p>
</div>
</div>
<!-- Sending Domain -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-domain" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-domain"><?php esc_html_e( 'Sending Domain', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<input name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][domain]" type="text"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'domain' ) ); ?>"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'domain' ) ? 'disabled' : ''; ?>
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-domain" spellcheck="false"
/>
<p class="desc">
<?php
printf(
wp_kses(
/* translators: %s - URL to Sendinblue documentation on wpmailsmtp.com */
__( 'Please input the sending domain/subdomain you configured in your Brevo (formerly Sendinblue) dashboard. More information can be found in our <a href="%s" target="_blank" rel="noopener noreferrer">Brevo documentation</a>.', 'wp-mail-smtp' ),
[
'br' => [],
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-set-up-the-sendinblue-mailer-in-wp-mail-smtp/#setup-smtp', 'Brevo documentation' ) )
);
?>
</p>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,453 @@
<?php
namespace WPMailSMTP\Providers\Sendlayer;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Helpers\Helpers;
use WPMailSMTP\WP;
use WPMailSMTP\MailCatcherInterface;
use WPMailSMTP\Providers\MailerAbstract;
/**
* Class Mailer.
*
* @since 3.4.0
*/
class Mailer extends MailerAbstract {
/**
* URL to make an API request to.
*
* @since 3.4.0
*
* @var string
*/
protected $url = 'https://console.sendlayer.com/api/v1/email';
/**
* Mailer constructor.
*
* @since 3.4.0
*
* @param MailCatcherInterface $phpmailer The MailCatcher object.
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $phpmailer, $connection = null ) {
// We want to prefill everything from MailCatcher class, which extends PHPMailer.
parent::__construct( $phpmailer, $connection );
// Set mailer specific headers.
$this->set_header( 'Authorization', 'Bearer ' . $this->connection_options->get( $this->mailer, 'api_key' ) );
$this->set_header( 'Accept', 'application/json' );
$this->set_header( 'Content-Type', 'application/json' );
}
/**
* Redefine the way custom headers are processed for this mailer - they should be in body.
*
* @since 3.4.0
*
* @param array $headers Headers array.
*/
public function set_headers( $headers ) {
foreach ( $headers as $header ) {
$name = isset( $header[0] ) ? $header[0] : false;
$value = isset( $header[1] ) ? $header[1] : false;
$this->set_body_header( $name, $value );
}
// Add custom header.
$this->set_body_header( 'X-Mailer', 'WPMailSMTP/Mailer/' . $this->mailer . ' ' . WPMS_PLUGIN_VER );
}
/**
* This mailer supports email-related custom headers inside a body of the message.
*
* @since 3.4.0
*
* @param string $name Header name.
* @param string $value Header value.
*/
public function set_body_header( $name, $value ) {
$name = sanitize_text_field( $name );
if ( empty( $name ) ) {
return;
}
$headers = isset( $this->body['Headers'] ) ? (array) $this->body['Headers'] : [];
$headers[ $name ] = WP::sanitize_value( $value );
$this->set_body_param(
[
'Headers' => $headers,
]
);
}
/**
* Set the From information for an email.
*
* @since 3.4.0
*
* @param string $email The sender email address.
* @param string $name The sender name.
*/
public function set_from( $email, $name ) {
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
return;
}
$this->set_body_param(
[
'From' => $this->address_format( [ $email, $name ] ),
]
);
}
/**
* Set email recipients: to, cc, bcc.
*
* @since 3.4.0
*
* @param array $recipients Email recipients.
*/
public function set_recipients( $recipients ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
if ( empty( $recipients ) ) {
return;
}
// Allow only these recipient types.
$allowed_types = [ 'to', 'cc', 'bcc' ];
$data = [];
foreach ( $recipients as $type => $emails ) {
if (
! in_array( $type, $allowed_types, true ) ||
empty( $emails ) ||
! is_array( $emails )
) {
continue;
}
$type = ucfirst( $type );
// Iterate over all emails for each type.
// There might be multiple cc/to/bcc emails.
foreach ( $emails as $email ) {
if ( ! isset( $email[0] ) || ! filter_var( $email[0], FILTER_VALIDATE_EMAIL ) ) {
continue;
}
$data[ $type ][] = $this->address_format( $email );
}
}
if ( ! empty( $data ) ) {
$this->set_body_param( $data );
}
}
/**
* Set the Reply To information for an email.
*
* @since 3.4.0
*
* @param array $emails Reply To email addresses.
*/
public function set_reply_to( $emails ) {
if ( empty( $emails ) ) {
return;
}
$data = [];
foreach ( $emails as $email ) {
if ( ! isset( $email[0] ) || ! filter_var( $email[0], FILTER_VALIDATE_EMAIL ) ) {
continue;
}
$data[] = $this->address_format( $email );
}
if ( ! empty( $data ) ) {
$this->set_body_param(
[
'ReplyTo' => $data,
]
);
}
}
/**
* Set email subject.
*
* @since 3.4.0
*
* @param string $subject Email subject.
*/
public function set_subject( $subject ) {
$this->set_body_param(
[
'Subject' => $subject,
]
);
}
/**
* Set email content.
*
* @since 3.4.0
*
* @param string|array $content Email content.
*/
public function set_content( $content ) {
if ( empty( $content ) ) {
return;
}
if ( is_array( $content ) ) {
if ( ! empty( $content['text'] ) ) {
$this->set_body_param(
[
'ContentType' => 'plain',
'PlainContent' => $content['text'],
]
);
}
if ( ! empty( $content['html'] ) ) {
$this->set_body_param(
[
'ContentType' => 'html',
'HTMLContent' => $content['html'],
]
);
}
} else {
if ( $this->phpmailer->ContentType === 'text/plain' ) {
$this->set_body_param(
[
'ContentType' => 'plain',
'PlainContent' => $content,
]
);
} else {
$this->set_body_param(
[
'ContentType' => 'html',
'HTMLContent' => $content,
]
);
}
}
}
/**
* Set attachments for an email.
*
* @since 3.4.0
*
* @param array $attachments Attachments array.
*/
public function set_attachments( $attachments ) {
if ( empty( $attachments ) ) {
return;
}
$data = $this->prepare_attachments( $attachments );
if ( ! empty( $data ) ) {
$this->set_body_param(
[
'Attachments' => $data,
]
);
}
}
/**
* Prepare attachments data for SendLayer API.
*
* @since 3.4.0
*
* @param array $attachments Array of attachments.
*
* @return array
*/
protected function prepare_attachments( $attachments ) {
$data = [];
foreach ( $attachments as $attachment ) {
$file = $this->get_attachment_file_content( $attachment );
if ( $file === false ) {
continue;
}
$filetype = str_replace( ';', '', trim( $attachment[4] ) );
$data[] = [
'Filename' => empty( $attachment[2] ) ? 'file-' . wp_hash( microtime() ) . '.' . $filetype : trim( $attachment[2] ),
// phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
'Content' => base64_encode( $file ),
'Type' => $attachment[4],
'Disposition' => in_array( $attachment[6], [ 'inline', 'attachment' ], true ) ? $attachment[6] : 'attachment',
'ContentId' => empty( $attachment[7] ) ? '' : trim( (string) $attachment[7] ),
];
}
return $data;
}
/**
* Doesn't support this.
* So we do nothing.
*
* @since 3.4.0
*
* @param string $email Return Path email address.
*/
public function set_return_path( $email ) { }
/**
* Redefine the way email body is returned.
* By default, we are sending an array of data.
* SendLayer requires a JSON, so we encode the body.
*
* @since 3.4.0
*/
public function get_body() {
$body = parent::get_body();
return wp_json_encode( $body );
}
/**
* We might need to do something after the email was sent to the API.
* In this method we preprocess the response from the API.
*
* @since 3.4.0
*
* @param mixed $response Response data.
*/
protected function process_response( $response ) {
parent::process_response( $response );
if (
! is_wp_error( $response ) &&
! empty( $this->response['body']->MessageID )
) {
$this->phpmailer->addCustomHeader( 'X-Msg-ID', $this->response['body']->MessageID );
$this->verify_sent_status = true;
}
}
/**
* Get a SendLayer-specific response with a helpful error.
*
* @since 3.4.0
*
* @return string
*/
public function get_response_error() { // phpcs:ignore Generic.Metrics.NestingLevel.MaxExceeded
$error_text[] = $this->error_message;
if ( ! empty( $this->response ) ) {
$body = wp_remote_retrieve_body( $this->response );
// phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
if ( ! empty( $body->Errors ) && is_array( $body->Errors ) ) {
foreach ( $body->Errors as $error ) {
if ( ! empty( $error->Message ) ) {
$message = $error->Message;
$code = ! empty( $error->Code ) ? $error->Code : '';
$error_text[] = Helpers::format_error_message( $message, $code );
}
}
} else {
$error_text[] = WP::wp_remote_get_response_error_message( $this->response );
}
// phpcs:enable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
}
return implode( WP::EOL, array_map( 'esc_textarea', array_filter( $error_text ) ) );
}
/**
* Get mailer debug information, that is helpful during support.
*
* @since 3.4.0
*
* @return string
*/
public function get_debug_info() {
$options = $this->connection_options->get_group( $this->mailer );
$text[] = '<strong>' . esc_html__( 'API Key:', 'wp-mail-smtp' ) . '</strong> ' .
( ! empty( $options['api_key'] ) ? 'Yes' : 'No' );
return implode( '<br>', $text );
}
/**
* Whether the mailer has all its settings correctly set up and saved.
*
* This mailer is configured when `server_api_token` setting is defined.
*
* @since 3.4.0
*
* @return bool
*/
public function is_mailer_complete() {
$options = $this->connection_options->get_group( $this->mailer );
if ( ! empty( $options['api_key'] ) ) {
return true;
}
return false;
}
/**
* Prepare address param.
*
* @since 3.4.0
*
* @param array $address Address array.
*
* @return array
*/
private function address_format( $address ) {
$result = [];
$email = isset( $address[0] ) ? $address[0] : false;
$name = isset( $address[1] ) ? $address[1] : false;
$result['Email'] = $email;
if ( ! empty( $name ) ) {
$result['Name'] = $name;
}
return $result;
}
}

View File

@@ -0,0 +1,124 @@
<?php
namespace WPMailSMTP\Providers\Sendlayer;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Providers\OptionsAbstract;
/**
* Class Options.
*
* @since 3.4.0
*/
class Options extends OptionsAbstract {
/**
* Mailer slug.
*
* @since 3.4.0
*
* @var string
*/
const SLUG = 'sendlayer';
/**
* Options constructor.
*
* @since 3.4.0
*
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $connection = null ) {
if ( is_null( $connection ) ) {
$connection = wp_mail_smtp()->get_connections_manager()->get_primary_connection();
}
$description = sprintf(
wp_kses(
/* translators: %1$s - URL to sendlayer.com; %2$s - URL to SendLayer documentation on wpmailsmtp.com. */
__( '<strong><a href="%1$s" target="_blank" rel="noopener noreferrer">SendLayer</a> is our #1 recommended mailer.</strong> Its affordable pricing and simple setup make it the perfect choice for WordPress sites. SendLayer will authenticate your outgoing emails to make sure they always hit customers inboxes, and it has detailed documentation to help you authorize your domain.<br><br>You can send hundreds of emails for free when you sign up for a trial.<br><br>To get started, read our <a href="%2$s" target="_blank" rel="noopener noreferrer">SendLayer documentation</a>.', 'wp-mail-smtp' ),
[
'strong' => [],
'br' => [],
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
// phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound, WordPress.Security.NonceVerification.Recommended
esc_url( wp_mail_smtp()->get_utm_url( 'https://sendlayer.com/wp-mail-smtp/', [ 'source' => 'wpmailsmtpplugin', 'medium' => 'WordPress', 'content' => isset( $_GET['page'] ) && $_GET['page'] === 'wp-mail-smtp-setup-wizard' ? 'Setup Wizard - Mailer Description' : 'Plugin Settings - Mailer Description' ] ) ),
// phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-set-up-the-sendlayer-mailer-in-wp-mail-smtp/', 'SendLayer Documentation' ) )
);
$mailer_options = $connection->get_options()->get_group( self::SLUG );
if ( empty( $mailer_options['api_key'] ) ) {
$description .= sprintf(
'</p><p class="buttonned"><a href="%1$s" target="_blank" rel="noopener noreferrer" class="wp-mail-smtp-btn wp-mail-smtp-btn-md wp-mail-smtp-btn-blueish">%2$s</a></p>',
// phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound
esc_url( wp_mail_smtp()->get_utm_url( 'https://sendlayer.com/wp-mail-smtp/', [ 'source' => 'wpmailsmtpplugin', 'medium' => 'WordPress', 'content' => 'Plugin Settings - Mailer Button' ] ) ),
esc_html__( 'Get Started with SendLayer', 'wp-mail-smtp' )
);
}
parent::__construct(
[
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/sendlayer.svg',
'slug' => self::SLUG,
'title' => esc_html__( 'SendLayer', 'wp-mail-smtp' ),
'description' => $description,
'recommended' => true,
],
$connection
);
}
/**
* Output the mailer provider options.
*
* @since 3.4.0
*/
public function display_options() {
// phpcs:ignore WordPress.Arrays.ArrayDeclarationSpacing.AssociativeArrayFound, WordPress.Security.NonceVerification.Recommended
$get_api_key_url = wp_mail_smtp()->get_utm_url( 'https://app.sendlayer.com/settings/api/', [ 'source' => 'wpmailsmtpplugin', 'medium' => 'WordPress', 'content' => 'Plugin Settings - Get API Key' ] );
?>
<!-- API Key -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'API Key', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php if ( $this->connection_options->is_const_defined( $this->get_slug(), 'api_key' ) ) : ?>
<input type="text" disabled value="****************************************"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php $this->display_const_set_message( 'WPMS_SENDLAYER_API_KEY' ); ?>
<?php else : ?>
<input type="password" spellcheck="false"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'api_key' ) ); ?>"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php endif; ?>
<p class="desc">
<?php
printf(
/* translators: %s - API key link. */
esc_html__( 'Follow this link to get an API Key from SendLayer: %s.', 'wp-mail-smtp' ),
'<a href="' . esc_url( $get_api_key_url ) . '" target="_blank" rel="noopener noreferrer">' .
esc_html__( 'Get API Key', 'wp-mail-smtp' ) .
'</a>'
);
?>
</p>
</div>
</div>
<?php
}
}

View File

@@ -0,0 +1,542 @@
<?php
namespace WPMailSMTP\Providers\SparkPost;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Helpers\Helpers;
use WPMailSMTP\WP;
use WPMailSMTP\MailCatcherInterface;
use WPMailSMTP\Providers\MailerAbstract;
/**
* Class Mailer.
*
* @since 3.2.0
*/
class Mailer extends MailerAbstract {
/**
* API endpoint used for sites from all regions.
*
* @since 3.2.0
*
* @var string
*/
const API_BASE_US = 'https://api.sparkpost.com/api/v1';
/**
* API endpoint used for sites from EU region.
*
* @since 3.2.0
*
* @var string
*/
const API_BASE_EU = 'https://api.eu.sparkpost.com/api/v1';
/**
* Mailer constructor.
*
* @since 3.2.0
*
* @param MailCatcherInterface $phpmailer The MailCatcher object.
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $phpmailer, $connection = null ) {
// Default value should be defined before the parent class constructor fires.
$this->url = self::API_BASE_US;
// We want to prefill everything from MailCatcher class, which extends PHPMailer.
parent::__construct( $phpmailer, $connection );
// We have a special API URL to query in case of EU region.
if ( $this->connection_options->get( $this->mailer, 'region' ) === 'EU' ) {
$this->url = self::API_BASE_EU;
}
$this->url .= '/transmissions';
// Set mailer specific headers.
$this->set_header( 'Authorization', $this->connection_options->get( $this->mailer, 'api_key' ) );
$this->set_header( 'Content-Type', 'application/json' );
// Set default body params.
$this->set_body_param(
[
'options' => [
'open_tracking' => false,
'click_tracking' => false,
'transactional' => true,
],
]
);
/**
* Filters return path.
*
* Email address to use for envelope FROM.
* The domain of the return_path address must be a CNAME-verified sending domain.
* The local part of the return_path address will be overwritten by SparkPost.
*
* @since 3.2.0
*
* @param string $return_path Email address, by default will be used value configured in SparkPost dashboard.
*/
$return_path = apply_filters( 'wp_mail_smtp_providers_sparkpost_mailer_return_path', '' );
if ( $return_path && filter_var( $return_path, FILTER_VALIDATE_EMAIL ) ) {
$this->set_body_param(
[
'return_path' => $return_path,
]
);
}
}
/**
* Redefine the way custom headers are processed for this mailer - they should be in body.
*
* @since 3.2.0
*
* @param array $headers Headers array.
*/
public function set_headers( $headers ) {
foreach ( $headers as $header ) {
$name = isset( $header[0] ) ? $header[0] : false;
$value = isset( $header[1] ) ? $header[1] : false;
$this->set_body_header( $name, $value );
}
// Add custom PHPMailer-specific header.
$this->set_body_header( 'X-Mailer', 'WPMailSMTP/Mailer/' . $this->mailer . ' ' . WPMS_PLUGIN_VER );
$this->set_body_header( 'Message-ID', $this->phpmailer->getLastMessageID() );
}
/**
* This mailer supports email-related custom headers inside a body of the message.
*
* @since 3.2.0
*
* @param string $name Header name.
* @param string $value Header value.
*/
public function set_body_header( $name, $value ) {
$name = sanitize_text_field( $name );
if ( empty( $name ) ) {
return;
}
$headers = isset( $this->body['content']['headers'] ) ? (array) $this->body['content']['headers'] : [];
if ( ! in_array( $name, [ 'Message-ID', 'CC' ], true ) ) {
$value = WP::sanitize_value( $value );
}
$headers[ $name ] = $value;
$this->set_body_param(
[
'content' => [
'headers' => $headers,
],
]
);
}
/**
* Set the From information for an email.
*
* @since 3.2.0
*
* @param string $email The sender email address.
* @param string $name The sender name.
*/
public function set_from( $email, $name ) {
if ( ! filter_var( $email, FILTER_VALIDATE_EMAIL ) ) {
return;
}
$from['email'] = $email;
if ( ! empty( $name ) ) {
$from['name'] = $name;
}
$this->set_body_param(
[
'content' => [
'from' => $from,
],
]
);
}
/**
* Set email recipients: to, cc, bcc.
*
* @since 3.2.0
*
* @param array $recipients Email recipients.
*/
public function set_recipients( $recipients ) { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
if ( empty( $recipients ) ) {
return;
}
$recipients_to = isset( $recipients['to'] ) && is_array( $recipients['to'] ) ? $recipients['to'] : [];
$header_to = implode( ',', array_map( [ $this->phpmailer, 'addrFormat' ], $recipients_to ) );
$default = [ 'to', 'cc', 'bcc' ];
foreach ( $recipients as $type => $emails ) {
if (
! in_array( $type, $default, true ) ||
empty( $emails ) ||
! is_array( $emails )
) {
continue;
}
$data = [];
foreach ( $emails as $email ) {
$addr = isset( $email[0] ) ? $email[0] : false;
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
continue;
}
$data[] = [
'address' => $this->build_recipient( $email, $header_to ),
];
}
// CC recipients must be also included as header.
if ( $type === 'cc' ) {
$this->set_body_header( 'CC', implode( ',', array_map( [ $this->phpmailer, 'addrFormat' ], $emails ) ) );
}
if ( ! empty( $data ) ) {
$this->set_body_param(
[
'recipients' => $data,
]
);
}
}
}
/**
* Set the Reply To information for an email.
*
* @since 3.2.0
*
* @param array $emails Reply To email addresses.
*/
public function set_reply_to( $emails ) {
if ( empty( $emails ) ) {
return;
}
$data = [];
foreach ( $emails as $email ) {
$addr = isset( $email[0] ) ? $email[0] : false;
if ( ! filter_var( $addr, FILTER_VALIDATE_EMAIL ) ) {
continue;
}
$data[] = $this->phpmailer->addrFormat( $email );
}
if ( ! empty( $data ) ) {
$this->set_body_param(
[
'content' => [
'reply_to' => implode( ',', $data ),
],
]
);
}
}
/**
* Set email subject.
*
* @since 3.2.0
*
* @param string $subject Email subject.
*/
public function set_subject( $subject ) {
$this->set_body_param(
[
'content' => [
'subject' => $subject,
],
]
);
}
/**
* Set email content.
*
* @since 3.2.0
*
* @param string|array $content Email content.
*/
public function set_content( $content ) {
if ( empty( $content ) ) {
return;
}
if ( is_array( $content ) ) {
if ( ! empty( $content['text'] ) ) {
$this->set_body_param(
[
'content' => [
'text' => $content['text'],
],
]
);
}
if ( ! empty( $content['html'] ) ) {
$this->set_body_param(
[
'content' => [
'html' => $content['html'],
],
]
);
}
} else {
if ( $this->phpmailer->ContentType === 'text/plain' ) {
$this->set_body_param(
[
'content' => [
'text' => $content,
],
]
);
} else {
$this->set_body_param(
[
'content' => [
'html' => $content,
],
]
);
}
}
}
/**
* Set attachments for an email.
*
* @since 3.2.0
*
* @param array $attachments Attachments array.
*/
public function set_attachments( $attachments ) {
if ( empty( $attachments ) ) {
return;
}
$data = $this->prepare_attachments( $attachments );
if ( ! empty( $data ) ) {
$this->set_body_param(
[
'content' => [
'attachments' => $data,
],
]
);
}
}
/**
* Prepare attachments data for SparkPost API.
*
* @since 3.2.0
*
* @param array $attachments Array of attachments.
*
* @return array
*/
protected function prepare_attachments( $attachments ) {
$data = [];
foreach ( $attachments as $attachment ) {
$file = $this->get_attachment_file_content( $attachment );
if ( $file === false ) {
continue;
}
$data[] = [
'name' => $this->get_attachment_file_name( $attachment ),
'data' => base64_encode( $file ), // phpcs:ignore WordPress.PHP.DiscouragedPHPFunctions.obfuscation_base64_encode
'type' => $attachment[4],
];
}
return $data;
}
/**
* Doesn't support this.
* Return path can be configured in SparkPost account.
*
* @since 3.2.0
*
* @param string $email Return Path email address.
*/
public function set_return_path( $email ) { }
/**
* Redefine the way email body is returned.
* By default, we are sending an array of data.
* SparkPost requires a JSON, so we encode the body.
*
* @since 3.2.0
*/
public function get_body() {
$body = parent::get_body();
return wp_json_encode( $body );
}
/**
* We might need to do something after the email was sent to the API.
* In this method we preprocess the response from the API.
*
* @since 3.2.0
*
* @param mixed $response Response data.
*/
protected function process_response( $response ) {
parent::process_response( $response );
if (
! is_wp_error( $response ) &&
! empty( $this->response['body']->results->id )
) {
$this->phpmailer->addCustomHeader( 'X-Msg-ID', $this->response['body']->results->id );
$this->verify_sent_status = true;
}
}
/**
* Get a SparkPost-specific response with a helpful error.
*
* @since 3.2.0
*
* @return string
*/
public function get_response_error() { // phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh, Generic.Metrics.NestingLevel.MaxExceeded
$error_text[] = $this->error_message;
if ( ! empty( $this->response ) ) {
$body = wp_remote_retrieve_body( $this->response );
if ( ! empty( $body->errors ) && is_array( $body->errors ) ) {
foreach ( $body->errors as $error ) {
if ( ! empty( $error->message ) ) {
$message = $error->message;
$code = ! empty( $error->code ) ? $error->code : '';
$description = ! empty( $error->description ) ? $error->description : '';
$error_text[] = Helpers::format_error_message( $message, $code, $description );
}
}
} else {
$error_text[] = WP::wp_remote_get_response_error_message( $this->response );
}
}
return implode( WP::EOL, array_map( 'esc_textarea', array_filter( $error_text ) ) );
}
/**
* Get mailer debug information, that is helpful during support.
*
* @since 3.2.0
*
* @return string
*/
public function get_debug_info() {
$options = $this->connection_options->get_group( $this->mailer );
$text[] = '<strong>' . esc_html__( 'API Key:', 'wp-mail-smtp' ) . '</strong> ' .
( ! empty( $options['api_key'] ) ? 'Yes' : 'No' );
$text[] = '<strong>' . esc_html__( 'Region:', 'wp-mail-smtp' ) . '</strong> ' .
( ! empty( $options['region'] ) ? 'Yes' : 'No' );
return implode( '<br>', $text );
}
/**
* Whether the mailer has all its settings correctly set up and saved.
*
* This mailer is configured when `api_key` setting is defined.
*
* @since 3.2.0
*
* @return bool
*/
public function is_mailer_complete() {
$options = $this->connection_options->get_group( $this->mailer );
if ( ! empty( $options['api_key'] ) ) {
return true;
}
return false;
}
/**
* Build recipient array.
*
* @since 3.2.0
*
* @param array $address Email address array.
* @param string $header_to Email recipients To header.
*
* @return array
*/
private function build_recipient( $address, $header_to ) {
$holder = [];
$holder['email'] = $address[0];
if ( ! empty( $address[1] ) ) {
$holder['name'] = $address[1];
}
if ( ! empty( $header_to ) ) {
$holder['header_to'] = $header_to;
unset( $holder['name'] );
}
return $holder;
}
}

View File

@@ -0,0 +1,173 @@
<?php
namespace WPMailSMTP\Providers\SparkPost;
use WPMailSMTP\ConnectionInterface;
use WPMailSMTP\Providers\OptionsAbstract;
/**
* Class Options.
*
* @since 3.2.0
*/
class Options extends OptionsAbstract {
/**
* Mailer slug.
*
* @since 3.2.0
*/
const SLUG = 'sparkpost';
/**
* Options constructor.
*
* @since 3.2.0
*
* @param ConnectionInterface $connection The Connection object.
*/
public function __construct( $connection = null ) {
$description = sprintf(
wp_kses( /* translators: %1$s - URL to SparkPost website. */
__( '<a href="%1$s" target="_blank" rel="noopener noreferrer">SparkPost</a> is a transactional email provider that\'s trusted by big brands and small businesses. It sends more than 4 trillion emails each year and reports 99.9%% uptime. You can get started with the free test account that lets you send up to 500 emails per month.', 'wp-mail-smtp' ) .
'<br><br>' .
/* translators: %2$s - URL to wpmailsmtp.com doc. */
__( 'To get started, read our <a href="%2$s" target="_blank" rel="noopener noreferrer">SparkPost documentation</a>.', 'wp-mail-smtp' ),
[
'br' => true,
'a' => [
'href' => true,
'rel' => true,
'target' => true,
],
]
),
'https://www.sparkpost.com/',
esc_url( wp_mail_smtp()->get_utm_url( 'https://wpmailsmtp.com/docs/how-to-set-up-the-sparkpost-mailer-in-wp-mail-smtp/', 'SparkPost documentation' ) )
);
parent::__construct(
[
'logo_url' => wp_mail_smtp()->assets_url . '/images/providers/sparkpost.svg',
'slug' => self::SLUG,
'title' => esc_html__( 'SparkPost', 'wp-mail-smtp' ),
'php' => '5.6',
'description' => $description,
'supports' => [
'from_email' => true,
'from_name' => true,
'return_path' => false,
'from_email_force' => true,
'from_name_force' => true,
],
'recommended' => false,
],
$connection
);
}
/**
* Output the mailer provider options.
*
* @since 3.2.0
*/
public function display_options() {
// Do not display options if PHP version is not correct.
if ( ! $this->is_php_correct() ) {
$this->display_php_warning();
return;
}
?>
<!-- API Key -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-api_key" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-text wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"><?php esc_html_e( 'API Key', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<?php if ( $this->connection_options->is_const_defined( $this->get_slug(), 'api_key' ) ) : ?>
<input type="text" disabled value="****************************************"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php $this->display_const_set_message( 'WPMS_SPARKPOST_API_KEY' ); ?>
<?php else : ?>
<input type="password" spellcheck="false"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][api_key]"
value="<?php echo esc_attr( $this->connection_options->get( $this->get_slug(), 'api_key' ) ); ?>"
id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-api_key"
/>
<?php endif; ?>
<p class="desc">
<?php
$url = 'sparkpost.com';
$url = $this->connection_options->get( $this->get_slug(), 'region' ) === 'EU' ? 'eu.' . $url : $url;
$url = 'https://app.' . $url . '/account/api-keys';
printf( /* translators: %s - API Key link. */
esc_html__( 'Follow this link to get an API Key from SparkPost: %s.', 'wp-mail-smtp' ),
'<a href="' . esc_url( $url ) . '" target="_blank" rel="noopener noreferrer">' .
esc_html__( 'Get API Key', 'wp-mail-smtp' ) .
'</a>'
);
?>
</p>
</div>
</div>
<!-- Region -->
<div id="wp-mail-smtp-setting-row-<?php echo esc_attr( $this->get_slug() ); ?>-region" class="wp-mail-smtp-setting-row wp-mail-smtp-setting-row-radio wp-mail-smtp-clear">
<div class="wp-mail-smtp-setting-label">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-region"><?php esc_html_e( 'Region', 'wp-mail-smtp' ); ?></label>
</div>
<div class="wp-mail-smtp-setting-field">
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-region-us">
<input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-region-us"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][region]" value="US"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'region' ) ? 'disabled' : ''; ?>
<?php checked( 'US', $this->connection_options->get( $this->get_slug(), 'region' ) ); ?>
/>
<?php esc_html_e( 'US', 'wp-mail-smtp' ); ?>
</label>
<label for="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-region-eu">
<input type="radio" id="wp-mail-smtp-setting-<?php echo esc_attr( $this->get_slug() ); ?>-region-eu"
name="wp-mail-smtp[<?php echo esc_attr( $this->get_slug() ); ?>][region]" value="EU"
<?php echo $this->connection_options->is_const_defined( $this->get_slug(), 'region' ) ? 'disabled' : ''; ?>
<?php checked( 'EU', $this->connection_options->get( $this->get_slug(), 'region' ) ); ?>
/>
<?php esc_html_e( 'EU', 'wp-mail-smtp' ); ?>
</label>
<?php
if ( $this->connection_options->is_const_defined( $this->get_slug(), 'region' ) ) {
$this->display_const_set_message( 'WPMS_SPARKPOST_REGION' );
}
?>
<p class="desc">
<?php esc_html_e( 'Select your SparkPost account region.', 'wp-mail-smtp' ); ?>
<?php
printf(
wp_kses(
/* translators: %s - URL to Mailgun.com page. */
__( '<a href="%s" rel="" target="_blank">More information</a> on SparkPost.', 'wp-mail-smtp' ),
[
'a' => [
'href' => [],
'rel' => [],
'target' => [],
],
]
),
'https://www.sparkpost.com/docs/getting-started/getting-started-sparkpost'
);
?>
</p>
</div>
</div>
<?php
}
}

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