class-settings-page-email.php
3 years ago
class-settings-page-general.php
3 years ago
class-settings-page-policies.php
3 years ago
class-settings-page-white-label.php
3 years ago
class-settings-page-email.php
435 lines
| 1 | <?php |
| 2 | /** |
| 3 | * Email settings class. |
| 4 | * |
| 5 | * @package wp2fa |
| 6 | * @subpackage settings-pages |
| 7 | * @copyright 2023 WP White Security |
| 8 | * @license https://www.apache.org/licenses/LICENSE-2.0 Apache License 2.0 |
| 9 | * @link https://wordpress.org/plugins/wp-2fa/ |
| 10 | */ |
| 11 | |
| 12 | namespace WP2FA\Admin\SettingsPages; |
| 13 | |
| 14 | use WP2FA\Email_Template; |
| 15 | use \WP2FA\WP2FA as WP2FA; |
| 16 | use WP2FA\Utils\Debugging; |
| 17 | use WP2FA\Admin\Controllers\Settings; |
| 18 | use WP2FA\Utils\Settings_Utils as Settings_Utils; |
| 19 | |
| 20 | /** |
| 21 | * Email settings tab |
| 22 | */ |
| 23 | if ( ! class_exists( '\WP2FA\Admin\SettingsPages\Settings_Page_Email' ) ) { |
| 24 | /** |
| 25 | * Settings_Page_Email - Class for handling email settings |
| 26 | * |
| 27 | * @since 2.0.0 |
| 28 | */ |
| 29 | class Settings_Page_Email { |
| 30 | |
| 31 | /** |
| 32 | * Render the settings |
| 33 | * |
| 34 | * @return void |
| 35 | * |
| 36 | * @since 2.0.0 |
| 37 | */ |
| 38 | public static function render() { |
| 39 | settings_fields( WP_2FA_EMAIL_SETTINGS_NAME ); |
| 40 | self::email_from_settings(); |
| 41 | self::email_settings(); |
| 42 | submit_button( esc_html__( 'Save email settings and templates', 'wp-2fa' ) ); |
| 43 | } |
| 44 | |
| 45 | /** |
| 46 | * Handle saving email options to the network main site options. |
| 47 | * |
| 48 | * @return void |
| 49 | * |
| 50 | * @since 2.0.0 |
| 51 | * |
| 52 | * @SuppressWarnings(PHPMD.ExitExpressions) |
| 53 | */ |
| 54 | public static function update_wp2fa_network_options() { |
| 55 | if ( isset( $_POST['email_from_setting'] ) ) { // phpcs:ignore |
| 56 | $options = self::validate_and_sanitize( wp_unslash( $_POST ) ); // phpcs:ignore |
| 57 | |
| 58 | if ( isset( $_POST['email_from_setting'] ) && 'use-custom-email' === $_POST['email_from_setting'] && isset( $_POST['custom_from_display_name'] ) && empty( $_POST['custom_from_display_name'] ) || isset( $_POST['email_from_setting'] ) && 'use-custom-email' === $_POST['email_from_setting'] && isset( $_POST['custom_from_email_address'] ) && empty( $_POST['custom_from_email_address'] ) ) { // phpcs:ignore |
| 59 | // redirect back to our options page. |
| 60 | wp_safe_redirect( |
| 61 | add_query_arg( |
| 62 | array( |
| 63 | 'page' => 'wp-2fa-settings', |
| 64 | 'wp_2fa_network_settings_updated' => 'false', |
| 65 | 'tab' => 'email-settings', |
| 66 | ), |
| 67 | network_admin_url( 'admin.php' ) |
| 68 | ) |
| 69 | ); |
| 70 | exit; |
| 71 | } |
| 72 | |
| 73 | Settings_Utils::update_option( WP_2FA_EMAIL_SETTINGS_NAME, $options ); |
| 74 | } |
| 75 | |
| 76 | // redirect back to our options page. |
| 77 | wp_safe_redirect( |
| 78 | add_query_arg( |
| 79 | array( |
| 80 | 'page' => 'wp-2fa-settings', |
| 81 | 'wp_2fa_network_settings_updated' => 'true', |
| 82 | 'tab' => 'email-settings', |
| 83 | ), |
| 84 | network_admin_url( 'admin.php' ) |
| 85 | ) |
| 86 | ); |
| 87 | exit; |
| 88 | } |
| 89 | |
| 90 | /** |
| 91 | * Email settings |
| 92 | * |
| 93 | * @return void |
| 94 | * |
| 95 | * @since 2.0.0 |
| 96 | */ |
| 97 | private static function email_from_settings() { |
| 98 | ?> |
| 99 | <h3><?php esc_html_e( 'Which email address should the plugin use as a from address?', 'wp-2fa' ); ?></h3> |
| 100 | <p class="description"> |
| 101 | <?php esc_html_e( 'Use these settings to customize the "from" name and email address for all correspondence sent from our plugin.', 'wp-2fa' ); ?> |
| 102 | </p> |
| 103 | <table class="form-table"> |
| 104 | <tbody> |
| 105 | <tr> |
| 106 | <th><label for="2fa-method"><?php esc_html_e( 'From email & name', 'wp-2fa' ); ?></label> |
| 107 | </th> |
| 108 | <td> |
| 109 | <fieldset class="contains-hidden-inputs"> |
| 110 | <label for="use-defaults"> |
| 111 | <input type="radio" name="email_from_setting" id="use-defaults" value="use-defaults" |
| 112 | <?php checked( WP2FA::get_wp2fa_email_templates( 'email_from_setting' ), 'use-defaults' ); ?> |
| 113 | > |
| 114 | <span><?php esc_html_e( 'Use the email address from the WordPress general settings.', 'wp-2fa' ); ?></span> |
| 115 | </label> |
| 116 | |
| 117 | <br/> |
| 118 | <label for="use-custom-email"> |
| 119 | <input type="radio" name="email_from_setting" id="use-custom-email" value="use-custom-email" |
| 120 | <?php checked( WP2FA::get_wp2fa_email_templates( 'email_from_setting' ), 'use-custom-email' ); ?> |
| 121 | data-unhide-when-checked=".custom-from-inputs"> |
| 122 | <span><?php esc_html_e( 'Use another email address', 'wp-2fa' ); ?></span> |
| 123 | </label> |
| 124 | <fieldset class="hidden custom-from-inputs"> |
| 125 | <br/> |
| 126 | <span><?php esc_html_e( 'Email Address:', 'wp-2fa' ); ?></span> <input type="text" id="custom_from_email_address" name="custom_from_email_address" value="<?php echo esc_attr( WP2FA::get_wp2fa_email_templates( 'custom_from_email_address' ) ); ?>"><br><br> |
| 127 | <span><?php esc_html_e( 'Display Name:', 'wp-2fa' ); ?></span> <input type="text" id="custom_from_display_name" name="custom_from_display_name" value="<?php echo esc_attr( WP2FA::get_wp2fa_email_templates( 'custom_from_display_name' ) ); ?>"> |
| 128 | </fieldset> |
| 129 | |
| 130 | </fieldset> |
| 131 | </td> |
| 132 | </tr> |
| 133 | </tbody> |
| 134 | </table> |
| 135 | |
| 136 | <br> |
| 137 | <hr> |
| 138 | |
| 139 | <h3><?php esc_html_e( 'Email delivery test', 'wp-2fa' ); ?></h3> |
| 140 | <p class="description"> |
| 141 | <?php esc_html_e( 'The plugin sends emails with one-time codes, blocked account notifications and more. Use the button below to confirm the plugin can successfully send emails.', 'wp-2fa' ); ?> |
| 142 | </p> |
| 143 | <p> |
| 144 | <button type="button" name="test_email_config_test" |
| 145 | class="button js-button-test-email-trigger" |
| 146 | data-email-id="config_test" |
| 147 | data-nonce="<?php echo esc_attr( wp_create_nonce( 'wp-2fa-email-test-config_test' ) ); ?>"> |
| 148 | <?php esc_html_e( 'Test email delivery', 'wp-2fa' ); ?> |
| 149 | </button> |
| 150 | </p> |
| 151 | |
| 152 | <br> |
| 153 | <hr> |
| 154 | |
| 155 | <?php |
| 156 | } |
| 157 | |
| 158 | /** |
| 159 | * Creates the email notification definitions. |
| 160 | * |
| 161 | * @return Email_Template[] |
| 162 | * |
| 163 | * @since 2.0.0 |
| 164 | */ |
| 165 | public static function get_email_notification_definitions() { |
| 166 | $result = array( |
| 167 | new Email_Template( |
| 168 | 'login_code', |
| 169 | esc_html__( 'Login code email', 'wp-2fa' ), |
| 170 | esc_html__( 'This is the email sent to a user when a login code is required.', 'wp-2fa' ) |
| 171 | ), |
| 172 | new Email_Template( |
| 173 | 'account_locked', |
| 174 | esc_html__( 'User account locked email', 'wp-2fa' ), |
| 175 | esc_html__( 'This is the email sent to a user upon grace period expiry.', 'wp-2fa' ) |
| 176 | ), |
| 177 | new Email_Template( |
| 178 | 'account_unlocked', |
| 179 | esc_html__( 'User account unlocked email', 'wp-2fa' ), |
| 180 | esc_html__( 'This is the email sent to a user when the user\'s account has been unlocked.', 'wp-2fa' ) |
| 181 | ), |
| 182 | ); |
| 183 | |
| 184 | /** |
| 185 | * Add an option for external providers to implement their own email template settings for the settings tab. |
| 186 | * |
| 187 | * @param array $result - The array with all the email templates. |
| 188 | * |
| 189 | * @since 2.0.0 |
| 190 | */ |
| 191 | $result = apply_filters( WP_2FA_PREFIX . 'email_notification_definitions', $result ); |
| 192 | |
| 193 | if ( count( $result ) > 3 ) { |
| 194 | $result[0]->set_can_be_toggled( false ); |
| 195 | $result[1]->set_can_be_toggled( false ); |
| 196 | $result[2]->set_email_content_id( 'user_account_locked' ); |
| 197 | $result[3]->set_email_content_id( 'user_account_unlocked' ); |
| 198 | } else { |
| 199 | $result[0]->set_can_be_toggled( false ); |
| 200 | $result[1]->set_email_content_id( 'user_account_locked' ); |
| 201 | $result[2]->set_email_content_id( 'user_account_unlocked' ); |
| 202 | } |
| 203 | return $result; |
| 204 | } |
| 205 | |
| 206 | /** |
| 207 | * Validate email templates before saving |
| 208 | * |
| 209 | * @since 2.0.0 |
| 210 | * |
| 211 | * @SuppressWarnings(PHPMD.ExitExpressions) |
| 212 | */ |
| 213 | public static function validate_and_sanitize() { |
| 214 | |
| 215 | // Bail if user doesn't have permissions to be here. |
| 216 | if ( ! current_user_can( 'manage_options' ) ) { |
| 217 | return; |
| 218 | } |
| 219 | |
| 220 | Debugging::log( 'The following settings will be processed (E-mail): ' . "\n" . wp_json_encode( $_POST ) ); // phpcs:ignore |
| 221 | |
| 222 | if ( empty( $_POST ) || ! isset( $_POST['_wpnonce'] ) || empty( $_POST['_wpnonce'] ) || ! wp_verify_nonce( $_POST['_wpnonce'], WP_2FA_PREFIX . 'email_settings-options' ) && ! wp_verify_nonce( $_POST['_wpnonce'], WP_2FA_PREFIX . 'settings-options' ) || ! wp_verify_nonce( $_POST['_wpnonce'], WP_2FA_PREFIX . 'email_settings-options' ) && ! wp_verify_nonce( $_POST['_wpnonce'], WP_2FA_PREFIX . 'settings-options' ) ) { // phpcs:ignore |
| 223 | die( esc_html__( 'Nonce verification failed.', 'wp-2fa' ) ); |
| 224 | } |
| 225 | |
| 226 | $output = array(); |
| 227 | |
| 228 | if ( isset( $_POST['email_from_setting'] ) && 'use-defaults' === $_POST['email_from_setting'] || isset( $_POST['email_from_setting'] ) && 'use-custom-email' === $_POST['email_from_setting'] ) { |
| 229 | $output['email_from_setting'] = sanitize_text_field( wp_unslash( $_POST['email_from_setting'] ) ); |
| 230 | } |
| 231 | |
| 232 | if ( isset( $_POST['email_from_setting'] ) && 'use-custom-email' === $_POST['email_from_setting'] && isset( $_POST['custom_from_email_address'] ) && empty( $_POST['custom_from_email_address'] ) ) { |
| 233 | add_settings_error( |
| 234 | WP_2FA_SETTINGS_NAME, |
| 235 | esc_attr( 'email_from_settings_error' ), |
| 236 | esc_html__( 'Please provide an email address', 'wp-2fa' ), |
| 237 | 'error' |
| 238 | ); |
| 239 | $output['custom_from_email_address'] = ''; |
| 240 | } |
| 241 | |
| 242 | if ( isset( $_POST['email_from_setting'] ) && 'use-custom-email' === $_POST['email_from_setting'] && isset( $_POST['custom_from_display_name'] ) && empty( $_POST['custom_from_display_name'] ) ) { |
| 243 | add_settings_error( |
| 244 | WP_2FA_SETTINGS_NAME, |
| 245 | esc_attr( 'display_name_settings_error' ), |
| 246 | esc_html__( 'Please provide a display name.', 'wp-2fa' ), |
| 247 | 'error' |
| 248 | ); |
| 249 | $output['custom_from_email_address'] = ''; |
| 250 | } |
| 251 | |
| 252 | if ( isset( $_POST['custom_from_email_address'] ) && ! empty( $_POST['custom_from_email_address'] ) ) { |
| 253 | if ( ! filter_var( wp_unslash( $_POST['custom_from_email_address'] ), FILTER_VALIDATE_EMAIL ) ) { |
| 254 | add_settings_error( |
| 255 | WP_2FA_SETTINGS_NAME, |
| 256 | esc_attr( 'email_invalid_settings_error' ), |
| 257 | esc_html__( 'Please provide a valid email address. Your email address has not been updated.', 'wp-2fa' ), |
| 258 | 'error' |
| 259 | ); |
| 260 | } |
| 261 | $output['custom_from_email_address'] = sanitize_email( wp_unslash( $_POST['custom_from_email_address'] ) ); |
| 262 | } |
| 263 | |
| 264 | if ( isset( $_POST['custom_from_display_name'] ) && ! empty( $_POST['custom_from_display_name'] ) ) { |
| 265 | // Check if the string contains HTML/tags. |
| 266 | preg_match( "/<\/?\w+((\s+\w+(\s*=\s*(?:\".*?\"|'.*?'|[^'\">\s]+))?)+\s*|\s*)\/?>/", sanitize_text_field( wp_unslash( $_POST['custom_from_display_name'] ) ), $matches ); |
| 267 | if ( count( $matches ) > 0 ) { |
| 268 | add_settings_error( |
| 269 | WP_2FA_SETTINGS_NAME, |
| 270 | esc_attr( 'display_name_invalid_settings_error' ), |
| 271 | esc_html__( 'Please only use alphanumeric text. Your display name has not been updated.', 'wp-2fa' ), |
| 272 | 'error' |
| 273 | ); |
| 274 | } else { |
| 275 | $output['custom_from_display_name'] = sanitize_text_field( wp_unslash( $_POST['custom_from_display_name'] ) ); |
| 276 | } |
| 277 | } |
| 278 | |
| 279 | if ( isset( $_POST['login_code_email_subject'] ) ) { |
| 280 | $output['login_code_email_subject'] = wp_kses_post( wp_unslash( $_POST['login_code_email_subject'] ) ); |
| 281 | } |
| 282 | |
| 283 | if ( isset( $_POST['login_code_email_body'] ) ) { |
| 284 | $output['login_code_email_body'] = wpautop( wp_kses_post( wp_unslash( $_POST['login_code_email_body'] ) ) ); |
| 285 | } |
| 286 | |
| 287 | if ( isset( $_POST['user_account_locked_email_subject'] ) ) { |
| 288 | $output['user_account_locked_email_subject'] = wp_kses_post( wp_unslash( $_POST['user_account_locked_email_subject'] ) ); |
| 289 | } |
| 290 | |
| 291 | if ( isset( $_POST['user_account_locked_email_body'] ) ) { |
| 292 | $output['user_account_locked_email_body'] = wpautop( wp_kses_post( wp_unslash( $_POST['user_account_locked_email_body'] ) ) ); |
| 293 | } |
| 294 | |
| 295 | if ( isset( $_POST['user_account_unlocked_email_subject'] ) ) { |
| 296 | $output['user_account_unlocked_email_subject'] = wp_kses_post( wp_unslash( $_POST['user_account_unlocked_email_subject'] ) ); |
| 297 | } |
| 298 | |
| 299 | if ( isset( $_POST['user_account_unlocked_email_body'] ) ) { |
| 300 | $output['user_account_unlocked_email_body'] = wpautop( wp_kses_post( wp_unslash( $_POST['user_account_unlocked_email_body'] ) ) ); |
| 301 | } |
| 302 | |
| 303 | $output['send_account_locked_email'] = ''; |
| 304 | if ( isset( $_POST['send_account_locked_email'] ) && 'enable_account_locked_email' === $_POST['send_account_locked_email'] ) { |
| 305 | $output['send_account_locked_email'] = sanitize_text_field( wp_unslash( $_POST['send_account_locked_email'] ) ); |
| 306 | } |
| 307 | |
| 308 | $output['send_account_unlocked_email'] = ''; |
| 309 | if ( isset( $_POST['send_account_unlocked_email'] ) && 'enable_account_unlocked_email' === $_POST['send_account_unlocked_email'] ) { |
| 310 | $output['send_account_unlocked_email'] = sanitize_text_field( wp_unslash( $_POST['send_account_unlocked_email'] ) ); |
| 311 | } |
| 312 | |
| 313 | /** |
| 314 | * Filter the values we are about to store in the plugin settings. |
| 315 | * |
| 316 | * @param array $output - The output array with all the data we will store in the settings. |
| 317 | * |
| 318 | * @since 2.0.0 |
| 319 | */ |
| 320 | $output = apply_filters( WP_2FA_PREFIX . 'filter_output_email_template_content', $output ); |
| 321 | |
| 322 | Debugging::log( 'The following settings are being saved (E-mail): ' . "\n" . wp_json_encode( $output ) ); |
| 323 | |
| 324 | // Remove duplicates from settings errors. We do this as this sanitization callback is actually fired twice, so we end up with duplicates when saving the settings for the FIRST TIME only. The issue is not present once the settings are in the DB as the sanitization wont fire again. For details on this core issue - https://core.trac.wordpress.org/ticket/21989. |
| 325 | global $wp_settings_errors; |
| 326 | if ( isset( $wp_settings_errors ) ) { |
| 327 | $errors = array_map( 'unserialize', array_unique( array_map( 'serialize', $wp_settings_errors ) ) ); |
| 328 | $wp_settings_errors = $errors; // phpcs:ignore |
| 329 | } |
| 330 | |
| 331 | if ( isset( $output ) ) { |
| 332 | return $output; |
| 333 | } else { |
| 334 | return; |
| 335 | } |
| 336 | } |
| 337 | |
| 338 | /** |
| 339 | * Email settings |
| 340 | * |
| 341 | * @return void |
| 342 | * |
| 343 | * @since 2.0.0 |
| 344 | */ |
| 345 | private static function email_settings() { |
| 346 | $custom_user_page_id = Settings::check_setting_in_all_roles( 'custom-user-page-id' ); |
| 347 | $email_template_definitions = self::get_email_notification_definitions(); |
| 348 | ?> |
| 349 | <h1><?php esc_html_e( 'Email Templates', 'wp-2fa' ); ?></h1> |
| 350 | <?php foreach ( $email_template_definitions as $email_template ) : ?> |
| 351 | <?php $template_id = $email_template->get_id(); ?> |
| 352 | <h3><?php echo esc_html( $email_template->get_title() ); ?></h3> |
| 353 | <p class="description"><?php echo $email_template->get_description(); // phpcs:ignore ?></p> |
| 354 | <table class="form-table"> |
| 355 | <tbody> |
| 356 | <?php if ( $email_template->can_be_toggled() ) : ?> |
| 357 | <tr> |
| 358 | <th><label for="send_<?php echo esc_attr( $template_id ); ?>_email"><?php esc_html_e( 'Send this email', 'wp-2fa' ); ?></label></th> |
| 359 | <td> |
| 360 | <fieldset> |
| 361 | <input type="checkbox" id="send_<?php echo esc_attr( $template_id ); ?>_email" name="send_<?php echo esc_attr( $template_id ); ?>_email" value="enable_<?php echo esc_attr( $template_id ); ?>_email" |
| 362 | <?php checked( 'enable_' . $template_id . '_email', WP2FA::get_wp2fa_email_templates( 'send_' . $template_id . '_email' ) ); ?> |
| 363 | > |
| 364 | <label for="send_<?php echo esc_attr( $template_id ); ?>_email"><?php esc_html_e( 'Uncheck to disable this message.', 'wp-2fa' ); ?></label> |
| 365 | </fieldset> |
| 366 | </td> |
| 367 | </tr> |
| 368 | <?php endif; ?> |
| 369 | <?php $template_id = $email_template->get_email_content_id(); ?> |
| 370 | <tr> |
| 371 | <th><label for="<?php echo esc_attr( $template_id ); ?>_email_subject"><?php esc_html_e( 'Email subject', 'wp-2fa' ); ?></label></th> |
| 372 | <td> |
| 373 | <fieldset> |
| 374 | <input type="text" id="<?php echo esc_attr( $template_id ); ?>_email_subject" name="<?php echo esc_attr( $template_id ); ?>_email_subject" class="large-text" value="<?php echo esc_attr( WP2FA::get_wp2fa_email_templates( $template_id . '_email_subject' ) ); ?>"> |
| 375 | </fieldset> |
| 376 | </td> |
| 377 | </tr> |
| 378 | <tr> |
| 379 | <th> |
| 380 | <label for="<?php echo esc_attr( $template_id ); ?>_email_body"><?php esc_html_e( 'Email body', 'wp-2fa' ); ?></label> |
| 381 | </br> |
| 382 | <label for="<?php echo esc_attr( $template_id ); ?>_email_tags" style="font-weight: 400;"><?php esc_html_e( 'Available template tags:', 'wp-2fa' ); ?></label> |
| 383 | </br> |
| 384 | </br> |
| 385 | <span style="font-weight: 400;"> |
| 386 | {site_url}</br> |
| 387 | {site_name}</br> |
| 388 | {grace_period}</br> |
| 389 | {user_login_name}</br> |
| 390 | {user_first_name}</br> |
| 391 | {user_last_name}</br> |
| 392 | {user_display_name}</br> |
| 393 | {login_code}</br> |
| 394 | {user_ip_address} |
| 395 | <?php |
| 396 | if ( ! empty( $custom_user_page_id ) ) { |
| 397 | echo '</br>{2fa_settings_page_url}'; |
| 398 | } |
| 399 | ?> |
| 400 | </span> |
| 401 | </th> |
| 402 | <td> |
| 403 | <fieldset> |
| 404 | <?php |
| 405 | $message = WP2FA::get_wp2fa_email_templates( $template_id . '_email_body' ); |
| 406 | $content = $message; |
| 407 | $editor_id = $template_id . '_email_body'; |
| 408 | $settings = array( |
| 409 | 'media_buttons' => false, |
| 410 | 'editor_height' => 200, |
| 411 | ); |
| 412 | wp_editor( $content, $editor_id, $settings ); |
| 413 | ?> |
| 414 | </fieldset> |
| 415 | <p> |
| 416 | <button type="button" name="test_email_<?php echo esc_attr( $template_id ); ?>" |
| 417 | class="button js-button-test-email-trigger" |
| 418 | data-email-id="<?php echo esc_attr( $template_id ); ?>" |
| 419 | data-nonce="<?php echo esc_attr( wp_create_nonce( 'wp-2fa-email-test-' . $template_id ) ); ?>"> |
| 420 | <?php esc_html_e( 'Send test email', 'wp-2fa' ); ?> |
| 421 | </button> |
| 422 | </p> |
| 423 | </td> |
| 424 | </tr> |
| 425 | </tbody> |
| 426 | </table> |
| 427 | |
| 428 | <br> |
| 429 | <hr> |
| 430 | <?php endforeach; ?> |
| 431 | <?php |
| 432 | } |
| 433 | } |
| 434 | } |
| 435 |