v2.1.3
This commit is contained in:
parent
3daee2df53
commit
19ef0566df
610 changed files with 21958 additions and 3112 deletions
|
|
@ -126,12 +126,10 @@ class Plugin {
|
|||
$secret_key = (string) ( $settings[ self::OPTION_SECRET_KEY ] ?? '' );
|
||||
$region = (string) ( $settings[ self::OPTION_REGION ] ?? '' );
|
||||
|
||||
|
||||
if ( '' === $access_key || '' === $secret_key || '' === $region ) {
|
||||
return $pre_wp_mail;
|
||||
}
|
||||
|
||||
|
||||
$mail_data = \wp_parse_args(
|
||||
$mail_data,
|
||||
array(
|
||||
|
|
@ -198,12 +196,12 @@ class Plugin {
|
|||
/**
|
||||
* Sends the email data to Amazon SES using the SDK client.
|
||||
*
|
||||
* @param array<string, mixed> $mail_context Normalized mail data.
|
||||
* @param array<string, mixed> $settings Stored plugin settings.
|
||||
* @param array<string, mixed> $parsed_headers Structured header data.
|
||||
* @param string $access_key AWS access key ID.
|
||||
* @param string $secret_key AWS secret access key.
|
||||
* @param string $region AWS region identifier.
|
||||
* @param array{to: array<int, string>, subject: string, message: string, headers: mixed, attachments: array<int, string>} $mail_context Normalized mail data.
|
||||
* @param array{host: string, username: string, password: string, from_email: string, from_name: string, reply_to_email: string, reply_to_name: string, security: string, port: int, amazon_ses_access_key: string, amazon_ses_secret_key: string, amazon_ses_region: string, logs_enabled: bool, logs_retention_mode: string, logs_retention_count: int, logs_retention_days: int, stats_retention_days: int, rate_limit_per_second: int, rate_limit_per_hour: int, rate_limit_per_day: int, delete_data_on_uninstall: bool} $settings Stored plugin settings.
|
||||
* @param array{content_type: string|null, charset: string|null, cc: array<int, string>, bcc: array<int, string>, reply_to: array<int, string>, custom: array<int, array{name: string, value: string}>} $parsed_headers Structured header data.
|
||||
* @param string $access_key AWS access key ID.
|
||||
* @param string $secret_key AWS secret access key.
|
||||
* @param string $region AWS region identifier.
|
||||
*
|
||||
* @return WP_Error|null
|
||||
*/
|
||||
|
|
@ -278,15 +276,15 @@ class Plugin {
|
|||
\esc_html( (string) $message )
|
||||
),
|
||||
array(
|
||||
'to' => $mail_context['to'],
|
||||
'subject' => $mail_context['subject'],
|
||||
'message' => $mail_context['message'],
|
||||
'headers' => $mail_context['headers'],
|
||||
'attachments' => $mail_context['attachments'],
|
||||
'ses_error_code' => $exception->getAwsErrorCode(),
|
||||
'ses_request_id' => $exception->getAwsRequestId(),
|
||||
'ses_http_status_code' => $exception->getStatusCode(),
|
||||
'ses_debug' => $debug_context,
|
||||
'to' => $mail_context['to'],
|
||||
'subject' => $mail_context['subject'],
|
||||
'message' => $mail_context['message'],
|
||||
'headers' => $mail_context['headers'],
|
||||
'attachments' => $mail_context['attachments'],
|
||||
'ses_error_code' => $exception->getAwsErrorCode(),
|
||||
'ses_request_id' => $exception->getAwsRequestId(),
|
||||
'ses_http_status_code' => $exception->getStatusCode(),
|
||||
'ses_debug' => $debug_context,
|
||||
)
|
||||
);
|
||||
} catch ( Throwable $exception ) {
|
||||
|
|
@ -314,9 +312,9 @@ class Plugin {
|
|||
/**
|
||||
* Builds a PHPMailer instance configured with the provided mail data.
|
||||
*
|
||||
* @param array<string, mixed> $mail_context Normalized mail data.
|
||||
* @param array<string, mixed> $settings Stored plugin settings.
|
||||
* @param array<string, mixed> $parsed_headers Structured header data.
|
||||
* @param array{to: array<int, string>, subject: string, message: string, headers: mixed, attachments: array<int, string>} $mail_context Normalized mail data.
|
||||
* @param array{host: string, username: string, password: string, from_email: string, from_name: string, reply_to_email: string, reply_to_name: string, security: string, port: int, amazon_ses_access_key: string, amazon_ses_secret_key: string, amazon_ses_region: string, logs_enabled: bool, logs_retention_mode: string, logs_retention_count: int, logs_retention_days: int, stats_retention_days: int, rate_limit_per_second: int, rate_limit_per_hour: int, rate_limit_per_day: int, delete_data_on_uninstall: bool} $settings Stored plugin settings.
|
||||
* @param array{content_type: string|null, charset: string|null, cc: array<int, string>, bcc: array<int, string>, reply_to: array<int, string>, custom: array<int, array{name: string, value: string}>} $parsed_headers Structured header data.
|
||||
*
|
||||
* @return PHPMailer|WP_Error
|
||||
*/
|
||||
|
|
@ -326,14 +324,21 @@ class Plugin {
|
|||
$default_content_type = \apply_filters( 'wp_mail_content_type', 'text/plain' );
|
||||
$default_charset = \apply_filters( 'wp_mail_charset', \get_bloginfo( 'charset' ) );
|
||||
|
||||
$content_type = is_string( $parsed_headers['content_type'] ?? '' ) && '' !== $parsed_headers['content_type'] ? $parsed_headers['content_type'] : ( is_string( $default_content_type ) ? $default_content_type : 'text/plain' );
|
||||
$charset = is_string( $parsed_headers['charset'] ?? '' ) && '' !== $parsed_headers['charset'] ? $parsed_headers['charset'] : ( is_string( $default_charset ) ? $default_charset : 'utf-8' );
|
||||
$content_type_header = $parsed_headers['content_type'];
|
||||
$content_type = ( null !== $content_type_header && '' !== $content_type_header )
|
||||
? $content_type_header
|
||||
: ( is_string( $default_content_type ) ? $default_content_type : 'text/plain' );
|
||||
|
||||
$charset_header = $parsed_headers['charset'];
|
||||
$charset = ( null !== $charset_header && '' !== $charset_header )
|
||||
? $charset_header
|
||||
: ( is_string( $default_charset ) ? $default_charset : 'utf-8' );
|
||||
|
||||
// Ensure charset is never empty, null, or the string "null".
|
||||
$charset = \trim( (string) $charset );
|
||||
if ( '' === $charset || 'null' === \strtolower( $charset ) ) {
|
||||
$charset = 'utf-8';
|
||||
}
|
||||
$charset = \trim( $charset );
|
||||
if ( '' === $charset || 'null' === \strtolower( $charset ) ) {
|
||||
$charset = 'utf-8';
|
||||
}
|
||||
|
||||
// phpcs:disable WordPress.NamingConventions.ValidVariableName.UsedPropertyNotSnakeCase
|
||||
$phpmailer->CharSet = $charset;
|
||||
|
|
@ -538,43 +543,43 @@ class Plugin {
|
|||
/**
|
||||
* Determines the From email address based on the stored settings and filters.
|
||||
*
|
||||
* @param array<string, mixed> $settings Stored plugin settings.
|
||||
* @param array{host: string, username: string, password: string, from_email: string, from_name: string, reply_to_email: string, reply_to_name: string, security: string, port: int, amazon_ses_access_key: string, amazon_ses_secret_key: string, amazon_ses_region: string, logs_enabled: bool, logs_retention_mode: string, logs_retention_count: int, logs_retention_days: int, stats_retention_days: int, rate_limit_per_second: int, rate_limit_per_hour: int, rate_limit_per_day: int, delete_data_on_uninstall: bool} $settings Stored plugin settings.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function determine_from_email( array $settings ): string {
|
||||
$default_email = \get_bloginfo( 'admin_email' );
|
||||
|
||||
if ( isset( $settings['from_email'] ) && \is_email( $settings['from_email'] ) ) {
|
||||
if ( \is_email( $settings['from_email'] ) ) {
|
||||
$default_email = $settings['from_email'];
|
||||
}
|
||||
|
||||
$filtered = \apply_filters( 'wp_mail_from', $default_email );
|
||||
|
||||
if ( ! \is_email( $filtered ) ) {
|
||||
return (string) $default_email;
|
||||
if ( ! is_string( $filtered ) || ! \is_email( $filtered ) ) {
|
||||
return $default_email;
|
||||
}
|
||||
|
||||
return (string) $filtered;
|
||||
return $filtered;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the From name based on stored settings and filters.
|
||||
*
|
||||
* @param array<string, mixed> $settings Stored plugin settings.
|
||||
* @param array{host: string, username: string, password: string, from_email: string, from_name: string, reply_to_email: string, reply_to_name: string, security: string, port: int, amazon_ses_access_key: string, amazon_ses_secret_key: string, amazon_ses_region: string, logs_enabled: bool, logs_retention_mode: string, logs_retention_count: int, logs_retention_days: int, stats_retention_days: int, rate_limit_per_second: int, rate_limit_per_hour: int, rate_limit_per_day: int, delete_data_on_uninstall: bool} $settings Stored plugin settings.
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function determine_from_name( array $settings ): string {
|
||||
$default_name = \get_bloginfo( 'name', 'display' );
|
||||
|
||||
if ( isset( $settings['from_name'] ) && '' !== $settings['from_name'] ) {
|
||||
if ( '' !== $settings['from_name'] ) {
|
||||
$default_name = $settings['from_name'];
|
||||
}
|
||||
|
||||
$filtered = \apply_filters( 'wp_mail_from_name', $default_name );
|
||||
|
||||
return (string) $filtered;
|
||||
return is_string( $filtered ) ? $filtered : $default_name;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -600,11 +605,11 @@ class Plugin {
|
|||
$normalized = array();
|
||||
|
||||
foreach ( $headers as $header ) {
|
||||
if ( is_array( $header ) ) {
|
||||
if ( ! is_string( $header ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$line = trim( (string) $header );
|
||||
$line = trim( $header );
|
||||
|
||||
if ( '' !== $line ) {
|
||||
$normalized[] = $line;
|
||||
|
|
@ -619,7 +624,14 @@ class Plugin {
|
|||
*
|
||||
* @param array<int, string> $headers Normalized header lines.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
* @return array{
|
||||
* content_type: string|null,
|
||||
* charset: string|null,
|
||||
* cc: array<int, string>,
|
||||
* bcc: array<int, string>,
|
||||
* reply_to: array<int, string>,
|
||||
* custom: array<int, array{name: string, value: string}>
|
||||
* }
|
||||
*/
|
||||
private function parse_headers( array $headers ): array {
|
||||
$parsed = array(
|
||||
|
|
@ -701,17 +713,17 @@ class Plugin {
|
|||
}
|
||||
|
||||
if ( ! is_array( $recipients ) ) {
|
||||
$recipients = explode( ',', (string) $recipients );
|
||||
$recipients = is_string( $recipients ) ? explode( ',', $recipients ) : array();
|
||||
}
|
||||
|
||||
$normalized = array();
|
||||
|
||||
foreach ( $recipients as $recipient ) {
|
||||
if ( is_array( $recipient ) ) {
|
||||
if ( ! is_string( $recipient ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$address = trim( (string) $recipient );
|
||||
$address = trim( $recipient );
|
||||
|
||||
if ( '' !== $address ) {
|
||||
$normalized[] = $address;
|
||||
|
|
@ -740,11 +752,11 @@ class Plugin {
|
|||
$normalized = array();
|
||||
|
||||
foreach ( $attachments as $attachment ) {
|
||||
if ( is_array( $attachment ) ) {
|
||||
if ( ! is_string( $attachment ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$path = trim( (string) $attachment );
|
||||
$path = trim( $attachment );
|
||||
|
||||
if ( '' !== $path ) {
|
||||
$normalized[] = $path;
|
||||
|
|
@ -810,11 +822,11 @@ class Plugin {
|
|||
$endpoint = \sprintf( 'https://email.%s.amazonaws.com', $region );
|
||||
|
||||
return array(
|
||||
'region' => $region,
|
||||
'access_key' => $masked_key,
|
||||
'sdk_version' => $sdk_version,
|
||||
'endpoint' => $endpoint,
|
||||
'timestamp' => \gmdate( 'Y-m-d H:i:s' ) . ' UTC',
|
||||
'region' => $region,
|
||||
'access_key' => $masked_key,
|
||||
'sdk_version' => $sdk_version,
|
||||
'endpoint' => $endpoint,
|
||||
'timestamp' => \gmdate( 'Y-m-d H:i:s' ) . ' UTC',
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -828,7 +840,6 @@ class Plugin {
|
|||
public function declare_active( bool $is_active ): bool {
|
||||
unset( $is_active );
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -854,8 +865,12 @@ class Plugin {
|
|||
\delete_transient( 'robotstxt_smtp_admin_notices' );
|
||||
|
||||
foreach ( $notices as $notice ) {
|
||||
$type = $notice['type'] ?? 'info';
|
||||
$message = $notice['message'] ?? '';
|
||||
if ( ! is_array( $notice ) ) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$type = isset( $notice['type'] ) && is_string( $notice['type'] ) ? $notice['type'] : 'info';
|
||||
$message = isset( $notice['message'] ) && is_string( $notice['message'] ) ? $notice['message'] : '';
|
||||
|
||||
if ( $message ) {
|
||||
printf(
|
||||
|
|
@ -888,7 +903,8 @@ class Plugin {
|
|||
// This is a refresh quota request - now verify nonce.
|
||||
$nonce_post = \filter_input( INPUT_POST, 'robotstxt_smtp_refresh_quota_nonce', FILTER_UNSAFE_RAW );
|
||||
$nonce_get = \filter_input( INPUT_GET, 'robotstxt_smtp_refresh_quota_nonce', FILTER_UNSAFE_RAW );
|
||||
$nonce = $nonce_post ?? $nonce_get ?? '';
|
||||
$nonce_raw = $nonce_post ?? $nonce_get ?? '';
|
||||
$nonce = is_string( $nonce_raw ) ? $nonce_raw : '';
|
||||
|
||||
if ( ! \wp_verify_nonce( $nonce, 'robotstxt_smtp_refresh_quota' ) ) {
|
||||
\wp_die( \esc_html__( 'Security check failed.', 'robotstxt-smtp-amazonses' ) );
|
||||
|
|
@ -1007,7 +1023,7 @@ class Plugin {
|
|||
* @return void
|
||||
*/
|
||||
public function render_access_key_field(): void {
|
||||
$settings = $this->get_stored_settings();
|
||||
$settings = $this->get_stored_settings();
|
||||
$has_access_key = '' !== $settings[ self::OPTION_ACCESS_KEY ];
|
||||
$placeholder_label = $has_access_key ? \__( 'Leave empty to keep the stored access key.', 'robotstxt-smtp-amazonses' ) : '';
|
||||
?>
|
||||
|
|
@ -1079,8 +1095,6 @@ class Plugin {
|
|||
public function sanitize_settings( array $clean, array $options, Settings_Page $settings ): array {
|
||||
unset( $settings );
|
||||
|
||||
// Debug: Log incoming $clean array.
|
||||
|
||||
if ( ! SMTP_Plugin::is_amazon_ses_integration_active() ) {
|
||||
return $clean;
|
||||
}
|
||||
|
|
@ -1094,7 +1108,8 @@ class Plugin {
|
|||
$credentials_changed = false;
|
||||
|
||||
if ( array_key_exists( self::OPTION_ACCESS_KEY, $options ) ) {
|
||||
$submitted_access_key = \trim( (string) $options[ self::OPTION_ACCESS_KEY ] );
|
||||
$raw_access_key = $options[ self::OPTION_ACCESS_KEY ] ?? null;
|
||||
$submitted_access_key = \trim( is_string( $raw_access_key ) ? $raw_access_key : '' );
|
||||
|
||||
if ( '' !== $submitted_access_key ) {
|
||||
$sanitized_access_key = \sanitize_text_field( $submitted_access_key );
|
||||
|
|
@ -1108,7 +1123,8 @@ class Plugin {
|
|||
}
|
||||
|
||||
if ( array_key_exists( self::OPTION_SECRET_KEY, $options ) ) {
|
||||
$submitted_secret_key = \trim( (string) $options[ self::OPTION_SECRET_KEY ] );
|
||||
$raw_secret_key = $options[ self::OPTION_SECRET_KEY ] ?? null;
|
||||
$submitted_secret_key = \trim( is_string( $raw_secret_key ) ? $raw_secret_key : '' );
|
||||
|
||||
if ( '' !== $submitted_secret_key ) {
|
||||
$sanitized_secret_key = \sanitize_text_field( $submitted_secret_key );
|
||||
|
|
@ -1122,7 +1138,8 @@ class Plugin {
|
|||
}
|
||||
|
||||
if ( array_key_exists( self::OPTION_REGION, $options ) ) {
|
||||
$submitted_region = \sanitize_text_field( (string) $options[ self::OPTION_REGION ] );
|
||||
$raw_region = $options[ self::OPTION_REGION ] ?? null;
|
||||
$submitted_region = \sanitize_text_field( is_string( $raw_region ) ? $raw_region : '' );
|
||||
|
||||
if ( '' === $submitted_region ) {
|
||||
if ( '' !== $region ) {
|
||||
|
|
@ -1152,10 +1169,6 @@ class Plugin {
|
|||
$clean[ self::OPTION_SECRET_KEY ] = $secret_key;
|
||||
$clean[ self::OPTION_REGION ] = $region;
|
||||
|
||||
// Temporary debug logging
|
||||
|
||||
// Debug: Check credentials_changed and values
|
||||
|
||||
if ( $credentials_changed && ( '' === $access_key || '' === $secret_key || '' === $region ) ) {
|
||||
\add_settings_error(
|
||||
$settings_error_slug,
|
||||
|
|
@ -1197,16 +1210,14 @@ class Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
// Debug: Log final $clean array before return.
|
||||
return $clean;
|
||||
return $clean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restores the previously stored Amazon SES values in case validation fails.
|
||||
*
|
||||
* @param array<string, mixed> $clean Current sanitized values.
|
||||
* @param array<string, mixed> $stored_settings Stored settings merged with defaults.
|
||||
* @param array<string, mixed> $clean Current sanitized values.
|
||||
* @param array{amazon_ses_access_key: string, amazon_ses_secret_key: string, amazon_ses_region: string, host: string, username: string, password: string, from_email: string, from_name: string, reply_to_email: string, reply_to_name: string, security: string, port: int, logs_enabled: bool, logs_retention_mode: string, logs_retention_count: int, logs_retention_days: int, stats_retention_days: int, rate_limit_per_second: int, rate_limit_per_hour: int, rate_limit_per_day: int, delete_data_on_uninstall: bool} $stored_settings Stored settings merged with defaults.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
*/
|
||||
|
|
@ -1221,7 +1232,29 @@ class Plugin {
|
|||
/**
|
||||
* Retrieves the stored settings merged with defaults for the active scope.
|
||||
*
|
||||
* @return array<string, mixed>
|
||||
* @return array{
|
||||
* host: string,
|
||||
* username: string,
|
||||
* password: string,
|
||||
* from_email: string,
|
||||
* from_name: string,
|
||||
* reply_to_email: string,
|
||||
* reply_to_name: string,
|
||||
* security: string,
|
||||
* port: int,
|
||||
* amazon_ses_access_key: string,
|
||||
* amazon_ses_secret_key: string,
|
||||
* amazon_ses_region: string,
|
||||
* logs_enabled: bool,
|
||||
* logs_retention_mode: string,
|
||||
* logs_retention_count: int,
|
||||
* logs_retention_days: int,
|
||||
* stats_retention_days: int,
|
||||
* rate_limit_per_second: int,
|
||||
* rate_limit_per_hour: int,
|
||||
* rate_limit_per_day: int,
|
||||
* delete_data_on_uninstall: bool
|
||||
* }
|
||||
*/
|
||||
private function get_stored_settings(): array {
|
||||
$option_name = $this->get_settings_option_name();
|
||||
|
|
@ -1238,16 +1271,43 @@ class Plugin {
|
|||
|
||||
$settings = \wp_parse_args( $settings, Settings_Page::get_default_settings() );
|
||||
|
||||
$s = (array) $settings;
|
||||
|
||||
$access_key = is_string( $s[ self::OPTION_ACCESS_KEY ] ?? null ) ? $s[ self::OPTION_ACCESS_KEY ] : '';
|
||||
$secret_key = is_string( $s[ self::OPTION_SECRET_KEY ] ?? null ) ? $s[ self::OPTION_SECRET_KEY ] : '';
|
||||
|
||||
// Decrypt Amazon SES credentials after loading from database.
|
||||
if ( isset( $settings[ self::OPTION_ACCESS_KEY ] ) && '' !== $settings[ self::OPTION_ACCESS_KEY ] ) {
|
||||
$settings[ self::OPTION_ACCESS_KEY ] = \Robotstxt_SMTP_Encryption::decrypt( $settings[ self::OPTION_ACCESS_KEY ] );
|
||||
if ( '' !== $access_key ) {
|
||||
$access_key = \Robotstxt_SMTP_Encryption::decrypt( $access_key );
|
||||
}
|
||||
|
||||
if ( isset( $settings[ self::OPTION_SECRET_KEY ] ) && '' !== $settings[ self::OPTION_SECRET_KEY ] ) {
|
||||
$settings[ self::OPTION_SECRET_KEY ] = \Robotstxt_SMTP_Encryption::decrypt( $settings[ self::OPTION_SECRET_KEY ] );
|
||||
if ( '' !== $secret_key ) {
|
||||
$secret_key = \Robotstxt_SMTP_Encryption::decrypt( $secret_key );
|
||||
}
|
||||
|
||||
return $settings;
|
||||
return array(
|
||||
'host' => is_string( $s['host'] ?? null ) ? $s['host'] : '',
|
||||
'username' => is_string( $s['username'] ?? null ) ? $s['username'] : '',
|
||||
'password' => is_string( $s['password'] ?? null ) ? $s['password'] : '',
|
||||
'from_email' => is_string( $s['from_email'] ?? null ) ? $s['from_email'] : '',
|
||||
'from_name' => is_string( $s['from_name'] ?? null ) ? $s['from_name'] : '',
|
||||
'reply_to_email' => is_string( $s['reply_to_email'] ?? null ) ? $s['reply_to_email'] : '',
|
||||
'reply_to_name' => is_string( $s['reply_to_name'] ?? null ) ? $s['reply_to_name'] : '',
|
||||
'security' => is_string( $s['security'] ?? null ) ? $s['security'] : 'none',
|
||||
'port' => is_int( $s['port'] ?? null ) ? $s['port'] : 25,
|
||||
self::OPTION_ACCESS_KEY => $access_key,
|
||||
self::OPTION_SECRET_KEY => $secret_key,
|
||||
self::OPTION_REGION => is_string( $s[ self::OPTION_REGION ] ?? null ) ? $s[ self::OPTION_REGION ] : '',
|
||||
'logs_enabled' => is_bool( $s['logs_enabled'] ?? null ) ? $s['logs_enabled'] : false,
|
||||
'logs_retention_mode' => is_string( $s['logs_retention_mode'] ?? null ) ? $s['logs_retention_mode'] : 'count',
|
||||
'logs_retention_count' => is_int( $s['logs_retention_count'] ?? null ) ? $s['logs_retention_count'] : 1024,
|
||||
'logs_retention_days' => is_int( $s['logs_retention_days'] ?? null ) ? $s['logs_retention_days'] : 28,
|
||||
'stats_retention_days' => is_int( $s['stats_retention_days'] ?? null ) ? $s['stats_retention_days'] : 28,
|
||||
'rate_limit_per_second' => is_int( $s['rate_limit_per_second'] ?? null ) ? $s['rate_limit_per_second'] : 0,
|
||||
'rate_limit_per_hour' => is_int( $s['rate_limit_per_hour'] ?? null ) ? $s['rate_limit_per_hour'] : 0,
|
||||
'rate_limit_per_day' => is_int( $s['rate_limit_per_day'] ?? null ) ? $s['rate_limit_per_day'] : 0,
|
||||
'delete_data_on_uninstall' => is_bool( $s['delete_data_on_uninstall'] ?? null ) ? $s['delete_data_on_uninstall'] : false,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -1303,7 +1363,7 @@ class Plugin {
|
|||
$regions = $partition->getAvailableEndpoints( 'ses' );
|
||||
|
||||
foreach ( $regions as $region ) {
|
||||
if ( is_string( $region ) && '' !== $region ) {
|
||||
if ( '' !== $region ) {
|
||||
$discovered_list[ $region ] = $labels[ $region ] ?? $this->format_region_label( $region );
|
||||
}
|
||||
}
|
||||
|
|
@ -1561,17 +1621,21 @@ class Plugin {
|
|||
|
||||
$send_quota = $result->get( 'SendQuota' );
|
||||
|
||||
if ( ! $send_quota ) {
|
||||
if ( ! is_array( $send_quota ) ) {
|
||||
return new WP_Error(
|
||||
'no_quota_data',
|
||||
__( 'Amazon SES did not return quota data.', 'robotstxt-smtp-amazonses' )
|
||||
);
|
||||
}
|
||||
|
||||
$raw_max_24 = $send_quota['Max24HourSend'] ?? 0;
|
||||
$raw_rate = $send_quota['MaxSendRate'] ?? 0;
|
||||
$raw_sent_24 = $send_quota['SentLast24Hours'] ?? 0;
|
||||
|
||||
return array(
|
||||
'max_24_hour_send' => (int) ( $send_quota['Max24HourSend'] ?? 0 ),
|
||||
'max_send_rate' => (float) ( $send_quota['MaxSendRate'] ?? 0 ),
|
||||
'sent_last_24_hours' => (int) ( $send_quota['SentLast24Hours'] ?? 0 ),
|
||||
'max_24_hour_send' => is_numeric( $raw_max_24 ) ? (int) $raw_max_24 : 0,
|
||||
'max_send_rate' => is_numeric( $raw_rate ) ? (float) $raw_rate : 0.0,
|
||||
'sent_last_24_hours' => is_numeric( $raw_sent_24 ) ? (int) $raw_sent_24 : 0,
|
||||
'fetched_at' => time(),
|
||||
);
|
||||
|
||||
|
|
@ -1606,56 +1670,6 @@ class Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies SES quota limits to the SMTP plugin rate limiting settings.
|
||||
*
|
||||
* @since 1.0.1
|
||||
*
|
||||
* @param array<string, mixed> $quota Quota data from SES.
|
||||
* @return void
|
||||
*/
|
||||
private function apply_ses_quota_to_rate_limits( array $quota ): void {
|
||||
$max_send_rate = (float) ( $quota['max_send_rate'] ?? 0 );
|
||||
$max_24_hour_send = (int) ( $quota['max_24_hour_send'] ?? 0 );
|
||||
|
||||
$settings_page = \Robotstxt_SMTP\Admin\Settings_Page::class;
|
||||
|
||||
if ( ! class_exists( $settings_page ) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
$is_network = ROBOTSTXT_SMTP_IS_MULTISITE && $settings_page::is_network_mode_enabled();
|
||||
$option_name = $is_network ? $settings_page::NETWORK_OPTION_NAME : $settings_page::OPTION_NAME;
|
||||
|
||||
$settings = $is_network ? get_site_option( $option_name, array() ) : get_option( $option_name, array() );
|
||||
|
||||
if ( ! is_array( $settings ) ) {
|
||||
$settings = array();
|
||||
}
|
||||
|
||||
$settings['rate_limit_per_second'] = (int) floor( $max_send_rate );
|
||||
$settings['rate_limit_per_hour'] = (int) floor( $max_send_rate * 3600 * 0.9 );
|
||||
$settings['rate_limit_per_day'] = $max_24_hour_send;
|
||||
|
||||
if ( $is_network ) {
|
||||
update_site_option( $option_name, $settings );
|
||||
} else {
|
||||
update_option( $option_name, $settings );
|
||||
}
|
||||
|
||||
if ( defined( 'WP_DEBUG' ) && WP_DEBUG && defined( 'WP_DEBUG_LOG' ) && WP_DEBUG_LOG ) {
|
||||
// phpcs:ignore WordPress.PHP.DevelopmentFunctions.error_log_error_log
|
||||
error_log(
|
||||
sprintf(
|
||||
'ROBOTSTXT SMTP: Updated rate limits from Amazon SES quota - Per second: %d, Per hour: %d, Per day: %d',
|
||||
$settings['rate_limit_per_second'],
|
||||
$settings['rate_limit_per_hour'],
|
||||
$settings['rate_limit_per_day']
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the transient cache key for Amazon SES quota data.
|
||||
*
|
||||
|
|
@ -1682,9 +1696,10 @@ class Plugin {
|
|||
*
|
||||
* @since 1.0.1
|
||||
*
|
||||
* @return array<string, mixed>|false Quota data or false if not cached.
|
||||
* @return array<string|int, mixed>|false Quota data or false if not cached.
|
||||
*/
|
||||
public function get_cached_ses_quota() {
|
||||
return get_site_transient( self::get_quota_cache_key() );
|
||||
public function get_cached_ses_quota(): array|false {
|
||||
$result = \get_site_transient( self::get_quota_cache_key() );
|
||||
return is_array( $result ) ? $result : false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue