> ## Documentation Index
> Fetch the complete documentation index at: https://docs.37audits.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Contact Form Auditor

> Submits your contact form and confirms the notification email actually arrives

<Info>
  **Resilience Auditor** — fills in and submits the contact form you point it at, then waits for the notification email to be forwarded from your inbox. A form that looks fine but no longer delivers email is caught on the next scheduled run.
</Info>

<CardGroup cols={2}>
  <Card title="Silent failures" icon="bell-slash">
    A broken SMTP plugin, a host blocking `wp_mail` or a DMARC change stops delivery without any visible error on the site.
  </Card>

  <Card title="End-to-end proof" icon="envelope-circle-check">
    The only proof that a form works is the email landing in the inbox. This auditor checks exactly that.
  </Card>
</CardGroup>

This auditor opens the **form page** you configure in a headless browser, finds the form by the **CSS selector** you configure, fills every visible field with probe values, submits it and reads the page for a confirmation or a validation error. The result then stays **pending** until the notification email, forwarded from your inbox to `contact-form-auditor@inbound.37audits.com`, reaches 37 Audits. Each probe carries a reference such as `37AUDITS-3f9c2a1b7d04` in its subject and message, which is how the forwarded email is matched to the run.

## Preferences

These settings are configured per monitored URL from the URL's auditor configuration tab. Two are required: the platform does not run the auditor until both are set (the Overview shows *Needs configuration*), and the auditor never runs from Quick Audit. Nothing is submitted on a site that has not been configured.

| Preference | Type | Default | Meaning |
| - | - | - | - |
| `formPageUrl` | string | — (required) | Page where the contact form is published: an absolute URL (`https://example.com/contact`) or a path resolved against the monitored URL (`/contact`, `fale-conosco`). |
| `formSelector` | string | — (required) | CSS selector of the `form` element, for example `form.wpcf7-form`, `#contact-form` or `form[action*="contact"]`. The first match is used. |
| `deliveryTimeoutMinutes` | integer | `15` | How long the platform waits for the forwarded notification before the run is marked as failed. 1 to 1440 minutes. |

## Setup for site owners

<Steps>
  <Step title="Point the auditor at the form">
    Set `formPageUrl` and `formSelector` for the monitored URL. To find the selector, open the form page, right-click the form, choose *Inspect*, and read the `id` or `class` of the `<form>` element.
  </Step>

  <Step title="Forward the notification to 37 Audits">
    In the inbox that receives the form notifications, add a filter that forwards matching messages to **`contact-form-auditor@inbound.37audits.com`**. Match on the subject or body containing `37 Audits contact form probe`, or forward every notification from the form if you prefer.

    * **Gmail**: *Settings → See all settings → Forwarding and POP/IMAP → Add a forwarding address*. Gmail emails a confirmation code to the forwarding address; 37 Audits reads it on the Resend received-emails page and relays it to you. Then create the filter under *Filters and Blocked Addresses* with *Forward it to*.
    * **Google Workspace**: an administrator can add a *Routing* rule for the group or user without a confirmation step.
    * **Outlook / Microsoft 365**: *Settings → Mail → Rules → Add a new rule → Forward to*. No confirmation step.
    * **Other providers**: any server-side forward or redirect rule works. Client-side rules only run while the mail client is open.
  </Step>

  <Step title="Schedule it">
    Enable scheduled monitoring for the auditor. A weekly run is enough for most sites; each run leaves one probe message in your inbox.
  </Step>
</Steps>

## How it works

1. **Resolve preferences** — `formPageUrl` is resolved against the monitored URL and `formSelector` is trimmed. Either one missing is `ERROR` (`500`); the platform normally prevents this by refusing to run.
2. **Open the page** — headless Chromium loads the form page with the 37 Audits user agent and the URL's Basic auth, then waits up to 15 s for the network to settle (analytics and long-polling never go fully quiet, so this is bounded). A navigation failure is `ERROR` (`501`).
3. **Find the form** — the first element matching `formSelector`. No match is `WARNING` (`300`); nothing is submitted. A visible cookie-consent banner is closed first, preferring *Necessary only* / *Reject* over *Accept*, so it cannot sit over the form and swallow clicks.
4. **Fill every visible control**, deciding per control in this order and skipping hidden, submit, button, file and invisible (honeypot) controls:

   | Control | Value |
   | - | - |
   | `input[type=email]`, or a text input labelled *email* | `contact-form-auditor@inbound.37audits.com` |
   | `input[type=tel]`, or labelled *phone* / *telefone* | `+15555550123` |
   | `input[type=url]`, or labelled *website* / *url* / *site* | `https://www.37audits.com` |
   | `input[type=number]`, `input[type=date]` | `1`, today's date |
   | required checkbox, radio group, `select` | checked, first option, first option with a non-empty value |
   | labelled *name* / *nome* | `37 Audits Probe` |
   | labelled *subject* / *assunto* / *topic* | `37 Audits contact form probe 37AUDITS-…` |
   | labelled *company* / *empresa* | `37 Audits` |
   | every `textarea`, or labelled *message* / *mensagem* / *comments* | the probe message, which includes the reference |
   | any other text input | `37 Audits probe 37AUDITS-…` |

   The label is read from `<label for>`, a wrapping `<label>`, `aria-label`, the `name`, the `id` and the `placeholder`, so forms whose inputs have generic names still get sensible values.
5. **Submit** — clicks the form's submit button, falling back to `requestSubmit()` when there is no button or the click is intercepted. A field the browser still reports as invalid blocks the submission and is reported as rejected (`400`). A browser error while filling or submitting is `ERROR` (`501`) with the browser's own message and `data.stage = interaction`.
6. **Watch the page for 15 s** — a visible validation error is `FAIL` (`400`); a success message, the form disappearing or a navigation counts as confirmed; neither within 15 s is `WARNING` (`301`).
7. **Report the probe** — the INFORMATION check `101` names the reference and the deadline. The platform stores the probe and keeps the result **pending**.
8. **Reconcile** — when Resend receives an email at the inbound address, it notifies 37 Audits. The reference is looked up in the subject, then in the message body. A match completes the run as `SUCCESS` (`200`), or `WARNING` when the page showed no confirmation. No match before `deliveryTimeoutMinutes` completes it as `FAIL` (`401`).

## What it audits

Every rule reports its step either way: a `SUCCESS` check when the step is verified, or its `ERROR`, `FAIL` or `WARNING` check when it is not. A rule whose step was never reached, because an earlier one failed, reports nothing. The list of checks therefore shows how far the probe got and where it stopped. `SUCCESS` checks carry no recommendation and never change the overall status.

Codes `101`, `201`–`205`, `300`, `301`, `400`, `500` and `501` are emitted by the auditor Lambda; `200` and `401` are emitted by the platform when the forwarded email arrives or the deadline passes. CheckCode suffixes use status ranges: `100–199` information, `200–299` success, `300–399` warning, `400–499` fail, `500–599` error.

| CheckCode | Status | When it fires | Recommendation | Why it matters |
| - | - | - | - | - |
| <a id="37A-ContactFormAuditor-201" />`37A-ContactFormAuditor-201` | `SUCCESS` | `formPageUrl` and `formSelector` are both set. Message names the resolved form page and the selector. | — | — |
| <a id="37A-ContactFormAuditor-500" />`37A-ContactFormAuditor-500` | `ERROR` | `formPageUrl` or `formSelector` is blank or cannot be resolved. | Set `{keys}` in the Contact Form configuration of this URL: the page that hosts the form and the CSS selector of the form element. | — |
| <a id="37A-ContactFormAuditor-202" />`37A-ContactFormAuditor-202` | `SUCCESS` | The form page loaded in the browser and the browser got through it. Message gives the number of forms on the page. | — | — |
| <a id="37A-ContactFormAuditor-501" />`37A-ContactFormAuditor-501` | `ERROR` | The browser could not load the form page (`data.stage = load`), or threw while filling or submitting the form (`data.stage = interaction`). The message carries the browser's own error text. | Load: make sure `{formPageUrl}` is reachable from the auditor and finishes loading within 120 s. Interaction: check that nothing covers the form (cookie banner, modal) and that its fields stay in the page while it is filled. | — |
| <a id="37A-ContactFormAuditor-203" />`37A-ContactFormAuditor-203` | `SUCCESS` | `formSelector` matches a form on the page. Message gives the number of fields filled. | — | — |
| <a id="37A-ContactFormAuditor-300" />`37A-ContactFormAuditor-300` | `WARNING` | No element matches `formSelector` on the form page. Nothing is submitted. | Update the Form selector preference to the contact form's CSS selector, for example `form.wpcf7-form` or `#contact-form`. | While the selector matches nothing the contact form is never tested, so a form that stops delivering email goes unnoticed and leads are lost silently. |
| <a id="37A-ContactFormAuditor-204" />`37A-ContactFormAuditor-204` | `SUCCESS` | The form accepted the probe submission without a validation error. | — | — |
| <a id="37A-ContactFormAuditor-400" />`37A-ContactFormAuditor-400` | `FAIL` | The form showed a validation error after submit, or a field the browser reports as invalid blocked the submission. | Fix the validation reported as `"{errorText}"` or expose the required field (label, name or placeholder) so an automated probe can fill it. | A form that refuses a filled-in submission may be turning real visitors away as well, so leads are lost without any error reaching you; until it accepts the probe, email delivery cannot be verified either. |
| <a id="37A-ContactFormAuditor-101" />`37A-ContactFormAuditor-101` | `INFORMATION` | The probe was submitted and not rejected. `data` carries `messageId`, `inboundAddress`, `deadlineMinutes` and the fields that were filled. | — (the platform waits for the forwarded email). Shown only while the result is pending: the platform removes it when it adds `200` or `401`. | — |
| <a id="37A-ContactFormAuditor-205" />`37A-ContactFormAuditor-205` | `SUCCESS` | The page confirmed the submission with a success message, by removing the form, or by navigating. | — | — |
| <a id="37A-ContactFormAuditor-301" />`37A-ContactFormAuditor-301` | `WARNING` | The probe was submitted but no success message, form removal or navigation happened within 15 s. The platform still waits for the email. | Show a visible success message after submission so visitors know the message was sent. | Without a visible confirmation, visitors cannot tell whether their message went through, so they give up or send it again; it also hides a submission that silently failed. |
| <a id="37A-ContactFormAuditor-200" />`37A-ContactFormAuditor-200` | `SUCCESS` | The forwarded notification carrying the probe reference reached `contact-form-auditor@inbound.37audits.com`. Message: `Notification "{subject}" for probe {token} reached the inbound address {seconds}s after submission.` | — | — |
| <a id="37A-ContactFormAuditor-401" />`37A-ContactFormAuditor-401` | `FAIL` | No forwarded notification with the probe reference arrived within `deliveryTimeoutMinutes`. | Check the forward rule in the inbox that receives the form notifications, then the site's SMTP / `wp_mail` delivery (SPF, DKIM, DMARC). | — |

## Output documentation

| Status | Description | Test logic |
| - | - | - |
| **PENDING** | The probe was submitted; the platform is waiting for the forwarded email | The Lambda returned check `101`. The row completes when the email arrives or the deadline passes. |
| **SUCCESS** | The notification reached the inbound address and the page confirmed the submission | Forwarded email matched by reference before the deadline (`200`), with no `301` warning on the submission. |
| **WARNING** | Either nothing was submitted, or the email arrived but the page showed no confirmation | No form matched the selector (`300`); or the email arrived (`200`) after a submission with no visible confirmation (`301`). |
| **FAIL** | The form rejected the probe, or the email never arrived | Validation error visible after submit (`400`); or deadline passed without a matching email (`401`). |
| **ERROR** | The auditor could not run | Required preferences missing (`500`); the browser could not load the page or operate the form (`501`). |

## Risks and considerations

### Every run sends a real message

* The probe lands in the inbox that receives the form's notifications, once per run. Keep the schedule modest (weekly or daily) and consider a filter that labels or archives messages whose subject contains `37 Audits contact form probe`.
* Auto-responders and CRMs wired to the form will treat the probe as a lead. Exclude the `contact-form-auditor@inbound.37audits.com` address or the probe subject in those tools.

### What the auditor cannot pass

* **CAPTCHA, quiz questions and bot challenges** block the probe. The run ends with `400` or `301` rather than a false pass; use a form without a challenge, or whitelist the 37 Audits user agent in the challenge plugin.
* **Multi-step forms** are submitted only through their first step.
* A **required `select` whose only options are placeholders**, or a field with a format the heuristics do not know (for example a custom date picker), is reported as rejected (`400`) with the browser's validation message.

### Forwarding caveats

* Gmail requires the forwarding address to be confirmed with a code it emails to that address. 37 Audits reads it on the Resend received-emails page and relays it to you; until then, runs end as `401`.
* The reference is searched in the subject first and in the body second. Notification templates that include neither the subject field nor the message field cannot be matched: include at least the message in the template.
* The deadline covers the whole path: site mail server, your inbox, the forward hop, Resend and the platform. Fifteen minutes is generous for a healthy setup; raise `deliveryTimeoutMinutes` if your provider delays forwards.

### What this auditor does not check

* It does not read your inbox and never sees messages other than the ones you forward. It only receives mail sent to `contact-form-auditor@inbound.37audits.com`.
* It does not evaluate spam placement, SPF, DKIM or DMARC directly; see the DNS mail auditors for those.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.