PluginProbe
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz / 2.12.8
SureForms – Contact Form Builder, AI Forms, Payment Form, Survey & Quiz v2.12.8
2.12.8 2.12.7 2.12.6 2.12.5 2.12.4 2.12.3 2.12.2 2.12.1 2.12.0 2.11.1 2.11.0 2.10.1 2.10.0 2.9.1 2.9.0 2.8.2 2.8.1 2.7.0 2.7.1 2.8.0 trunk 0.0.10 0.0.11 0.0.12 0.0.13 All 98 releases
← All changes | inc/form-submit.php +62 -0 2.12.6 → 2.12.8 View file →
@@ -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 [