Most contact forms only email you. When the email fails — PHP mail switched off by the host, an SMTP password that expired, a notification filed as spam — the message is gone, and the visitor thinks you got it.
Letterkeep Contact Form saves each entry in its own database table first. Then it emails you, and records what happened: every entry is marked
Sent to your mail server,
Failed with the error your server gave, or
Not sent. A failed notification can be resent from the entry, and the settings screen can send a test email and tells you whether the From address is on your site's own domain.
Forms
- Fields: text, email, phone, web address, number, date, paragraph, dropdown, choose one, checkboxes and a consent box — each with a label, required or not, placeholder, help text and full or half width.
- Four templates: Contact form, Quote request, Callback request and Newsletter signup.
- The block Letterkeep Form and the shortcode
[letterkeep id="…"].
- The form's stylesheet and script load only on pages that show a form, and need no jQuery.
- Works without JavaScript and behind page caching: the form posts to its own page, and a fresh security token is fetched when a visitor starts typing on a cached page.
- Accessible: every field has a label, required fields say so in words, and errors are linked to their fields with a summary at the top.
- After sending, the visitor sees your thank-you message, or goes to a page on your site that you choose.
Entries
- Every entry is saved before any email is sent, with the page it was sent from.
- Letterkeep → Entries: search, a filter per form, unread and read, spam, delete, one entry at a time, and CSV export per form of exactly the entries the list shows.
- The CSV export puts an apostrophe in front of = + - or @ wherever a spreadsheet could start a formula, also when spaces or quotation marks stand before it: at the start of a value, and after a semicolon, tab or line break inside it, where a Danish, German or French Excel begins a new cell.
- If an entry cannot be saved, the email still goes out with the whole message and a line saying so; if neither works, the visitor is told the message was not sent.
Email
- Send to one or more addresses, written plainly or as
Name <address>. The subject and message can use {field:name}, {all_fields}, {form_title}, {page_url}, {site_title} and {admin_email}.
- From is wordpress@ your site's domain unless you choose another address, and the settings screen warns you when the address you chose is not on your site's domain. Reply-To is the visitor's email address in every new form that has an email field, so pressing Reply answers them.
- An optional automatic reply to the visitor, off by default.
- Send test email shows your mail server's own answer, and a notice on Letterkeep's screens counts notifications that failed.
Spam, without a puzzle
- Always on, without any account: a honeypot field, a check that the form was not sent within 3 seconds of loading, and at most 5 entries from one IP address per 10 minutes.
- Optional: Cloudflare Turnstile, hCaptcha or Google reCAPTCHA v3, with your own keys.
- If the CAPTCHA service does not answer, the entry is taken in and marked, instead of being turned away. If the service refuses your key, or its widget shows a visitor an error instead of its check (most often a key that does not list your domain), a notice tells you, and the entry is kept.
- While the CAPTCHA is passing your other visitors, a visitor who presses Send without answering a Turnstile or hCaptcha challenge in front of them is asked to confirm and press Send again, keeping what they typed — and a form that arrives without any answer the visitor could have given (JavaScript off, a blocked script, a widget that showed its own error, a reCAPTCHA v3 that never answered) is not turned away, but kept under Spam with that reason. When the CAPTCHA has passed no one for about a day, or since you changed its key or service, entries are taken in without the check, and a notice says it is not running on your forms.
- Everything caught as spam is kept under Spam for 30 days (at most 1,000 entries), with the reason — so a real message caught by mistake is not lost.
Switch from Contact Form 7
The Import button on Letterkeep → Forms reads your Contact Form 7 forms — Contact Form 7 does not need to be active. For each form it first shows what will come along and what will not, with a reason for every tag it leaves out. It imports the fields, the recipients, the subject and message, Mail (2) as the automatic reply, and your messages; if you say so, it also uses Contact Form 7's reCAPTCHA or Turnstile keys. It lists the pages where a Contact Form 7 shortcode or block is used, so you know which ones to update. Nothing in Contact Form 7 or on your pages is changed.
Entries you collected with Flamingo or CFDB7 are not imported; they stay where they are.
Forms in and out
Export forms as a file and import them on the next site — fields, email settings and messages included.
Privacy
- A consent box stores the text the visitor agreed to with the entry.
- Visitors' IP addresses are not saved unless you turn that on.
- Old entries can be deleted automatically after a number of days you choose.
- WordPress' own Export Personal Data and Erase Personal Data tools find entries by email address, and Letterkeep suggests text for your privacy policy.
- Deleting the plugin keeps your forms and entries, unless you tick "Delete all Letterkeep data when the plugin is deleted".
Letterkeep Pro
Letterkeep Pro is a paid add-on that sends each entry on to Mailchimp, Brevo, Kit, MailerLite, ActiveCampaign, HubSpot or a webhook, using API keys from your own accounts. When a connection stops accepting entries — a revoked key, an outage — Pro keeps them, emails you, and sends them again once it works. This plugin mentions it in five places: a Newsletter & CRM tab under Letterkeep → Settings, a Send entries to your CRM button on the Entries screen once entries arrive, one line on new forms that you can hide, a link in the plugin's row on the Plugins screen, and — only when a Contact Form 7 form you import sent contacts to Brevo — one line in that form's import report. Everything in this plugin stays free.