blockHeadless and block list
Besides allowed origins and Turnstile, Frontmail has two lightweight filters that you can enable in the SDK, in the dashboard, or both. The dashboard settings live on the Security page (owners and admins can change them).
blockHeadless
Section titled “blockHeadless”Rejects sends from automated, headless browsers (Puppeteer, Playwright, Selenium and similar), which are often used by form spam bots.
init({ publicKey: 'pk_4f2a…', blockHeadless: true });- In the SDK, the check runs in the browser before any request is made:
send()rejects with aBlockedErrorwith codeheadless_blocked. No request, no credit. - In Security → Abuse protection → Block headless browsers, the API also rejects public-key requests whose user agent identifies a headless or automated browser (HeadlessChrome, Puppeteer, Playwright, Selenium, PhantomJS, jsdom …). Use both.
Legitimate users are not affected. Your own end-to-end tests are – send with a private key in tests, or disable the option on test environments.
Block list
Section titled “Block list”A block list rejects sends whose recipient – or the value of a chosen param – matches an entry. Typical uses: a persistent spammer’s address, disposable email domains, a competitor scraping your forms.
init({ publicKey: 'pk_4f2a…', blockList: { list: ['spam@example.net', 'mailinator.com'], watchVariable: 'email', // param or form field to check },});- Values are compared case-insensitively after trimming. An entry without
@(or starting with@, like@mailinator.com) matches every address on that domain; other entries match an email address or the watched value exactly. - In the SDK, the check runs before the request; a match rejects with
BlockedErrorcoderecipient_blocked. - In Security → Block list, owners and admins enter Blocked values (one per line, up to
1,000) and optionally a Parameter to check (e.g.
email, dotted paths work too). The API enforces the list for every request – public or private key, including outdated clients or scripts that don’t use the SDK – before any credit is used. It checks the rendered recipients (To/CC/BCC) and the value of the parameter to check.
The SDK list is visible in your page source; keep sensitive entries only in the dashboard list.
limitRate (client-side throttle)
Section titled “limitRate (client-side throttle)”The SDKs can also prevent a single browser from sending too often – for example, a visitor double-clicking the submit button:
init({ publicKey: 'pk_4f2a…', limitRate: { id: 'contact', throttle: 10_000 } });A second send within 10 seconds from the same page (or the same id) is rejected locally with
BlockedError code rate_limited. This is a convenience, not a security measure – see
Rate limits for server-side limits.
Strict parameters
Section titled “Strict parameters”Security → Abuse protection → Strict parameters rejects requests that contain parameters the template’s schema doesn’t define (see Parameters). Bots that fill in every field of a form, including made-up ones, are stopped before they use credits.