From 9b0a58747d9f3268c4b653de015a65f499e2de04 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Tue, 26 Aug 2025 14:55:29 +0200 Subject: [PATCH 01/10] WIP --- .../check-email-dns-records.js | 13 + .../suggested-tasks/class-tasks-manager.php | 2 + .../class-check-email-dns-records.php | 227 ++++++++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 assets/js/recommendations/check-email-dns-records.js create mode 100644 classes/suggested-tasks/providers/class-check-email-dns-records.php diff --git a/assets/js/recommendations/check-email-dns-records.js b/assets/js/recommendations/check-email-dns-records.js new file mode 100644 index 000000000..a60111f64 --- /dev/null +++ b/assets/js/recommendations/check-email-dns-records.js @@ -0,0 +1,13 @@ +/* global prplInteractiveTaskFormListener */ + +/* + * Set the site timezone. + * + * Dependencies: progress-planner/recommendations/interactive-task + */ + +prplInteractiveTaskFormListener.settings( { + taskId: 'check-email-dns-records', + popoverId: 'prpl-popover-check-email-dns-records', + action: 'prpl_interactive_task_submit_check-email-dns-records', +} ); diff --git a/classes/suggested-tasks/class-tasks-manager.php b/classes/suggested-tasks/class-tasks-manager.php index 6a7c4fdbd..f007480fe 100644 --- a/classes/suggested-tasks/class-tasks-manager.php +++ b/classes/suggested-tasks/class-tasks-manager.php @@ -35,6 +35,7 @@ use Progress_Planner\Suggested_Tasks\Providers\Unpublished_Content; use Progress_Planner\Suggested_Tasks\Providers\Collaborator; use Progress_Planner\Suggested_Tasks\Providers\Select_Timezone; +use Progress_Planner\Suggested_Tasks\Providers\Check_Email_DNS_Records; /** * Tasks_Manager class. @@ -80,6 +81,7 @@ public function __construct() { new Unpublished_Content(), new Collaborator(), new Select_Timezone(), + new Check_Email_DNS_Records(), ]; // Add the plugin integration. diff --git a/classes/suggested-tasks/providers/class-check-email-dns-records.php b/classes/suggested-tasks/providers/class-check-email-dns-records.php new file mode 100644 index 000000000..519721bba --- /dev/null +++ b/classes/suggested-tasks/providers/class-check-email-dns-records.php @@ -0,0 +1,227 @@ +get_activities__query()->query_activities( + [ + 'category' => 'suggested_task', + 'data_id' => static::PROVIDER_ID, + ] + ); + + return ! $email_dns_records_activity; + } + + /** + * Get the popover instructions. + * + * @return void + */ + public function print_popover_instructions() { + echo '

'; + \esc_html_e( 'Check the email DNS records to ensure they are configured correctly.', 'progress-planner' ); + echo '

'; + } + + /** + * Print the popover input field for the form. + * + * @return void + */ + public function print_popover_form_contents() { + + ?> + + \esc_html__( 'Invalid nonce.', 'progress-planner' ) ] ); + } + + $site = \get_site_url(); + + // Get a nonce from the remote server. + $nonce_request = wp_remote_post( + \progress_planner()->get_remote_server_root_url() . '/wp-json/progress-planner-saas/v1/get-nonce', + [ + 'body' => [ + 'site' => $site, + ], + ] + ); + + if ( is_wp_error( $nonce_request ) || 200 !== wp_remote_retrieve_response_code( $nonce_request ) ) { + \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to get nonce.', 'progress-planner' ) ] ); + } + + $nonce_response = \json_decode( wp_remote_retrieve_body( $nonce_request ), true ); + $remote_nonce = $nonce_response['nonce'] ?? ''; + + // TODO: Tell server which email are we going to send, response should be email address. + $subject = \get_bloginfo( 'name' ) . ' - ' . \microtime( true ); + + $pre_request = wp_remote_post( + \progress_planner()->get_remote_server_root_url() . '/wp-json/progress-planner-saas/v1/register-email-for-dns-check', + [ + 'body' => [ + 'nonce' => $remote_nonce, + 'site' => $site, + 'subject' => $subject, + ], + ] + ); + + if ( is_wp_error( $pre_request ) || 200 !== wp_remote_retrieve_response_code( $pre_request ) ) { + \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to send test email.', 'progress-planner' ) ] ); + } + + $pre_request_response = \json_decode( wp_remote_retrieve_body( $pre_request ), true ); + $email_address = $pre_request_response['email_address'] ?? ''; + + // Send the email. + $email_sent = wp_mail( $email_address, $subject, '' ); + + // TODO: If wp_mail returned false we need to tell the server to not check for the email. + if ( ! $email_sent ) { + // TODO: Tell server that the email was not sent. + + \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to send email.', 'progress-planner' ) ] ); + } + + // TODO: Sleep for 10 seconds, wait for the report to be ready. + sleep( 10 ); + + $dns_check_request = wp_remote_get( + \progress_planner()->get_remote_server_root_url() . '/wp-json/progress-planner-saas/v1/check-email-dns-records', + [ + 'body' => [ + 'nonce' => $remote_nonce, + 'site' => $site, + 'subject' => $subject, + ], + ] + ); + + if ( is_wp_error( $dns_check_request ) || 200 !== wp_remote_retrieve_response_code( $dns_check_request ) ) { + \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to check email DNS records.', 'progress-planner' ) ] ); + } + + $dns_check_response = \json_decode( wp_remote_retrieve_body( $dns_check_request ), true ); + $dns_records_status = $dns_check_response['dns_records_status'] ?? false; + $spam_score = $dns_check_response['spam_score'] ?? false; // Lower is better. + + // TODO: If the report is still being processed, we need to let the user know and save the email subject for later. + // Most likely we will fire another AJAX request (for example up to 5 times) to check if the report is ready. + + // TODO: Handle different statuses, ie SPF set correctly, DKIM is not set, etc. + if ( $dns_records_status && $spam_score ) { + + // We're not checking for the return value of the update_option calls, because it will return false if the value is the same (for example if gmt_offset is already set to ''). + \wp_send_json_success( [ 'message' => \esc_html__( 'Email DNS records checked successfully.', 'progress-planner' ) ] ); + } + + \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to check email DNS records.', 'progress-planner' ) ] ); + } +} From d8af0315b5c275650507c2936bb5e1f1c78c732b Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Tue, 18 Nov 2025 14:17:21 +0100 Subject: [PATCH 02/10] update API endpoints --- .../providers/class-check-email-dns-records.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/classes/suggested-tasks/providers/class-check-email-dns-records.php b/classes/suggested-tasks/providers/class-check-email-dns-records.php index 519721bba..002fed7fa 100644 --- a/classes/suggested-tasks/providers/class-check-email-dns-records.php +++ b/classes/suggested-tasks/providers/class-check-email-dns-records.php @@ -135,6 +135,11 @@ public function print_popover_form_contents() { * @return void */ public function handle_interactive_task_specific_submit() { + + if ( ! $this->capability_required() ) { + \wp_send_json_error( [ 'message' => \esc_html__( 'You do not have permission to check email DNS records.', 'progress-planner' ) ] ); + } + // Check the nonce. if ( ! \check_ajax_referer( 'progress_planner', 'nonce', false ) ) { \wp_send_json_error( [ 'message' => \esc_html__( 'Invalid nonce.', 'progress-planner' ) ] ); @@ -159,11 +164,11 @@ public function handle_interactive_task_specific_submit() { $nonce_response = \json_decode( wp_remote_retrieve_body( $nonce_request ), true ); $remote_nonce = $nonce_response['nonce'] ?? ''; - // TODO: Tell server which email are we going to send, response should be email address. + // TODO: Tell server which email are we going to send, response should be email address to which email we are sending the test email. $subject = \get_bloginfo( 'name' ) . ' - ' . \microtime( true ); $pre_request = wp_remote_post( - \progress_planner()->get_remote_server_root_url() . '/wp-json/progress-planner-saas/v1/register-email-for-dns-check', + \progress_planner()->get_remote_server_root_url() . '/wp-json/progress-planner-saas/v1/email-dns-check', [ 'body' => [ 'nonce' => $remote_nonce, @@ -194,7 +199,7 @@ public function handle_interactive_task_specific_submit() { sleep( 10 ); $dns_check_request = wp_remote_get( - \progress_planner()->get_remote_server_root_url() . '/wp-json/progress-planner-saas/v1/check-email-dns-records', + \progress_planner()->get_remote_server_root_url() . '/wp-json/progress-planner-saas/v1/email-dns-check', [ 'body' => [ 'nonce' => $remote_nonce, From 82694dc2994bf02348a1fde692a8d548b0a54bdc Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Tue, 18 Nov 2025 16:18:52 +0100 Subject: [PATCH 03/10] couple more tweaks --- .../check-email-dns-records.js | 29 +++++++++++-- .../class-check-email-dns-records.php | 43 ++++++++++++------- 2 files changed, 52 insertions(+), 20 deletions(-) diff --git a/assets/js/recommendations/check-email-dns-records.js b/assets/js/recommendations/check-email-dns-records.js index a60111f64..02f59449f 100644 --- a/assets/js/recommendations/check-email-dns-records.js +++ b/assets/js/recommendations/check-email-dns-records.js @@ -1,13 +1,34 @@ -/* global prplInteractiveTaskFormListener */ +/* global prplInteractiveTaskFormListener, progressPlanner */ /* - * Set the site timezone. + * Check email DNS records recommendation. * * Dependencies: progress-planner/recommendations/interactive-task */ -prplInteractiveTaskFormListener.settings( { +prplInteractiveTaskFormListener.customSubmit( { taskId: 'check-email-dns-records', popoverId: 'prpl-popover-check-email-dns-records', - action: 'prpl_interactive_task_submit_check-email-dns-records', + callback: () => { + return new Promise( ( resolve, reject ) => { + fetch( progressPlanner.ajaxUrl, { + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + body: new URLSearchParams( { + action: 'prpl_interactive_task_submit_check-email-dns-records', + nonce: progressPlanner.nonce, + } ), + } ) + .then( ( response ) => response.json() ) + .then( ( response ) => { + // WIP:This will close the popover and trigger the celebration event (confetti). + resolve( { response, success: true } ); + } ) + .catch( ( error ) => { + reject( { success: false, error } ); + } ); + } ); + }, } ); diff --git a/classes/suggested-tasks/providers/class-check-email-dns-records.php b/classes/suggested-tasks/providers/class-check-email-dns-records.php index 002fed7fa..0ee14bc78 100644 --- a/classes/suggested-tasks/providers/class-check-email-dns-records.php +++ b/classes/suggested-tasks/providers/class-check-email-dns-records.php @@ -111,12 +111,7 @@ public function print_popover_instructions() { * @return void */ public function print_popover_form_contents() { - - ?> - - print_submit_button( \__( 'Check email DNS records', 'progress-planner' ) ); } /** @@ -164,16 +159,16 @@ public function handle_interactive_task_specific_submit() { $nonce_response = \json_decode( wp_remote_retrieve_body( $nonce_request ), true ); $remote_nonce = $nonce_response['nonce'] ?? ''; - // TODO: Tell server which email are we going to send, response should be email address to which email we are sending the test email. - $subject = \get_bloginfo( 'name' ) . ' - ' . \microtime( true ); + // Tell server which email identifier are we going to use, response should be email address to which we are sending the test email. + $subject = md5( \get_bloginfo( 'name' ) . ' - ' . \microtime( true ) ); $pre_request = wp_remote_post( \progress_planner()->get_remote_server_root_url() . '/wp-json/progress-planner-saas/v1/email-dns-check', [ 'body' => [ - 'nonce' => $remote_nonce, - 'site' => $site, - 'subject' => $subject, + 'nonce' => $remote_nonce, + 'site' => $site, + 'email_identifier' => $subject, ], ] ); @@ -190,8 +185,7 @@ public function handle_interactive_task_specific_submit() { // TODO: If wp_mail returned false we need to tell the server to not check for the email. if ( ! $email_sent ) { - // TODO: Tell server that the email was not sent. - + \error_log( 'Failed to send email: ' . $email_address ); \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to send email.', 'progress-planner' ) ] ); } @@ -202,9 +196,9 @@ public function handle_interactive_task_specific_submit() { \progress_planner()->get_remote_server_root_url() . '/wp-json/progress-planner-saas/v1/email-dns-check', [ 'body' => [ - 'nonce' => $remote_nonce, - 'site' => $site, - 'subject' => $subject, + 'nonce' => $remote_nonce, + 'site' => $site, + 'email_identifier' => $subject, ], ] ); @@ -229,4 +223,21 @@ public function handle_interactive_task_specific_submit() { \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to check email DNS records.', 'progress-planner' ) ] ); } + + /** + * Add task actions specific to this task. + * + * @param array $data The task data. + * @param array $actions The existing actions. + * + * @return array + */ + public function add_task_actions( $data = [], $actions = [] ) { + $actions[] = [ + 'priority' => 10, + 'html' => '' . \esc_html__( 'Check', 'progress-planner' ) . '', + ]; + + return $actions; + } } From 8ab44371c4dee5adf402cb6ca3ca352a841fc341 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Wed, 19 Nov 2025 10:35:55 +0100 Subject: [PATCH 04/10] WIP better popover --- assets/css/check-email-dns-records.css | 190 +++++++++++++++++ .../check-email-dns-records.js | 196 ++++++++++++++++-- .../class-check-email-dns-records.php | 138 ++++++++++-- views/popovers/check-email-dns-records.php | 57 +++++ 4 files changed, 537 insertions(+), 44 deletions(-) create mode 100644 assets/css/check-email-dns-records.css create mode 100644 views/popovers/check-email-dns-records.php diff --git a/assets/css/check-email-dns-records.css b/assets/css/check-email-dns-records.css new file mode 100644 index 000000000..1324e0273 --- /dev/null +++ b/assets/css/check-email-dns-records.css @@ -0,0 +1,190 @@ +/** + * Check Email DNS Records Styles + * + * Styles for email DNS check task execution and display. + */ + +/* Email DNS Check Popover */ +.prpl-popover-email-dns { + max-width: 600px; +} + +.prpl-email-dns-content { + min-height: 100px; +} + +/* Header */ +.prpl-popover-email-dns .prpl-popover-header { + display: flex; + justify-content: space-between; + align-items: center; + padding: 15px 20px; + border-bottom: 1px solid #e5e7eb; +} + +.prpl-popover-email-dns .prpl-popover-title { + margin: 0; + font-size: 18px; + font-weight: 600; + color: #1f2937; +} + +.prpl-popover-email-dns .prpl-popover-close { + background: none; + border: none; + cursor: pointer; + padding: 5px; + color: #6b7280; + transition: color 0.2s; +} + +.prpl-popover-email-dns .prpl-popover-close:hover { + color: #1f2937; +} + +/* Content */ +.prpl-popover-email-dns .prpl-popover-content { + padding: 20px; +} + +/* Instructions */ +.prpl-email-dns-instructions p { + margin: 0 0 10px 0; + line-height: 1.6; +} + +.prpl-email-dns-instructions p:last-child { + margin-bottom: 0; +} + +/* Loading State */ +.prpl-email-dns-loading { + text-align: center; + padding: 30px 20px; +} + +.prpl-email-dns-loading .prpl-spinner { + margin: 0 auto 20px; + width: 40px; + height: 40px; + border: 4px solid #f3f4f6; + border-top-color: #534786; + border-radius: 50%; + animation: prpl-email-dns-spin 1s linear infinite; +} + +@keyframes prpl-email-dns-spin { + + to { + transform: rotate(360deg); + } +} + +.prpl-email-dns-loading p { + color: #666; + font-size: 14px; + margin: 0; +} + +/* Result State */ +.prpl-email-dns-result { + padding: 20px; + background: #f9fafb; + border-radius: 6px; + margin-bottom: 20px; +} + +.prpl-email-dns-response { + line-height: 1.6; + color: #1f2937; +} + +/* DNS Results Styling */ +.prpl-dns-results { + font-size: 14px; +} + +.prpl-spam-score { + margin: 0 0 15px 0; + padding: 10px; + border-radius: 4px; +} + +.prpl-spam-score.prpl-score-good { + background-color: #d1fae5; + color: #065f46; +} + +.prpl-spam-score.prpl-score-warning { + background-color: #fef3c7; + color: #92400e; +} + +.prpl-spam-score.prpl-score-bad { + background-color: #fee2e2; + color: #991b1b; +} + +.prpl-dns-records-list { + list-style: none; + margin: 0; + padding: 0; +} + +.prpl-dns-record { + padding: 8px 0; + border-bottom: 1px solid #e5e7eb; + display: flex; + align-items: center; + gap: 8px; +} + +.prpl-dns-record:last-child { + border-bottom: none; +} + +.prpl-status-icon { + font-weight: 700; + font-size: 16px; +} + +.prpl-dns-record.prpl-status-pass .prpl-status-icon { + color: #059669; +} + +.prpl-dns-record.prpl-status-fail .prpl-status-icon { + color: #dc2626; +} + +/* Error State */ +.prpl-email-dns-error { + padding: 15px; + background: #fef2f2; + border: 1px solid #fecaca; + border-radius: 6px; + margin-bottom: 20px; +} + +.prpl-email-dns-error .prpl-error-message { + color: #dc2626; + margin: 0; + font-size: 14px; +} + +/* Buttons */ +.prpl-email-dns-check, +.prpl-email-dns-retry { + min-width: 120px; +} + +/* Responsive */ +@media (max-width: 768px) { + + .prpl-popover-email-dns { + max-width: 90vw; + } + + .prpl-email-dns-result { + padding: 15px; + } +} diff --git a/assets/js/recommendations/check-email-dns-records.js b/assets/js/recommendations/check-email-dns-records.js index 02f59449f..a94daf376 100644 --- a/assets/js/recommendations/check-email-dns-records.js +++ b/assets/js/recommendations/check-email-dns-records.js @@ -1,34 +1,184 @@ -/* global prplInteractiveTaskFormListener, progressPlanner */ +/* global progressPlannerAjaxRequest, progressPlanner */ -/* - * Check email DNS records recommendation. +/** + * Check Email DNS Records Handler * - * Dependencies: progress-planner/recommendations/interactive-task + * Handles execution of email DNS check tasks with state management. + * + * Dependencies: progress-planner/suggested-task, progress-planner/ajax-request */ -prplInteractiveTaskFormListener.customSubmit( { - taskId: 'check-email-dns-records', - popoverId: 'prpl-popover-check-email-dns-records', - callback: () => { - return new Promise( ( resolve, reject ) => { - fetch( progressPlanner.ajaxUrl, { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: new URLSearchParams( { +( () => { + /** + * Handle email DNS check execution. + */ + const handleEmailDNSCheck = () => { + const popover = document.getElementById( + 'prpl-popover-check-email-dns-records' + ); + if ( ! popover ) { + return; + } + + const checkButton = popover.querySelector( '.prpl-email-dns-check' ); + const retryButton = popover.querySelector( '.prpl-email-dns-retry' ); + const completeButton = popover.querySelector( + '.prpl-email-dns-complete' + ); + const instructionsEl = popover.querySelector( + '.prpl-email-dns-instructions' + ); + const loadingEl = popover.querySelector( '.prpl-email-dns-loading' ); + const resultEl = popover.querySelector( '.prpl-email-dns-result' ); + const responseEl = popover.querySelector( '.prpl-email-dns-response' ); + const errorEl = popover.querySelector( '.prpl-email-dns-error' ); + const errorMessageEl = popover.querySelector( '.prpl-error-message' ); + + /** + * Show loading state. + */ + const showLoading = () => { + if ( checkButton ) { + checkButton.style.display = 'none'; + } + if ( retryButton ) { + retryButton.style.display = 'none'; + } + if ( completeButton ) { + completeButton.style.display = 'none'; + } + if ( instructionsEl ) { + instructionsEl.style.display = 'none'; + } + if ( loadingEl ) { + loadingEl.style.display = 'block'; + } + if ( resultEl ) { + resultEl.style.display = 'none'; + } + if ( errorEl ) { + errorEl.style.display = 'none'; + } + }; + + /** + * Show result state. + * + * @param {string} responseHtml - The formatted HTML response. + */ + const showResult = ( responseHtml ) => { + if ( instructionsEl ) { + instructionsEl.style.display = 'none'; + } + if ( loadingEl ) { + loadingEl.style.display = 'none'; + } + if ( checkButton ) { + checkButton.style.display = 'none'; + } + if ( retryButton ) { + retryButton.style.display = 'none'; + } + if ( errorEl ) { + errorEl.style.display = 'none'; + } + if ( resultEl ) { + resultEl.style.display = 'block'; + } + if ( completeButton ) { + completeButton.style.display = 'inline-block'; + } + + if ( responseEl ) { + responseEl.innerHTML = responseHtml; + } + }; + + /** + * Show error state. + * + * @param {string} message - The error message. + */ + const showError = ( message ) => { + if ( instructionsEl ) { + instructionsEl.style.display = 'none'; + } + if ( loadingEl ) { + loadingEl.style.display = 'none'; + } + if ( checkButton ) { + checkButton.style.display = 'none'; + } + if ( retryButton ) { + retryButton.style.display = 'inline-block'; + } + if ( completeButton ) { + completeButton.style.display = 'none'; + } + if ( resultEl ) { + resultEl.style.display = 'none'; + } + if ( errorEl ) { + errorEl.style.display = 'block'; + } + if ( errorMessageEl ) { + errorMessageEl.textContent = message; + } + }; + + /** + * Execute the email DNS check. + */ + const executeCheck = () => { + showLoading(); + + // Make AJAX request to check email DNS records. + progressPlannerAjaxRequest( { + url: progressPlanner.ajaxUrl, + data: { action: 'prpl_interactive_task_submit_check-email-dns-records', nonce: progressPlanner.nonce, - } ), + }, } ) - .then( ( response ) => response.json() ) .then( ( response ) => { - // WIP:This will close the popover and trigger the celebration event (confetti). - resolve( { response, success: true } ); + if ( ! response.success ) { + const errorMessage = + response.data?.message || + 'Failed to check email DNS records. Please try again.'; + showError( errorMessage ); + return; + } + + const data = response.data; + const responseHtml = + data.response_html || + '

Check completed successfully.

'; + + showResult( responseHtml ); } ) .catch( ( error ) => { - reject( { success: false, error } ); + console.error( 'Email DNS check error:', error ); + showError( + 'An error occurred while checking your email DNS records. Please try again.' + ); } ); - } ); - }, -} ); + }; + + // Check button click handler. + if ( checkButton ) { + checkButton.addEventListener( 'click', executeCheck ); + } + + // Retry button click handler. + if ( retryButton ) { + retryButton.addEventListener( 'click', executeCheck ); + } + }; + + // Initialize when DOM is ready. + if ( document.readyState === 'loading' ) { + document.addEventListener( 'DOMContentLoaded', handleEmailDNSCheck ); + } else { + handleEmailDNSCheck(); + } +} )(); diff --git a/classes/suggested-tasks/providers/class-check-email-dns-records.php b/classes/suggested-tasks/providers/class-check-email-dns-records.php index 0ee14bc78..67cfcd516 100644 --- a/classes/suggested-tasks/providers/class-check-email-dns-records.php +++ b/classes/suggested-tasks/providers/class-check-email-dns-records.php @@ -70,14 +70,6 @@ protected function get_description() { return \esc_html__( 'Check the email DNS records to ensure they are configured correctly.', 'progress-planner' ); } - /** - * Get the task-action text. - * - * @return string - */ - protected function get_task_action_text() { - return \esc_html__( 'Check email DNS records', 'progress-planner' ); - } /** * Check if the task should be added. * @@ -95,23 +87,81 @@ public function should_add_task() { } /** - * Get the popover instructions. + * Print popover form contents. + * Required by Tasks_Interactive, but we override add_popover() completely. * * @return void */ - public function print_popover_instructions() { - echo '

'; - \esc_html_e( 'Check the email DNS records to ensure they are configured correctly.', 'progress-planner' ); - echo '

'; + public function print_popover_form_contents() { + // Not used - we use a custom popover view. } /** - * Print the popover input field for the form. + * The popover content, WIP until get_file bug is fixed. * * @return void */ - public function print_popover_form_contents() { - $this->print_submit_button( \__( 'Check email DNS records', 'progress-planner' ) ); + public function the_popover_content() { + \progress_planner()->the_view( + 'popovers/' . static::POPOVER_ID . '.php', + [ + 'prpl_popover_id' => static::POPOVER_ID, + 'prpl_provider_id' => $this->get_provider_id(), + ] + ); + } + + /** + * Add the popover for email DNS check task. + * Overrides parent to use custom popover view with state management. + * + * @return void + */ + public function add_popover() { + // Don't add the popover if the task is not published. + if ( ! $this->is_task_published() ) { + return; + } + ?> +
+ the_popover_content(); ?> +
+ is_task_published() ) { + return; + } + + // Enqueue the email DNS check script. + \progress_planner()->get_admin__enqueue()->enqueue_script( + 'progress-planner/recommendations/check-email-dns-records', + [ + 'file' => 'recommendations/check-email-dns-records.js', + 'dependencies' => [ 'progress-planner/suggested-task', 'progress-planner/ajax-request' ], + ] + ); + + // Enqueue the email DNS check CSS. + \progress_planner()->get_admin__enqueue()->enqueue_style( 'progress-planner/check-email-dns-records' ); } /** @@ -214,14 +264,60 @@ public function handle_interactive_task_specific_submit() { // TODO: If the report is still being processed, we need to let the user know and save the email subject for later. // Most likely we will fire another AJAX request (for example up to 5 times) to check if the report is ready. - // TODO: Handle different statuses, ie SPF set correctly, DKIM is not set, etc. - if ( $dns_records_status && $spam_score ) { + // Build the response with DNS records status information. + $response_html = $this->format_dns_response( $dns_records_status, $spam_score ); - // We're not checking for the return value of the update_option calls, because it will return false if the value is the same (for example if gmt_offset is already set to ''). - \wp_send_json_success( [ 'message' => \esc_html__( 'Email DNS records checked successfully.', 'progress-planner' ) ] ); + \wp_send_json_success( + [ + 'message' => \esc_html__( 'Email DNS records checked successfully.', 'progress-planner' ), + 'dns_records_status' => $dns_records_status, + 'spam_score' => $spam_score, + 'response_html' => $response_html, + ] + ); + } + + /** + * Format the DNS check response for display. + * + * @param array|bool $dns_records_status The DNS records status. + * @param float|bool $spam_score The spam score. + * @return string Formatted HTML response. + */ + protected function format_dns_response( $dns_records_status, $spam_score ) { + $html = '
'; + + // Format spam score. + if ( false !== $spam_score ) { + $score_class = $spam_score <= 2 ? 'good' : ( $spam_score <= 5 ? 'warning' : 'bad' ); + $html .= sprintf( + '

%s %s

', + \esc_attr( $score_class ), + \esc_html__( 'Spam Score:', 'progress-planner' ), + \esc_html( $spam_score ) + ); } - \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to check email DNS records.', 'progress-planner' ) ] ); + // Format DNS records status. + if ( \is_array( $dns_records_status ) ) { + $html .= '
    '; + foreach ( $dns_records_status as $record_type => $status ) { + $status_class = $status ? 'pass' : 'fail'; + $status_icon = $status ? '✓' : '✗'; + $html .= sprintf( + '
  • %s %s: %s
  • ', + \esc_attr( $status_class ), + $status_icon, + \esc_html( strtoupper( $record_type ) ), + $status ? \esc_html__( 'Configured', 'progress-planner' ) : \esc_html__( 'Not configured', 'progress-planner' ) + ); + } + $html .= '
'; + } + + $html .= '
'; + + return $html; } /** diff --git a/views/popovers/check-email-dns-records.php b/views/popovers/check-email-dns-records.php new file mode 100644 index 000000000..7061fa928 --- /dev/null +++ b/views/popovers/check-email-dns-records.php @@ -0,0 +1,57 @@ + + + +
+

+ +
+
+ +
+ + + +
+
+
From 3c5fbf9a67497f312557e9bf8d5a2ccd8a9ed220 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Wed, 19 Nov 2025 11:39:54 +0100 Subject: [PATCH 05/10] WIP: easier UI state --- .../check-email-dns-records.js | 156 ++++++++++-------- 1 file changed, 87 insertions(+), 69 deletions(-) diff --git a/assets/js/recommendations/check-email-dns-records.js b/assets/js/recommendations/check-email-dns-records.js index a94daf376..4316881b7 100644 --- a/assets/js/recommendations/check-email-dns-records.js +++ b/assets/js/recommendations/check-email-dns-records.js @@ -34,64 +34,105 @@ const errorEl = popover.querySelector( '.prpl-email-dns-error' ); const errorMessageEl = popover.querySelector( '.prpl-error-message' ); + // Define all elements in one place for easy maintenance. + const elements = { + checkButton, + retryButton, + completeButton, + instructionsEl, + loadingEl, + resultEl, + responseEl, + errorEl, + errorMessageEl, + }; + + // State configuration: define visibility for each element in each state. + const states = { + loading: { + checkButton: 'none', + retryButton: 'none', + completeButton: 'none', + instructionsEl: 'none', + loadingEl: 'block', + resultEl: 'none', + errorEl: 'none', + }, + result: { + instructionsEl: 'none', + loadingEl: 'none', + checkButton: 'none', + retryButton: 'none', + errorEl: 'none', + resultEl: 'block', + completeButton: 'inline-block', + }, + error: { + instructionsEl: 'none', + loadingEl: 'none', + checkButton: 'none', + retryButton: 'inline-block', + completeButton: 'none', + resultEl: 'none', + errorEl: 'block', + }, + }; + /** - * Show loading state. + * Set the UI state. + * + * @param {string} stateName - The state name ('loading', 'result', or 'error'). + * @param {Object} options - Additional options for the state. + * @param {string} options.responseHtml - HTML content for responseEl (result state only). + * @param {string} options.message - Error message for errorMessageEl (error state only). */ - const showLoading = () => { - if ( checkButton ) { - checkButton.style.display = 'none'; - } - if ( retryButton ) { - retryButton.style.display = 'none'; - } - if ( completeButton ) { - completeButton.style.display = 'none'; - } - if ( instructionsEl ) { - instructionsEl.style.display = 'none'; + const setUIState = ( stateName, options = {} ) => { + const state = states[ stateName ]; + if ( ! state ) { + console.warn( `Unknown state: ${ stateName }` ); + return; } - if ( loadingEl ) { - loadingEl.style.display = 'block'; - } - if ( resultEl ) { - resultEl.style.display = 'none'; + + // Apply visibility for each element in the state. + Object.entries( state ).forEach( ( [ key, display ] ) => { + const element = elements[ key ]; + if ( element ) { + element.style.display = display; + } + } ); + + // Handle special cases. + if ( + stateName === 'result' && + options.responseHtml && + elements.responseEl + ) { + elements.responseEl.innerHTML = options.responseHtml; } - if ( errorEl ) { - errorEl.style.display = 'none'; + + if ( + stateName === 'error' && + options.message && + elements.errorMessageEl + ) { + elements.errorMessageEl.textContent = options.message; } }; + /** + * Show loading state. + */ + const showLoading = () => { + setUIState( 'loading' ); + }; + /** * Show result state. * * @param {string} responseHtml - The formatted HTML response. */ const showResult = ( responseHtml ) => { - if ( instructionsEl ) { - instructionsEl.style.display = 'none'; - } - if ( loadingEl ) { - loadingEl.style.display = 'none'; - } - if ( checkButton ) { - checkButton.style.display = 'none'; - } - if ( retryButton ) { - retryButton.style.display = 'none'; - } - if ( errorEl ) { - errorEl.style.display = 'none'; - } - if ( resultEl ) { - resultEl.style.display = 'block'; - } - if ( completeButton ) { - completeButton.style.display = 'inline-block'; - } - - if ( responseEl ) { - responseEl.innerHTML = responseHtml; - } + setUIState( 'result', { responseHtml } ); }; /** @@ -100,30 +141,7 @@ * @param {string} message - The error message. */ const showError = ( message ) => { - if ( instructionsEl ) { - instructionsEl.style.display = 'none'; - } - if ( loadingEl ) { - loadingEl.style.display = 'none'; - } - if ( checkButton ) { - checkButton.style.display = 'none'; - } - if ( retryButton ) { - retryButton.style.display = 'inline-block'; - } - if ( completeButton ) { - completeButton.style.display = 'none'; - } - if ( resultEl ) { - resultEl.style.display = 'none'; - } - if ( errorEl ) { - errorEl.style.display = 'block'; - } - if ( errorMessageEl ) { - errorMessageEl.textContent = message; - } + setUIState( 'error', { message } ); }; /** From 2b925a3c8746606de8a3c3af7dbcb88ffb4b33b4 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Wed, 19 Nov 2025 15:37:27 +0100 Subject: [PATCH 06/10] format response server side, output just the result --- .../class-check-email-dns-records.php | 38 +++++++------------ 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/classes/suggested-tasks/providers/class-check-email-dns-records.php b/classes/suggested-tasks/providers/class-check-email-dns-records.php index 67cfcd516..4c94db51f 100644 --- a/classes/suggested-tasks/providers/class-check-email-dns-records.php +++ b/classes/suggested-tasks/providers/class-check-email-dns-records.php @@ -231,7 +231,7 @@ public function handle_interactive_task_specific_submit() { $email_address = $pre_request_response['email_address'] ?? ''; // Send the email. - $email_sent = wp_mail( $email_address, $subject, '' ); + $email_sent = \wp_mail( $email_address, $subject, '' ); // TODO: If wp_mail returned false we need to tell the server to not check for the email. if ( ! $email_sent ) { @@ -258,21 +258,21 @@ public function handle_interactive_task_specific_submit() { } $dns_check_response = \json_decode( wp_remote_retrieve_body( $dns_check_request ), true ); - $dns_records_status = $dns_check_response['dns_records_status'] ?? false; - $spam_score = $dns_check_response['spam_score'] ?? false; // Lower is better. + + if ( ! isset( $dns_check_response['results'] ) ) { + \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to check email DNS records.', 'progress-planner' ) ] ); + } // TODO: If the report is still being processed, we need to let the user know and save the email subject for later. // Most likely we will fire another AJAX request (for example up to 5 times) to check if the report is ready. // Build the response with DNS records status information. - $response_html = $this->format_dns_response( $dns_records_status, $spam_score ); + $response_html = $this->format_dns_response( $dns_check_response['results'] ); \wp_send_json_success( [ - 'message' => \esc_html__( 'Email DNS records checked successfully.', 'progress-planner' ), - 'dns_records_status' => $dns_records_status, - 'spam_score' => $spam_score, - 'response_html' => $response_html, + 'message' => \esc_html__( 'Email DNS records checked successfully.', 'progress-planner' ), + 'response_html' => $response_html, ] ); } @@ -280,28 +280,16 @@ public function handle_interactive_task_specific_submit() { /** * Format the DNS check response for display. * - * @param array|bool $dns_records_status The DNS records status. - * @param float|bool $spam_score The spam score. + * @param array|bool $check_results The DNS records status. * @return string Formatted HTML response. */ - protected function format_dns_response( $dns_records_status, $spam_score ) { + protected function format_dns_response( $check_results ) { $html = '
'; - // Format spam score. - if ( false !== $spam_score ) { - $score_class = $spam_score <= 2 ? 'good' : ( $spam_score <= 5 ? 'warning' : 'bad' ); - $html .= sprintf( - '

%s %s

', - \esc_attr( $score_class ), - \esc_html__( 'Spam Score:', 'progress-planner' ), - \esc_html( $spam_score ) - ); - } - // Format DNS records status. - if ( \is_array( $dns_records_status ) ) { + if ( \is_array( $check_results ) ) { $html .= '
    '; - foreach ( $dns_records_status as $record_type => $status ) { + foreach ( $check_results as $record_type => $status ) { $status_class = $status ? 'pass' : 'fail'; $status_icon = $status ? '✓' : '✗'; $html .= sprintf( @@ -309,7 +297,7 @@ protected function format_dns_response( $dns_records_status, $spam_score ) { \esc_attr( $status_class ), $status_icon, \esc_html( strtoupper( $record_type ) ), - $status ? \esc_html__( 'Configured', 'progress-planner' ) : \esc_html__( 'Not configured', 'progress-planner' ) + $status ? \esc_html__( 'Passed', 'progress-planner' ) : \esc_html__( 'Failed', 'progress-planner' ) ); } $html .= '
'; From e70b4cec803df5d73d875d996c8ab01191805440 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Fri, 21 Nov 2025 14:10:35 +0100 Subject: [PATCH 07/10] message body cant be empty --- .../providers/class-check-email-dns-records.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/suggested-tasks/providers/class-check-email-dns-records.php b/classes/suggested-tasks/providers/class-check-email-dns-records.php index 4c94db51f..d93c0f6fa 100644 --- a/classes/suggested-tasks/providers/class-check-email-dns-records.php +++ b/classes/suggested-tasks/providers/class-check-email-dns-records.php @@ -223,7 +223,7 @@ public function handle_interactive_task_specific_submit() { ] ); - if ( is_wp_error( $pre_request ) || 200 !== wp_remote_retrieve_response_code( $pre_request ) ) { + if ( \is_wp_error( $pre_request ) || 200 !== \wp_remote_retrieve_response_code( $pre_request ) ) { \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to send test email.', 'progress-planner' ) ] ); } @@ -231,7 +231,7 @@ public function handle_interactive_task_specific_submit() { $email_address = $pre_request_response['email_address'] ?? ''; // Send the email. - $email_sent = \wp_mail( $email_address, $subject, '' ); + $email_sent = \wp_mail( $email_address, $subject, 'email test' ); // Message body is not important, can't be empty. // TODO: If wp_mail returned false we need to tell the server to not check for the email. if ( ! $email_sent ) { From fdbad1533972929f922e642605b870ddb4a0785d Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Fri, 21 Nov 2025 15:10:30 +0100 Subject: [PATCH 08/10] sleep 15s, just in case --- .../providers/class-check-email-dns-records.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/classes/suggested-tasks/providers/class-check-email-dns-records.php b/classes/suggested-tasks/providers/class-check-email-dns-records.php index d93c0f6fa..9a0c0ee13 100644 --- a/classes/suggested-tasks/providers/class-check-email-dns-records.php +++ b/classes/suggested-tasks/providers/class-check-email-dns-records.php @@ -239,8 +239,8 @@ public function handle_interactive_task_specific_submit() { \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to send email.', 'progress-planner' ) ] ); } - // TODO: Sleep for 10 seconds, wait for the report to be ready. - sleep( 10 ); + // TODO: Sleep for 15 seconds, wait for the report to be ready. + sleep( 15 ); $dns_check_request = wp_remote_get( \progress_planner()->get_remote_server_root_url() . '/wp-json/progress-planner-saas/v1/email-dns-check', From 439ed5c0783cc33b7ae6fae6431087c2acdf6121 Mon Sep 17 00:00:00 2001 From: Filip Ilic Date: Mon, 24 Nov 2025 12:11:54 +0100 Subject: [PATCH 09/10] add re-check report button --- .../check-email-dns-records.js | 98 ++++++++++++- .../class-check-email-dns-records.php | 129 ++++++++++++++++-- views/popovers/check-email-dns-records.php | 5 +- 3 files changed, 220 insertions(+), 12 deletions(-) diff --git a/assets/js/recommendations/check-email-dns-records.js b/assets/js/recommendations/check-email-dns-records.js index 4316881b7..8b44b6795 100644 --- a/assets/js/recommendations/check-email-dns-records.js +++ b/assets/js/recommendations/check-email-dns-records.js @@ -22,6 +22,9 @@ const checkButton = popover.querySelector( '.prpl-email-dns-check' ); const retryButton = popover.querySelector( '.prpl-email-dns-retry' ); + const checkReportAgainButton = popover.querySelector( + '.prpl-email-dns-check-report-again' + ); const completeButton = popover.querySelector( '.prpl-email-dns-complete' ); @@ -38,6 +41,7 @@ const elements = { checkButton, retryButton, + checkReportAgainButton, completeButton, instructionsEl, loadingEl, @@ -52,17 +56,29 @@ loading: { checkButton: 'none', retryButton: 'none', + checkReportAgainButton: 'none', completeButton: 'none', instructionsEl: 'none', loadingEl: 'block', resultEl: 'none', errorEl: 'none', }, + pending: { + instructionsEl: 'none', + loadingEl: 'none', + checkButton: 'none', + retryButton: 'none', + checkReportAgainButton: 'inline-block', + completeButton: 'none', + resultEl: 'none', + errorEl: 'block', + }, result: { instructionsEl: 'none', loadingEl: 'none', checkButton: 'none', retryButton: 'none', + checkReportAgainButton: 'none', errorEl: 'none', resultEl: 'block', completeButton: 'inline-block', @@ -72,6 +88,7 @@ loadingEl: 'none', checkButton: 'none', retryButton: 'inline-block', + checkReportAgainButton: 'none', completeButton: 'none', resultEl: 'none', errorEl: 'block', @@ -81,10 +98,10 @@ /** * Set the UI state. * - * @param {string} stateName - The state name ('loading', 'result', or 'error'). + * @param {string} stateName - The state name ('loading', 'result', 'error', or 'pending'). * @param {Object} options - Additional options for the state. * @param {string} options.responseHtml - HTML content for responseEl (result state only). - * @param {string} options.message - Error message for errorMessageEl (error state only). + * @param {string} options.message - Error message for errorMessageEl (error and pending states). */ const setUIState = ( stateName, options = {} ) => { const state = states[ stateName ]; @@ -111,7 +128,7 @@ } if ( - stateName === 'error' && + ( stateName === 'error' || stateName === 'pending' ) && options.message && elements.errorMessageEl ) { @@ -144,6 +161,15 @@ setUIState( 'error', { message } ); }; + /** + * Show pending state (report is still being processed). + * + * @param {string} message - The message to display. + */ + const showPending = ( message ) => { + setUIState( 'pending', { message } ); + }; + /** * Execute the email DNS check. */ @@ -168,6 +194,64 @@ } const data = response.data; + + // Check if the report is still being processed. + if ( data.status === 'pending' ) { + showPending( + data.message || + 'Report is still being processed. Please check again in a moment.' + ); + return; + } + + const responseHtml = + data.response_html || + '

Check completed successfully.

'; + + showResult( responseHtml ); + } ) + .catch( ( error ) => { + console.error( 'Email DNS check error:', error ); + showError( + 'An error occurred while checking your email DNS records. Please try again.' + ); + } ); + }; + + /** + * Check if the report is ready (without sending a new email). + */ + const checkReportAgain = () => { + showLoading(); + + // Make AJAX request to check if report is ready. + progressPlannerAjaxRequest( { + url: progressPlanner.ajaxUrl, + data: { + action: 'prpl_check_email_dns_report_again', + nonce: progressPlanner.nonce, + }, + } ) + .then( ( response ) => { + if ( ! response.success ) { + const errorMessage = + response.data?.message || + 'Failed to check email DNS records. Please try again.'; + showError( errorMessage ); + return; + } + + const data = response.data; + + // Check if the report is still being processed. + if ( data.status === 'pending' ) { + showPending( + data.message || + 'Report is still being processed. Please check again in a moment.' + ); + return; + } + const responseHtml = data.response_html || '

Check completed successfully.

'; @@ -191,6 +275,14 @@ if ( retryButton ) { retryButton.addEventListener( 'click', executeCheck ); } + + // Check report again button click handler. + if ( checkReportAgainButton ) { + checkReportAgainButton.addEventListener( + 'click', + checkReportAgain + ); + } }; // Initialize when DOM is ready. diff --git a/classes/suggested-tasks/providers/class-check-email-dns-records.php b/classes/suggested-tasks/providers/class-check-email-dns-records.php index 9a0c0ee13..8d68eb4af 100644 --- a/classes/suggested-tasks/providers/class-check-email-dns-records.php +++ b/classes/suggested-tasks/providers/class-check-email-dns-records.php @@ -40,6 +40,7 @@ class Check_Email_DNS_Records extends Tasks_Interactive { */ public function init() { \add_action( 'wp_ajax_prpl_interactive_task_submit_check-email-dns-records', [ $this, 'handle_interactive_task_specific_submit' ] ); + \add_action( 'wp_ajax_prpl_check_email_dns_report_again', [ $this, 'handle_check_report_again' ] ); } /** @@ -239,40 +240,152 @@ public function handle_interactive_task_specific_submit() { \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to send email.', 'progress-planner' ) ] ); } + // Store email identifier and remote nonce in transient for later retrieval. + $user_id = \get_current_user_id(); + $cache_key = 'prpl_email_dns_check_' . $user_id; + \set_transient( + $cache_key, + [ + 'email_identifier' => $subject, + 'remote_nonce' => $remote_nonce, + 'site' => $site, + ], + HOUR_IN_SECONDS + ); + // TODO: Sleep for 15 seconds, wait for the report to be ready. sleep( 15 ); + // Check DNS report using the extracted method. + $check_result = $this->check_dns_report( $subject, $remote_nonce, $site ); + + if ( \is_wp_error( $check_result ) ) { + \wp_send_json_error( [ 'message' => $check_result->get_error_message() ] ); + } + + // If report is still processing, return a status indicating that. + if ( isset( $check_result['status'] ) && 'pending' === $check_result['status'] ) { + \wp_send_json_success( + [ + 'message' => \esc_html__( 'Report is still being processed. Please check again in a moment.', 'progress-planner' ), + 'status' => 'pending', + 'email_identifier' => $subject, + ] + ); + } + + // Report is ready, return the results and clean up the transient. + \delete_transient( $cache_key ); + + \wp_send_json_success( + [ + 'message' => \esc_html__( 'Email DNS records checked successfully.', 'progress-planner' ), + 'response_html' => $check_result['response_html'], + ] + ); + } + + /** + * Check DNS report status. + * + * @param string $email_identifier The email identifier (subject) used for the check. + * @param string $remote_nonce The remote nonce for authentication. + * @param string $site The site URL. + * + * @return array|\WP_Error Array with 'response_html' on success, or 'status' => 'pending' if still processing, or WP_Error on failure. + */ + protected function check_dns_report( $email_identifier, $remote_nonce, $site ) { $dns_check_request = wp_remote_get( \progress_planner()->get_remote_server_root_url() . '/wp-json/progress-planner-saas/v1/email-dns-check', [ 'body' => [ 'nonce' => $remote_nonce, 'site' => $site, - 'email_identifier' => $subject, + 'email_identifier' => $email_identifier, ], ] ); - if ( is_wp_error( $dns_check_request ) || 200 !== wp_remote_retrieve_response_code( $dns_check_request ) ) { - \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to check email DNS records.', 'progress-planner' ) ] ); + if ( \is_wp_error( $dns_check_request ) || 200 !== \wp_remote_retrieve_response_code( $dns_check_request ) ) { + return new \WP_Error( 'dns_check_failed', \esc_html__( 'Failed to check email DNS records.', 'progress-planner' ) ); } $dns_check_response = \json_decode( wp_remote_retrieve_body( $dns_check_request ), true ); - if ( ! isset( $dns_check_response['results'] ) ) { - \wp_send_json_error( [ 'message' => \esc_html__( 'Failed to check email DNS records.', 'progress-planner' ) ] ); + // Check if the report is still being processed. + if ( isset( $dns_check_response['status'] ) && 'pending' === $dns_check_response['status'] ) { + return [ + 'status' => 'pending', + ]; } - // TODO: If the report is still being processed, we need to let the user know and save the email subject for later. - // Most likely we will fire another AJAX request (for example up to 5 times) to check if the report is ready. + if ( ! isset( $dns_check_response['results'] ) ) { + return new \WP_Error( 'dns_check_no_results', \esc_html__( 'Failed to check email DNS records.', 'progress-planner' ) ); + } // Build the response with DNS records status information. $response_html = $this->format_dns_response( $dns_check_response['results'] ); + return [ + 'response_html' => $response_html, + ]; + } + + /** + * Handle the check report again AJAX request. + * + * This method only checks if the report is ready and fetches it if it is. + * It does not send a new email. + * + * @return void + */ + public function handle_check_report_again() { + if ( ! $this->capability_required() ) { + \wp_send_json_error( [ 'message' => \esc_html__( 'You do not have permission to check email DNS records.', 'progress-planner' ) ] ); + } + + // Check the nonce. + if ( ! \check_ajax_referer( 'progress_planner', 'nonce', false ) ) { + \wp_send_json_error( [ 'message' => \esc_html__( 'Invalid nonce.', 'progress-planner' ) ] ); + } + + $user_id = \get_current_user_id(); + $cache_key = 'prpl_email_dns_check_' . $user_id; + $cached_data = \get_transient( $cache_key ); + + if ( false === $cached_data || ! isset( $cached_data['email_identifier'], $cached_data['remote_nonce'], $cached_data['site'] ) ) { + \wp_send_json_error( [ 'message' => \esc_html__( 'Email check session expired. Please start a new check.', 'progress-planner' ) ] ); + } + + $email_identifier = $cached_data['email_identifier']; + $remote_nonce = $cached_data['remote_nonce']; + $site = $cached_data['site']; + + // Check DNS report using the extracted method. + $check_result = $this->check_dns_report( $email_identifier, $remote_nonce, $site ); + + if ( \is_wp_error( $check_result ) ) { + \wp_send_json_error( [ 'message' => $check_result->get_error_message() ] ); + } + + // If report is still processing, return a status indicating that. + if ( isset( $check_result['status'] ) && 'pending' === $check_result['status'] ) { + \wp_send_json_success( + [ + 'message' => \esc_html__( 'Report is still being processed. Please check again in a moment.', 'progress-planner' ), + 'status' => 'pending', + 'email_identifier' => $email_identifier, + ] + ); + } + + // Report is ready, return the results and clean up the transient. + \delete_transient( $cache_key ); + \wp_send_json_success( [ 'message' => \esc_html__( 'Email DNS records checked successfully.', 'progress-planner' ), - 'response_html' => $response_html, + 'response_html' => $check_result['response_html'], ] ); } diff --git a/views/popovers/check-email-dns-records.php b/views/popovers/check-email-dns-records.php index 7061fa928..fa62fccbf 100644 --- a/views/popovers/check-email-dns-records.php +++ b/views/popovers/check-email-dns-records.php @@ -47,7 +47,10 @@ +