| @@ -809,8 +809,15 @@ | ||
| 809 | 809 | if ( $provider->is_active() && '' !== $entry_language ) { |
| 810 | 810 | $provider->switch_language( $entry_language ); |
| 811 | 811 | } |
| 812 | 812 | |
| 813 | + // Entries::add() has stored the logs collected so far. Start the instance | |
| 814 | + // empty so the update below writes only what send_email() records -- | |
| 815 | + // Entries::update() merges with the stored logs, so anything left here | |
| 816 | + // would be written twice. | |
| 817 | + $entries_db_instance = Entries::get_instance(); | |
| 818 | + $entries_db_instance->reset_logs(); | |
| 819 | + | |
| 813 | 820 | // Send email after entry creation so {entry_id} is available when smart tags are processed. |
| 814 | 821 | $send_email = $this->send_email( $id, $submission_data, $form_data ); |
| 815 | 822 | if ( $send_email ) { |
| 816 | 823 | $emails = $send_email['emails']; |
| @@ -815,8 +822,15 @@ | ||
| 815 | 822 | if ( $send_email ) { |
| 816 | 823 | $emails = $send_email['emails']; |
| 817 | 824 | } |
| 818 | 825 | |
| 826 | + // send_email() logs to the in-memory instance; the entry already exists, | |
| 827 | + // so the log only reaches it through an update. | |
| 828 | + $notification_logs = $entries_db_instance->get_logs(); | |
| 829 | + if ( ! empty( $notification_logs ) ) { | |
| 830 | + Entries::update( Helper::get_integer_value( $entry_id ), [ 'logs' => $notification_logs ] ); | |
| 831 | + } | |
| 832 | + | |
| 819 | 833 | $confirmation_message = Generate_Form_Markup::get_confirmation_markup( $form_data, $submission_data ); |
| 820 | 834 | $redirect_url = Generate_Form_Markup::get_redirect_url( $form_data, $submission_data ); |
| 821 | 835 | |
| 822 | 836 | if ( $provider->is_active() && '' !== $entry_language ) { |
| @@ -1029,8 +1043,14 @@ | ||
| 1029 | 1043 | */ |
| 1030 | 1044 | public static function send_email( $id, $submission_data, $form_data = [] ) { |
| 1031 | 1045 | $email_notification = get_post_meta( intval( $id ), '_srfm_email_notification' ); |
| 1032 | 1046 | $is_mail_sent = false; |
| 1047 | + // Any recipient failing counts as a failure for the whole submission, so | |
| 1048 | + // these are set inside the loop and only read after it. | |
| 1049 | + $notification_failed = false; | |
| 1050 | + // Whether any recipient's "success" came from the mail() fallback, which | |
| 1051 | + // reports true for a message the local MTA accepted and will bounce. | |
| 1052 | + $used_mail_fallback = false; | |
| 1033 | 1053 | $emails = []; |
| 1034 | 1054 | |
| 1035 | 1055 | // Filter to determine whether the email notification should be sent. |
| 1036 | 1056 | $email_notification = apply_filters( 'srfm_email_notification_should_send', $email_notification, $submission_data, $form_data ); |
| @@ -1099,11 +1119,22 @@ | ||
| 1099 | 1119 | $sent = wp_mail( $parsed['to'], $parsed['subject'], $parsed['message'], $parsed['headers'] ); |
| 1100 | 1120 | if ( ! $sent ) { |
| 1101 | 1121 | // Fallback to default PHP mail if for some reasons wp_mail fails. |
| 1102 | 1122 | $sent = mail( $parsed['to'], $parsed['subject'], $parsed['message'], $parsed['headers'] ); |
| 1123 | + | |
| 1124 | + if ( $sent ) { | |
| 1125 | + // Accepted by the local MTA, not delivered. Good | |
| 1126 | + // enough to avoid recording a fault, not good | |
| 1127 | + // enough to retire one. | |
| 1128 | + $used_mail_fallback = true; | |
| 1129 | + } | |
| 1103 | 1130 | } |
| 1104 | 1131 | $email_report = ob_get_clean(); // Catch any printed notice/errors/message for reports. |
| 1105 | 1132 | |
| 1133 | + if ( true !== $sent ) { | |
| 1134 | + $notification_failed = true; | |
| 1135 | + } | |
| 1136 | + | |
| 1106 | 1137 | if ( is_int( $log_key ) ) { |
| 1107 | 1138 | if ( true === $sent ) { |
| 1108 | 1139 | $entries_db_instance->update_log( |
| 1109 | 1140 | $log_key, |
| @@ -1181,8 +1212,39 @@ | ||
| 1181 | 1212 | |
| 1182 | 1213 | if ( empty( $emails ) ) { |
| 1183 | 1214 | $entries_db_instance->reset_logs(); |
| 1184 | 1215 | $entries_db_instance->add_log( __( 'No emails were sent.', 'sureforms' ) ); |
| 1216 | + } | |
| 1217 | + | |
| 1218 | + // The notification fault clears when notifications work again. Nothing | |
| 1219 | + // else retired it: Client_Logger::clear_category() had a single caller | |
| 1220 | + // hardcoded to 'submission', and the notice is deliberately not | |
| 1221 | + // dismissible, so a site that had fixed its SMTP kept an undismissable | |
| 1222 | + // banner on every admin page until somebody opened a support ticket. | |
| 1223 | + // Held until the loop is done because one recipient succeeding while | |
| 1224 | + // another fails is still a failure. | |
| 1225 | + // | |
| 1226 | + // Scoped to the form the fault was recorded against. send_email() runs | |
| 1227 | + // on the public submit path and the counter is per category, not per | |
| 1228 | + // form, so without this an anonymous submission of a working form | |
| 1229 | + // wipes a different form's standing fault -- once per admin page load, | |
| 1230 | + // by anyone. The notice names a form, so the granularity is visible | |
| 1231 | + // now that this clears as well as records. | |
| 1232 | + // | |
| 1233 | + // wp_mail() only. The mail() fallback above returns true when the local | |
| 1234 | + // MTA merely accepts a message it will later bounce, which is the | |
| 1235 | + // broken configuration rather than the fixed one. | |
| 1236 | + // | |
| 1237 | + // is_int( $log_key ) mirrors the recording guard: record_failure() sits | |
| 1238 | + // inside it, so without it an install where add_log() returns a | |
| 1239 | + // non-int would never record a notification fault but would still | |
| 1240 | + // clear one. | |
| 1241 | + $open_failures = Client_Logger::get_failures(); | |
| 1242 | + | |
| 1243 | + if ( ! empty( $emails ) && ! $notification_failed && is_int( $log_key ) | |
| 1244 | + && ! $used_mail_fallback | |
| 1245 | + && intval( $id ) === Helper::get_integer_value( $open_failures['notification']['form_id'] ?? 0 ) ) { | |
| 1246 | + Client_Logger::clear_category( 'notification' ); | |
| 1185 | 1247 | } |
| 1186 | 1248 | } |
| 1187 | 1249 | |
| 1188 | 1250 | return [ |