Your options on Vercel and Netlify
| Approach | Good | Not so good |
|---|---|---|
Serverless function (/api or netlify/functions) | Full control | You maintain backend code, keep SMTP secrets in environment variables, and build spam and rate limiting yourself. |
| Netlify Forms | Built in on Netlify | Only works on Netlify, stores submissions in Netlify, and its email notifications don’t come from your own address. |
| FormSMTP | Plain HTML, same code on any host, sent through your own SMTP | You need an email account with SMTP access. |
1Create a FormSMTP project
Sign up free and add a project. Pick your email provider so the SMTP host and port fill in, enter your login, and click Test connection. Not sure which provider? Your existing mailbox works: see the Gmail or Zoho guides.
2Lock the project to your site
In Settings → Security, set Allowed websites to https://yoursite.com and Allowed recipients to your own address. Now the key in your page can only email you, only from your site, and only up to your hourly limit.
Allowed websites are matched exactly. Add your production domain and the default *.vercel.app or *.netlify.app address you use (written out in full). Preview deploys get new URLs each time, so test on production, or add a preview URL while you test.
3Add the form
Paste it into any page. It’s plain HTML, so it works the same in a hand-written site, Vite, Eleventy, Docusaurus or anything else that deploys static files.
<form action="https://app.formsmtp.com/api/v1/form/YOUR_API_KEY" method="POST">
<label>Name <input name="name" required></label>
<label>Email <input name="email" type="email" required></label>
<label>Message <textarea name="message" rows="5" required></textarea></label>
<input type="hidden" name="_subject" value="New message from my website">
<input type="hidden" name="_next" value="/thanks">
<input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off">
<button type="submit">Send message</button>
</form>Moving from Netlify Forms? Remove data-netlify="true", netlify-honeypot and the hidden form-name input, and set the action as above. Your field names stay the same.
4Keep the key out of your repo (optional)
With a framework, put the key in an environment variable in the Vercel or Netlify dashboard and read it at build time: VITE_FORMSMTP_KEY, NEXT_PUBLIC_FORMSMTP_KEY or PUBLIC_FORMSMTP_KEY, depending on your framework. The key still ends up in the built page, which is fine once the project is locked to your site.
5Deploy and test
git add .
git commit -m "Add contact form"
git push # Vercel and Netlify deploy on pushSubmit the form on your live domain. The message lands in your inbox, from your own address, and appears under Logs.
Framework guides
- Next.js contact form
- Astro contact form
- React contact form
- Vue & Nuxt contact form
- Svelte & SvelteKit contact form
FAQ
Do I need a Vercel or Netlify function to send email?
No. The form posts straight to FormSMTP over HTTPS, and FormSMTP sends through your SMTP account, so there’s no function to write, deploy or pay for.
Why does my form say the website isn’t allowed?
The page’s address isn’t in Allowed websites. Add the exact origin, such as https://yoursite.com or https://your-project.vercel.app, with no trailing path.
Does it work on Cloudflare Pages too?
Yes. It’s a plain HTML form, so it works on any static host.
Why did my message land in spam?
Usually the From address and the SMTP account don’t match, or the domain has no SPF/DKIM records. Send from the address you log in with, and check the Deliverability panel in FormSMTP’s Settings.