@Mail Domain Check

WordPress | Contact forms | Administrator notifications

Contact Form Submission Saved, but Notification Email Is Missing

A stored form response and an administrator email are separate outcomes. Make the stored submission the source of truth, schedule the alert from that record, and never require a visitor email or contact profile just to notify the site owner.

Decision: persist first, notify independently

Submission truth
Validation and persistence either failed, remain unknown after a timeout, or produced one durable opaque reference. Only the last state supports a truthful received response.
Administrator alert
A configured site-owner notification can be absent, coupled to visitor identity, unscheduled, queued, transport-accepted, delivered, rejected or bounced.
Submitter confirmation
An optional receipt to the visitor legitimately requires a visitor email. It is a separate branch and must not gate the administrator alert or durable intake.

Browser-local decision tool

Map the submission and notification states

Select evidence states only. No name, email address, message body, form response, token, credential or site secret is requested or transmitted.

Four boundaries, four different answers

  1. Durable intake. Validate and commit the form response, require a nonzero submission reference, and return an explicit error when persistence fails.
  2. Administrator notification. If a recipient is configured, enqueue one idempotent alert from the persisted submission. This branch depends on the configuration and submission reference, not the visitor's email field.
  3. Submitter confirmation. If the form collected a valid visitor email and consent or product rules permit it, schedule a separate receipt. Its absence cannot suppress the administrator alert.
  4. Mail delivery. Track queue, transport, provider and recipient outcomes separately. A mail function returning true means the request was processed at that boundary, not that the message reached an inbox.

Do not return a generic success response when persistence returns zero or false. Do not let a notification failure erase a valid submission, and do not ask the visitor to resubmit a request that already has a durable reference.

A minimal response and job contract

POST /form-submissions
  persistence failed: explicit error; keep browser fields
  persistence unknown: reconcile the same idempotency key
  persistence succeeded: 201 { submissionRef, intake: "received" }

submission:<submissionRef>
  intake: received | triaged | resolved
  adminNotification: not_configured | queued | transport_accepted
                     | delivered | delayed | bounced | failed
  submitterConfirmation: not_applicable | queued | delivered | failed

Invariant: admin notification depends on configured recipient
           + persisted submission, never on visitor identity.

Implementation order

  1. Capture the persistence return value and treat an empty or zero identifier as failure.
  2. Return an opaque submission reference only after the record is committed.
  3. Schedule the administrator alert when a notification recipient is configured, regardless of whether the form has an email question or a contact-profile plugin is active.
  4. Schedule submitter confirmation independently and only when a valid visitor address is available.
  5. Use a job uniqueness key composed from the submission reference and notification kind. Record each transport attempt as child evidence.
  6. Expose bounded states to operators so a dashboard can distinguish received, alert not configured, queued, transport failed and delivered.

What the current Fair Form source proves

Fair Event Plugins issue 1212 reports that Fair Form's configured notification email is skipped unless the form also collects an email address. In reviewed main revision c81b8425c2ce77d0c2bfed616aba26a0d96def46, FairFormController::create_item() creates a participant only when a submitter email and Fair Audience services are available. Both the submitter confirmation and configured administrator notification are nested under that participant branch.

The same controller calls QuestionnaireService::save_answers() but ignores its returned submission identifier. That service can return 0 when persistence fails, while the controller still reaches a success response. The repair therefore needs both changes: require durable persistence before success, then decouple administrator notification from optional visitor identity.

Acceptance tests before release

  1. Submit a form with no email question and with the optional audience/contact plugin inactive. Prove one durable submission and one administrator alert job.
  2. Submit a form with a valid visitor email. Prove one administrator alert and, when enabled, one separate submitter confirmation.
  3. Force save_answers() to return zero. Prove an explicit failure response, no success message, and no notification job.
  4. Make the mail transport unavailable after persistence. Prove the submission remains received and the administrator job becomes retryable.
  5. Replay the same request and notification job key. Prove one submission and one logical administrator alert, with bounded attempt history.
  6. Return transport acceptance, then simulate a later bounce. Prove that delivery state changes without rewriting intake state.
Verify the notification sender independently

Check the public SPF, DKIM, DMARC, PTR and MTA-STS surface without entering a recipient, form response or site credential.

Check sending domain

Primary references