Security & Spam Protection
Protect your forms from spam and malicious submissions.
- Honeypot Field
- Honeypot Best Practices
- Domain Restrictions
- Domain Configuration
- Language Detection
- Supported Languages
- Field Whitelisting
- Benefits
- File Upload Security
- Blocked Extensions
- Blocked MIME Types
- File Storage
- Combining Protections
- Protection Layers
- reCAPTCHA Integration
Honeypot Field
Add a hidden field that bots will fill but humans won't:
<form action="/api/inbox/submit/{form-token}" method="POST">
<!-- Honeypot - hidden from users -->
<div style="display: none;">
<input type="text" name="data[website]" tabindex="-1" autocomplete="off">
</div>
<label for="email">Email</label>
<input type="email" name="data[email]" required>
<label for="message">Message</label>
<textarea name="data[message]" required></textarea>
<button type="submit">Send</button>
</form>
In your form settings, set Honeypot to website. If the field contains any value, the submission is silently discarded (returns success to fool bots).
Honeypot Best Practices
- Use realistic field names like
website,url,company - Hide with CSS (
display: none) nottype="hidden" - Add
tabindex="-1"to prevent keyboard navigation - Add
autocomplete="off"to prevent autofill
Domain Restrictions
Limit form submissions to specific referrer domains:
- In form settings, add allowed domains to Domains (e.g.,
example.com,www.example.com) - Submissions from other domains receive a
412 Precondition Failederror
This prevents forms from being submitted from unauthorized websites.
Domain Configuration
example.com
www.example.com
staging.example.com
Include all domains and subdomains where your form is hosted. Don't include the protocol (http/https).
Language Detection
Filter submissions by detected language to reduce foreign-language spam:
- In form settings, add allowed languages to Languages (e.g.,
en,de,fr) - Text fields longer than 50 characters are analyzed
- If the detected language doesn't match the whitelist, submission is rejected
Supported Languages
| Code | Language | Code | Language |
|---|---|---|---|
en |
English | fr |
French |
de |
German | es |
Spanish |
it |
Italian | pt |
Portuguese |
nl |
Dutch | pl |
Polish |
ru |
Russian | zh |
Chinese |
ja |
Japanese | ko |
Korean |
ar |
Arabic | hi |
Hindi |
Full list: am, ar, az, be, bg, bn, ca, cs, da, de, el, en, es, et, eu, fa, fi, fr, gu, he, hi, hr, hu, hy, is, it, ja, ka, kn, ko, ku, lo, lt, lv, ml, mr, ms, nl, no, or, pa, pl, pt, ro, ru, sk, sl, sq, sr, sv, ta, te, th, tl, tr, uk, ur, vi, yo, zh
Field Whitelisting
Only accept specific fields by adding field names to Fields in security settings:
name
email
message
phone
Any field not in this list is ignored. Leave empty to accept all fields.
Benefits
- Prevents injection of unexpected data
- Reduces database storage
- Blocks additional fields added by bots
File Upload Security
Inbox automatically blocks dangerous file types.
Blocked Extensions
bat- Batch filesexe- Executablessh- Shell scriptsphp,phar,phtml,phps- PHP fileshtm,html,xhtml- HTML fileshtaccess- Apache config
Blocked MIME Types
application/x-httpd-phpapplication/x-phptext/x-phptext/htmlapplication/xhtml+xml
File Storage
Files are stored in:
/storage/uploads/inbox/uploads/{form-id}/{date}/
Combining Protections
For maximum security, enable multiple layers:
// Form settings
[
'honeypot' => 'website',
'domains' => ['example.com', 'www.example.com'],
'languages' => ['en', 'de'],
'fields' => ['name', 'email', 'message']
]
Protection Layers
- Honeypot - Catches automated bots
- Domain restrictions - Prevents cross-site submissions
- Language detection - Blocks foreign spam
- Field whitelisting - Limits accepted data
reCAPTCHA Integration
For additional protection, implement reCAPTCHA client-side and validate server-side:
// Submit with reCAPTCHA token
async function submitWithRecaptcha(form) {
const token = await grecaptcha.execute('your-site-key', { action: 'submit' });
const formData = new FormData(form);
formData.append('data[recaptcha_token]', token);
const response = await fetch(form.action, {
method: 'POST',
body: formData
});
return response.json();
}
Validate in a inbox.submit.before event:
$app->on('inbox.submit.before', function($form, &$record) {
$token = $record['data']['recaptcha_token'] ?? null;
if (!$token) {
throw new \Exception('reCAPTCHA required');
}
// Verify with Google
$response = file_get_contents(
'https://www.google.com/recaptcha/api/siteverify?' .
http_build_query([
'secret' => $_ENV['RECAPTCHA_SECRET'],
'response' => $token
])
);
$result = json_decode($response, true);
if (!$result['success'] || $result['score'] < 0.5) {
throw new \Exception('reCAPTCHA validation failed');
}
// Remove token from stored data
unset($record['data']['recaptcha_token']);
});