PluginProbe ʕ •ᴥ•ʔ
WP 2FA – Two-factor authentication for WordPress / 4.0.0
WP 2FA – Two-factor authentication for WordPress v4.0.0
4.0.0 1.7.1 2.0.0 2.0.1 2.1.0 2.2.0 2.2.1 2.3.0 2.4.0 2.4.1 2.4.2 2.5.0 2.6.0 2.6.1 2.6.2 2.6.3 2.6.4 2.7.0 2.8.0 2.9.0 2.9.1 2.9.2 2.9.3 3.0.0 3.0.1 3.1.0 3.1.1 3.1.1.2 trunk 1.2.0 1.3.0 1.4.0 1.4.1 1.4.2 1.5.0 1.5.1 1.5.2 1.6.0 1.6.1 1.6.2 1.7.0
wp-2fa / includes / classes / Admin / SettingsPages / class-settings-page-email.php
wp-2fa / includes / classes / Admin / SettingsPages Last commit date
class-settings-page-email.php 5 days ago class-settings-page-general.php 5 days ago class-settings-page-new.php 5 days ago class-settings-page-passkeys.php 5 days ago class-settings-page-policies-new.php 5 days ago class-settings-page-policies.php 5 days ago class-settings-page-render.php 5 days ago class-settings-page-white-label.php 5 days ago class-settings-page-white-labeling-new.php 5 days ago class-setup-wizard-new.php 5 days ago index.php 5 days ago
class-settings-page-email.php
646 lines
1 <?php
2 /**
3 * Email settings class.
4 *
5 * @package wp2fa
6 * @subpackage settings-pages
7 * @copyright 2026 Melapress
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\Utils\Debugging;
16 use WP2FA\Admin\Settings_Page;
17 use WP2FA\Utils\Settings_Utils;
18 use WP2FA\Admin\Helpers\WP_Helper;
19 use WP2FA\Admin\Controllers\Settings;
20 use WP2FA\Admin\Helpers\Email_Templates;
21
22 /**
23 * Email settings tab
24 */
25 if ( ! class_exists( '\WP2FA\Admin\SettingsPages\Settings_Page_Email' ) ) {
26 /**
27 * Settings_Page_Email - Class for handling email settings
28 *
29 * @since 2.0.0
30 */
31 class Settings_Page_Email {
32
33 /**
34 * Render the settings
35 *
36 * @return void
37 *
38 * @since 2.0.0
39 */
40 public static function render() {
41 if ( ! \current_user_can( 'manage_options' ) ) {
42 return;
43 }
44
45 \settings_fields( WP_2FA_EMAIL_SETTINGS_NAME );
46 self::email_from_settings();
47 self::email_settings();
48 \submit_button( \esc_html__( 'Save email settings and templates', 'wp-2fa' ) );
49 }
50
51 /**
52 * Handle saving email options to the network main site options.
53 *
54 * @return void
55 *
56 * @since 2.0.0
57 */
58 public static function update_wp2fa_network_options() {
59 if ( ! \current_user_can( 'manage_options' ) ) {
60 return;
61 }
62
63 if ( isset( $_POST['email_from_setting'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification.Missing
64 $options = self::validate_and_sanitize( wp_unslash( $_POST ) ); // phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
65
66 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 WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
67 Settings_Page::set_network_admin_notice( 'error' );
68 // redirect back to our options page.
69 \wp_safe_redirect(
70 \add_query_arg(
71 array(
72 'page' => 'wp-2fa-settings',
73 'tab' => 'email-settings',
74 ),
75 \network_admin_url( 'admin.php' )
76 )
77 );
78 exit;
79 }
80
81 Settings_Utils::update_option( WP_2FA_EMAIL_SETTINGS_NAME, $options );
82 }
83
84 Settings_Page::set_network_admin_notice( 'success' );
85 // redirect back to our options page.
86 \wp_safe_redirect(
87 \add_query_arg(
88 array(
89 'page' => 'wp-2fa-settings',
90 'tab' => 'email-settings',
91 ),
92 \network_admin_url( 'admin.php' )
93 )
94 );
95 exit;
96 }
97
98 /**
99 * Email settings
100 *
101 * @return void
102 *
103 * @since 2.0.0
104 */
105 private static function email_from_settings() {
106 ?>
107 <h3><?php \esc_html_e( 'Which email address should the plugin use as a from address?', 'wp-2fa' ); ?></h3>
108 <p class="description">
109 <?php \esc_html_e( 'Use these settings to customize the "from" name and email address for all correspondence sent from our plugin.', 'wp-2fa' ); ?>
110 </p>
111 <table class="form-table">
112 <tbody>
113 <tr>
114 <th><label for="wp-2fa-method"><?php \esc_html_e( 'From email & name', 'wp-2fa' ); ?></label>
115 </th>
116 <td>
117 <fieldset class="contains-hidden-inputs">
118 <label for="use-defaults">
119 <input type="radio" name="email_from_setting" id="use-defaults" value="use-defaults"
120 <?php \checked( Email_Templates::get_wp2fa_email_templates( 'email_from_setting' ), 'use-defaults' ); ?>
121 >
122 <span><?php \esc_html_e( 'Use the email address ', 'wp-2fa' ); ?> <?php echo Settings_Page::get_default_email_address(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></span>
123 </label>
124 <br/>
125 <label for="use-custom-email">
126 <input type="radio" name="email_from_setting" id="use-custom-email" value="use-custom-email"
127 <?php \checked( Email_Templates::get_wp2fa_email_templates( 'email_from_setting' ), 'use-custom-email' ); ?>
128 data-unhide-when-checked=".custom-from-inputs">
129 <span><?php \esc_html_e( 'Use another email address', 'wp-2fa' ); ?></span>
130 </label>
131 <fieldset class="hidden custom-from-inputs">
132 <p class="description">
133 <?php \esc_html_e( 'A \'From email\' address with a domain different than that of your website domain name, or with a domain that the hosting does not relay might cause the notification emails to be blocked, marked as spam, or not delivered at all. If you are not 100% sure about this change, consult with your web host.', 'wp-2fa' ); ?>
134 </p>
135 <br/>
136 <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( Email_Templates::get_wp2fa_email_templates( 'custom_from_email_address' ) ); ?>"><br><br>
137 <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( Email_Templates::get_wp2fa_email_templates( 'custom_from_display_name' ) ); ?>">
138 </fieldset>
139
140 </fieldset>
141 </td>
142 </tr>
143 </tbody>
144 </table>
145 <div class="description"><i><?php \esc_html_e( 'Tip: The \'From email\' address should match your website domain. If the "from address" does not match your website domain, the emails may be blocked or marked as spam. If you are not sure about this please consult with your website administrator / developer or ', 'wp-2fa' ); ?><a href="<?php echo \esc_url( 'https://melapress.com/contact/?utm_source=plugin&utm_medium=wp2fa&utm_campaign=from_email_address' ); ?>" target="_blank"><?php \esc_html_e( 'contact us', 'wp-2fa' ); ?></a> <?php \esc_html_e( 'for more information.', 'wp-2fa' ); ?></i></div>
146 <br>
147 <hr>
148
149 <h3><?php \esc_html_e( 'Email delivery test', 'wp-2fa' ); ?></h3>
150 <p class="description">
151 <?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' ); ?>
152 </p>
153 <p>
154 <button type="button" name="test_email_config_test"
155 class="button js-button-test-email-trigger"
156 data-email-id="config_test"
157 <?php echo WP_Helper::create_data_nonce( 'wp-2fa-email-test-config_test' ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
158 <?php \esc_html_e( 'Test email delivery', 'wp-2fa' ); ?>
159 </button>
160 </p>
161
162 <br>
163 <hr>
164
165 <?php
166 }
167
168 /**
169 * Creates the email notification definitions.
170 *
171 * @return Email_Template[]
172 *
173 * @since 2.0.0
174 */
175 public static function get_email_notification_definitions() {
176
177 $backup_codes = new Email_Template(
178 'user_backup_codes',
179 \esc_html__( 'User backup codes email', 'wp-2fa' ),
180 \esc_html__( 'This email can be sent to a user once backup codes are generated.', 'wp-2fa' )
181 );
182 $backup_codes->set_can_be_toggled( false );
183
184 $result = array(
185 new Email_Template(
186 'login_code_setup',
187 \esc_html__( '2FA setup code email', 'wp-2fa' ),
188 \esc_html__( 'This is the email sent to a user when setting up 2FA via email.', 'wp-2fa' )
189 ),
190 new Email_Template(
191 'login_code',
192 \esc_html__( 'Login code email', 'wp-2fa' ),
193 \esc_html__( 'This is the email sent to a user when a login code is required.', 'wp-2fa' )
194 ),
195 new Email_Template(
196 'account_locked',
197 \esc_html__( 'User account locked email', 'wp-2fa' ),
198 \esc_html__( 'This is the email sent to a user when their account has been locked.', 'wp-2fa' )
199 ),
200 new Email_Template(
201 'account_unlocked',
202 \esc_html__( 'User account unlocked email', 'wp-2fa' ),
203 \esc_html__( 'This is the email sent to a user when the user\'s account has been unlocked.', 'wp-2fa' )
204 ),
205 $backup_codes,
206 );
207
208 /**
209 * Add an option for external providers to implement their own email template settings for the settings tab.
210 *
211 * @param array $result - The array with all the email templates.
212 *
213 * @since 2.0.0
214 */
215 $result = \apply_filters( WP_2FA_PREFIX . 'email_notification_definitions', $result );
216
217 if ( count( $result ) > 6 ) {
218 $result[0]->set_can_be_toggled( false );
219 $result[1]->set_can_be_toggled( false );
220 $result[2]->set_can_be_toggled( false );
221 $result[3]->set_email_content_id( 'user_account_locked' );
222 $result[4]->set_email_content_id( 'user_account_unlocked' );
223 $result[5]->set_can_be_toggled( false );
224 } else {
225 $result[0]->set_can_be_toggled( false );
226 $result[1]->set_can_be_toggled( false );
227 $result[2]->set_email_content_id( 'user_account_locked' );
228 $result[3]->set_email_content_id( 'user_account_unlocked' );
229 $result[4]->set_can_be_toggled( false );
230 }
231 return $result;
232 }
233
234 /**
235 * Validate email templates before saving
236 *
237 * @since 2.0.0
238 */
239 public static function validate_and_sanitize() {
240
241 // Bail if user doesn't have permissions to be here.
242 if ( ! \current_user_can( 'manage_options' ) ) {
243 return;
244 }
245
246 Debugging::log( 'The following settings will be processed (E-mail): ' . "\n" . wp_json_encode( $_POST ) );
247
248 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 WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
249 die( \esc_html__( 'Nonce verification failed.', 'wp-2fa' ) );
250 }
251
252 $output = array();
253
254 if ( isset( $_POST['email_from_setting'] ) && 'use-defaults' === $_POST['email_from_setting'] || isset( $_POST['email_from_setting'] ) && 'use-custom-email' === $_POST['email_from_setting'] ) {
255 $output['email_from_setting'] = \sanitize_text_field( \wp_unslash( $_POST['email_from_setting'] ) );
256 }
257
258 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'] ) ) {
259 \add_settings_error(
260 WP_2FA_SETTINGS_NAME,
261 \esc_attr( 'email_from_settings_error' ),
262 \esc_html__( 'Please provide an email address', 'wp-2fa' ),
263 'error'
264 );
265 $output['custom_from_email_address'] = '';
266 }
267
268 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'] ) ) {
269 \add_settings_error(
270 WP_2FA_SETTINGS_NAME,
271 \esc_attr( 'display_name_settings_error' ),
272 \esc_html__( 'Please provide a display name.', 'wp-2fa' ),
273 'error'
274 );
275 $output['custom_from_email_address'] = '';
276 }
277
278 if ( isset( $_POST['custom_from_email_address'] ) && ! empty( $_POST['custom_from_email_address'] ) ) {
279 if ( ! filter_var( \wp_unslash( $_POST['custom_from_email_address'] ), FILTER_VALIDATE_EMAIL ) ) {
280 \add_settings_error(
281 WP_2FA_SETTINGS_NAME,
282 \esc_attr( 'email_invalid_settings_error' ),
283 \esc_html__( 'Please provide a valid email address. Your email address has not been updated.', 'wp-2fa' ),
284 'error'
285 );
286 }
287 $output['custom_from_email_address'] = \sanitize_email( \wp_unslash( $_POST['custom_from_email_address'] ) );
288
289 Settings_Utils::delete_option( 'dismiss_notice_mail_domain' );
290 }
291
292 if ( ! isset( $_POST['email_from_setting'] ) ) {
293 Settings_Utils::delete_option( 'dismiss_notice_mail_domain' );
294 }
295
296 if ( isset( $_POST['custom_from_display_name'] ) && ! empty( $_POST['custom_from_display_name'] ) ) {
297 // Check if the string contains HTML/tags.
298 preg_match( "/<\/?\w+((\s+\w+(\s*=\s*(?:\".*?\"|'.*?'|[^'\">\s]+))?)+\s*|\s*)\/?>/", sanitize_text_field( wp_unslash( $_POST['custom_from_display_name'] ) ), $matches );
299 if ( count( $matches ) > 0 ) {
300 \add_settings_error(
301 WP_2FA_SETTINGS_NAME,
302 \esc_attr( 'display_name_invalid_settings_error' ),
303 \esc_html__( 'Please only use alphanumeric text. Your display name has not been updated.', 'wp-2fa' ),
304 'error'
305 );
306 } else {
307 $output['custom_from_display_name'] = \sanitize_text_field( \wp_unslash( $_POST['custom_from_display_name'] ) );
308 }
309 }
310
311 if ( isset( $_POST['login_code_email_subject'] ) ) {
312 $output['login_code_email_subject'] = \wp_kses_post( \wp_unslash( $_POST['login_code_email_subject'] ) );
313 }
314
315 if ( isset( $_POST['login_code_email_body'] ) ) {
316 $output['login_code_email_body'] = \wpautop( \wp_kses_post( \wp_unslash( $_POST['login_code_email_body'] ) ) );
317 }
318
319 if ( isset( $_POST['login_code_setup_email_subject'] ) ) {
320 $output['login_code_setup_email_subject'] = \wp_kses_post( \wp_unslash( $_POST['login_code_setup_email_subject'] ) );
321 }
322
323 if ( isset( $_POST['login_code_setup_email_body'] ) ) {
324 $output['login_code_setup_email_body'] = \wpautop( \wp_kses_post( \wp_unslash( $_POST['login_code_setup_email_body'] ) ) );
325 }
326
327 if ( isset( $_POST['user_account_locked_email_subject'] ) ) {
328 $output['user_account_locked_email_subject'] = \wp_kses_post( \wp_unslash( $_POST['user_account_locked_email_subject'] ) );
329 }
330
331 if ( isset( $_POST['user_account_locked_email_body'] ) ) {
332 $output['user_account_locked_email_body'] = \wpautop( \wp_kses_post( \wp_unslash( $_POST['user_account_locked_email_body'] ) ) );
333 }
334
335 if ( isset( $_POST['user_account_unlocked_email_subject'] ) ) {
336 $output['user_account_unlocked_email_subject'] = \wp_kses_post( \wp_unslash( $_POST['user_account_unlocked_email_subject'] ) );
337 }
338
339 if ( isset( $_POST['user_account_unlocked_email_body'] ) ) {
340 $output['user_account_unlocked_email_body'] = \wpautop( \wp_kses_post( \wp_unslash( $_POST['user_account_unlocked_email_body'] ) ) );
341 }
342
343
344 $output['send_account_locked_email'] = '';
345 if ( isset( $_POST['send_account_locked_email'] ) && 'enable_account_locked_email' === $_POST['send_account_locked_email'] ) {
346 $output['send_account_locked_email'] = \sanitize_text_field( \wp_unslash( $_POST['send_account_locked_email'] ) );
347 }
348
349 $output['send_account_unlocked_email'] = '';
350 if ( isset( $_POST['send_account_unlocked_email'] ) && 'enable_account_unlocked_email' === $_POST['send_account_unlocked_email'] ) {
351 $output['send_account_unlocked_email'] = \sanitize_text_field( \wp_unslash( $_POST['send_account_unlocked_email'] ) );
352 }
353
354 $output['send_login_code_email'] = '';
355 if ( isset( $_POST['send_login_code_email'] ) && 'enable_send_login_code_email' === $_POST['send_login_code_email'] ) {
356 $output['send_login_code_email'] = \sanitize_text_field( \wp_unslash( $_POST['send_login_code_email'] ) );
357 }
358
359 if ( isset( $_POST['user_backup_codes_email_subject'] ) ) {
360 $output['user_backup_codes_email_subject'] = \wp_kses_post( \wp_unslash( $_POST['user_backup_codes_email_subject'] ) );
361 }
362
363 if ( isset( $_POST['user_backup_codes_email_body'] ) ) {
364 $output['user_backup_codes_email_body'] = \wpautop( \wp_kses_post( \wp_unslash( $_POST['user_backup_codes_email_body'] ) ) );
365 }
366
367 /**
368 * Filter the values we are about to store in the plugin settings.
369 *
370 * @param array $output - The output array with all the data we will store in the settings.
371 *
372 * @since 2.0.0
373 */
374 $output = \apply_filters( WP_2FA_PREFIX . 'filter_output_email_template_content', $output );
375
376 Debugging::log( 'The following settings are being saved (E-mail): ' . "\n" . \wp_json_encode( $output ) );
377
378 // 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.
379 global $wp_settings_errors;
380 if ( isset( $wp_settings_errors ) ) {
381 $errors = array_map( 'unserialize', array_unique( array_map( 'serialize', $wp_settings_errors ) ) );
382 $wp_settings_errors = $errors; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
383 }
384
385 if ( isset( $output ) ) {
386 return $output;
387 } else {
388 return;
389 }
390 }
391
392 /**
393 * Validate email templates before saving
394 *
395 * @since 3.1.1.2
396 */
397 public static function validate_and_sanitize_new() {
398
399 // Bail if user doesn't have permissions to be here.
400 if ( ! \current_user_can( 'manage_options' ) ) {
401 return;
402 }
403
404 $output = array();
405
406 if ( isset( $_POST['email_from_setting'] ) && 'use-defaults' === $_POST['email_from_setting'] || isset( $_POST['email_from_setting'] ) && 'use-custom-email' === $_POST['email_from_setting'] ) {
407 $output['email_from_setting'] = \sanitize_text_field( \wp_unslash( $_POST['email_from_setting'] ) );
408 }
409
410 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'] ) ) {
411 \add_settings_error(
412 WP_2FA_SETTINGS_NAME,
413 \esc_attr( 'email_from_settings_error' ),
414 \esc_html__( 'Please provide an email address', 'wp-2fa' ),
415 'error'
416 );
417 $output['custom_from_email_address'] = '';
418 }
419
420 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'] ) ) {
421 \add_settings_error(
422 WP_2FA_SETTINGS_NAME,
423 \esc_attr( 'display_name_settings_error' ),
424 \esc_html__( 'Please provide a display name.', 'wp-2fa' ),
425 'error'
426 );
427 $output['custom_from_email_address'] = '';
428 }
429
430 if ( isset( $_POST['custom_from_email_address'] ) && ! empty( $_POST['custom_from_email_address'] ) ) {
431 if ( ! filter_var( \wp_unslash( $_POST['custom_from_email_address'] ), FILTER_VALIDATE_EMAIL ) ) {
432 \add_settings_error(
433 WP_2FA_SETTINGS_NAME,
434 \esc_attr( 'email_invalid_settings_error' ),
435 \esc_html__( 'Please provide a valid email address. Your email address has not been updated.', 'wp-2fa' ),
436 'error'
437 );
438 }
439 $output['custom_from_email_address'] = \sanitize_email( \wp_unslash( $_POST['custom_from_email_address'] ) );
440
441 Settings_Utils::delete_option( 'dismiss_notice_mail_domain' );
442 }
443
444 if ( ! isset( $_POST['email_from_setting'] ) ) {
445 Settings_Utils::delete_option( 'dismiss_notice_mail_domain' );
446 }
447
448 if ( isset( $_POST['custom_from_display_name'] ) && ! empty( $_POST['custom_from_display_name'] ) ) {
449 // Check if the string contains HTML/tags.
450 preg_match( "/<\/?\w+((\s+\w+(\s*=\s*(?:\".*?\"|'.*?'|[^'\">\s]+))?)+\s*|\s*)\/?>/", sanitize_text_field( wp_unslash( $_POST['custom_from_display_name'] ) ), $matches );
451 if ( count( $matches ) > 0 ) {
452 \add_settings_error(
453 WP_2FA_SETTINGS_NAME,
454 \esc_attr( 'display_name_invalid_settings_error' ),
455 \esc_html__( 'Please only use alphanumeric text. Your display name has not been updated.', 'wp-2fa' ),
456 'error'
457 );
458 } else {
459 $output['custom_from_display_name'] = \sanitize_text_field( \wp_unslash( $_POST['custom_from_display_name'] ) );
460 }
461 }
462
463 if ( isset( $_POST['login_code_email_subject'] ) ) {
464 $output['login_code_email_subject'] = \wp_kses_post( \wp_unslash( $_POST['login_code_email_subject'] ) );
465 }
466
467 if ( isset( $_POST['login_code_email_body'] ) ) {
468 $output['login_code_email_body'] = \wpautop( \wp_kses_post( \wp_unslash( $_POST['login_code_email_body'] ) ) );
469 }
470
471 if ( isset( $_POST['login_code_setup_email_subject'] ) ) {
472 $output['login_code_setup_email_subject'] = \wp_kses_post( \wp_unslash( $_POST['login_code_setup_email_subject'] ) );
473 }
474
475 if ( isset( $_POST['login_code_setup_email_body'] ) ) {
476 $output['login_code_setup_email_body'] = \wpautop( \wp_kses_post( \wp_unslash( $_POST['login_code_setup_email_body'] ) ) );
477 }
478
479 if ( isset( $_POST['user_account_locked_email_subject'] ) ) {
480 $output['user_account_locked_email_subject'] = \wp_kses_post( \wp_unslash( $_POST['user_account_locked_email_subject'] ) );
481 }
482
483 if ( isset( $_POST['user_account_locked_email_body'] ) ) {
484 $output['user_account_locked_email_body'] = \wpautop( \wp_kses_post( \wp_unslash( $_POST['user_account_locked_email_body'] ) ) );
485 }
486
487 if ( isset( $_POST['user_account_unlocked_email_subject'] ) ) {
488 $output['user_account_unlocked_email_subject'] = \wp_kses_post( \wp_unslash( $_POST['user_account_unlocked_email_subject'] ) );
489 }
490
491 if ( isset( $_POST['user_account_unlocked_email_body'] ) ) {
492 $output['user_account_unlocked_email_body'] = \wpautop( \wp_kses_post( \wp_unslash( $_POST['user_account_unlocked_email_body'] ) ) );
493 }
494
495
496 $output['send_account_locked_email'] = '';
497 if ( isset( $_POST['send_account_locked_email'] ) && 'enable_account_locked_email' === $_POST['send_account_locked_email'] ) {
498 $output['send_account_locked_email'] = \sanitize_text_field( \wp_unslash( $_POST['send_account_locked_email'] ) );
499 }
500
501 $output['send_account_unlocked_email'] = '';
502 if ( isset( $_POST['send_account_unlocked_email'] ) && 'enable_account_unlocked_email' === $_POST['send_account_unlocked_email'] ) {
503 $output['send_account_unlocked_email'] = \sanitize_text_field( \wp_unslash( $_POST['send_account_unlocked_email'] ) );
504 }
505
506 $output['send_login_code_email'] = '';
507 if ( isset( $_POST['send_login_code_email'] ) && 'enable_send_login_code_email' === $_POST['send_login_code_email'] ) {
508 $output['send_login_code_email'] = \sanitize_text_field( \wp_unslash( $_POST['send_login_code_email'] ) );
509 }
510
511 if ( isset( $_POST['user_backup_codes_email_subject'] ) ) {
512 $output['user_backup_codes_email_subject'] = \wp_kses_post( \wp_unslash( $_POST['user_backup_codes_email_subject'] ) );
513 }
514
515 if ( isset( $_POST['user_backup_codes_email_body'] ) ) {
516 $output['user_backup_codes_email_body'] = \wpautop( \wp_kses_post( \wp_unslash( $_POST['user_backup_codes_email_body'] ) ) );
517 }
518
519 /**
520 * Filter the values we are about to store in the plugin settings.
521 *
522 * @param array $output - The output array with all the data we will store in the settings.
523 *
524 * @since 2.0.0
525 */
526 $output = \apply_filters( WP_2FA_PREFIX . 'filter_output_email_template_content', $output );
527
528 // 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.
529 global $wp_settings_errors;
530 if ( isset( $wp_settings_errors ) ) {
531 $errors = array_map( 'unserialize', array_unique( array_map( 'serialize', $wp_settings_errors ) ) );
532 $wp_settings_errors = $errors; // phpcs:ignore WordPress.WP.GlobalVariablesOverride.Prohibited
533 }
534
535 if ( isset( $output ) ) {
536 return $output;
537 } else {
538 return;
539 }
540 }
541
542 /**
543 * Email settings
544 *
545 * @return void
546 *
547 * @since 2.0.0
548 */
549 private static function email_settings() {
550 $custom_user_page_id = Settings::check_setting_in_all_roles( 'custom-user-page-id' );
551 if ( empty( $custom_user_page_id ) ) {
552 $custom_user_page_id = Settings::check_setting_in_all_roles( 'custom-user-page-url' );
553 }
554 $email_template_definitions = self::get_email_notification_definitions();
555 ?>
556 <h1><?php \esc_html_e( 'Email Templates', 'wp-2fa' ); ?></h1>
557 <?php foreach ( $email_template_definitions as $email_template ) { ?>
558 <?php $template_id = $email_template->get_id(); ?>
559 <h3><?php echo \esc_html( $email_template->get_title() ); ?></h3>
560 <p class="description"><?php echo $email_template->get_description(); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?></p>
561 <table class="form-table">
562 <tbody>
563 <?php if ( $email_template->can_be_toggled() ) { ?>
564 <tr>
565 <th><label for="send_<?php echo \esc_attr( $template_id ); ?>_email"><?php \esc_html_e( 'Send this email', 'wp-2fa' ); ?></label></th>
566 <td>
567 <fieldset>
568 <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"
569 <?php \checked( 'enable_' . $template_id . '_email', Email_Templates::get_wp2fa_email_templates( 'send_' . $template_id . '_email' ) ); ?>
570 >
571 <label for="send_<?php echo \esc_attr( $template_id ); ?>_email"><?php \esc_html_e( 'Uncheck to disable this message.', 'wp-2fa' ); ?></label>
572 </fieldset>
573 </td>
574 </tr>
575 <?php } ?>
576 <?php $template_id = $email_template->get_email_content_id(); ?>
577 <tr>
578 <th><label for="<?php echo \esc_attr( $template_id ); ?>_email_subject"><?php \esc_html_e( 'Email subject', 'wp-2fa' ); ?></label></th>
579 <td>
580 <fieldset>
581 <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( Email_Templates::get_wp2fa_email_templates( $template_id . '_email_subject' ) ); ?>">
582 </fieldset>
583 </td>
584 </tr>
585 <tr>
586 <th>
587 <label for="<?php echo \esc_attr( $template_id ); ?>_email_body"><?php \esc_html_e( 'Email body', 'wp-2fa' ); ?></label>
588 </br>
589 <label for="<?php echo \esc_attr( $template_id ); ?>_email_tags" style="font-weight: 400;"><?php \esc_html_e( 'Available template tags:', 'wp-2fa' ); ?></label>
590 </br>
591 </br>
592 <span style="font-weight: 400;">
593 {site_url}</br>
594 {site_name}</br>
595 {grace_period}</br>
596 {user_login_name}</br>
597 {user_first_name}</br>
598 {user_last_name}</br>
599 {user_display_name}</br>
600 {login_code}</br>
601 {user_ip_address}</br>
602 {backup_codes}
603 {admin_email}
604 {wp_admin_email}
605 <?php
606 if ( ! empty( $custom_user_page_id ) ) {
607 echo '</br>{2fa_settings_page_url}';
608 }
609 ?>
610 </span>
611 </th>
612 <td>
613 <fieldset>
614 <?php
615 $message = Email_Templates::get_wp2fa_email_templates( $template_id . '_email_body' );
616 $content = $message;
617 $editor_id = $template_id . '_email_body';
618 $settings = array(
619 'media_buttons' => false,
620 'editor_height' => 200,
621 );
622 \wp_editor( $content, $editor_id, $settings );
623 ?>
624 </fieldset>
625 <p>
626 <button type="button" name="test_email_<?php echo \esc_attr( $template_id ); ?>"
627 class="button js-button-test-email-trigger"
628 data-email-id="<?php echo \esc_attr( $template_id ); ?>"
629 <?php echo WP_Helper::create_data_nonce( 'wp-2fa-email-test-' . $template_id ); // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?>>
630 <?php \esc_html_e( 'Send test email', 'wp-2fa' ); ?>
631 </button>
632 </p>
633 </td>
634 </tr>
635 </tbody>
636 </table>
637 <br>
638 <hr>
639 <?php } ?>
640 <?php
641 $additional_content = \apply_filters( WP_2FA_PREFIX . 'append_to_email_and_sms_template_settings', '' );
642 echo \wp_kses_post( $additional_content );
643 }
644 }
645 }
646