Email for frontend developers
Send email straight from your frontend.Pay for your peaks, not all year.
Connect the email provider you already use, build HTML templates with typed parameters and call send() from the browser. When a seasonal rush outgrows your quota, nothing is dropped – messages wait in a hold queue and go out the moment you top up.
Free plan with 300 emails a month. No card required.
contact.js
import { init, sendForm } from '@frontmail/browser';
init({ publicKey: 'pk_live_2Jx8…' });
const form = document.querySelector('#contact');
form.addEventListener('submit', async (event) => {
event.preventDefault();
const { status } = await sendForm('svc_default', 'tpl_contact', form);
// 'queued' – or 'held' when you're out of credits. Never dropped.
});ContactForm.tsx
import { FrontmailProvider, useSendEmail } from '@frontmail/react';
function ContactForm() {
const { send, status } = useSendEmail('svc_default', 'tpl_contact');
return (
<form
onSubmit={(event) => {
event.preventDefault();
const { email, message } = Object.fromEntries(new FormData(event.currentTarget));
send({ email, message });
}}
>
<input name="email" type="email" required />
<textarea name="message" required />
<button disabled={status === 'sending'}>Send</button>
</form>
);
}
const options = { publicKey: 'pk_live_2Jx8…' };
// <FrontmailProvider options={options}><ContactForm /></FrontmailProvider>ContactForm.vue
<script setup lang="ts">
import { reactive } from 'vue';
import { useSendEmail } from '@frontmail/vue';
const { send, status } = useSendEmail('svc_default', 'tpl_contact');
const form = reactive({ email: '', message: '' });
</script>
<template>
<form @submit.prevent="send(form)">
<input v-model="form.email" type="email" required />
<textarea v-model="form.message" required />
<button :disabled="status === 'sending'">Send</button>
</form>
</template>ContactForm.svelte
<script lang="ts">
import { createFrontmail, frontmailForm } from '@frontmail/svelte';
const frontmail = createFrontmail({ publicKey: 'pk_live_2Jx8…' });
const { status } = frontmail;
</script>
<form use:frontmailForm={{ serviceId: 'svc_default', templateId: 'tpl_contact', frontmail }}>
<input name="email" type="email" required />
<textarea name="message" required></textarea>
<button disabled={$status === 'sending'}>Send</button>
</form>order-confirmation.ts
import { Frontmail } from '@frontmail/node';
const frontmail = new Frontmail({ privateKey: process.env.FRONTMAIL_PRIVATE_KEY });
await frontmail.send({
serviceId: 'svc_transactional',
templateId: 'tpl_order_confirmation',
params: {
customer_name: 'Jana',
order_id: 'A-1042',
items: [{ title: 'Ceramic mug', qty: 2 }],
},
});How it works
From form to inbox in three steps
Connect a service
Plug in SMTP, Gmail, Outlook or a transactional provider like Mailgun, Postmark or SES. Credentials are encrypted and checked daily.
Design an HTML template
Write full HTML with Handlebars, define typed parameters and watch a live preview on desktop, mobile, light and dark.
Send from your code
Call send() with your public key from any framework – or from your server with a private key. Retries and idempotency are built in.
No lost email
Running out of credits never means losing a message
Quotas run out and OAuth tokens expire. Frontmail treats both as a reason to wait, never a reason to drop an email.
frontmail.send()- Credits available?
- YesQueued and sentQuota first, then the pack that expires soonest.
- NoOverdraft buffer+10% of your monthly quota on paid plans, billed on the next invoice.
- Held, not droppedThe API answers 202 with status "held". Messages wait up to 3 days on Free or 14 days on paid plans.
- Released automaticallyA pack purchase, auto top-up, upgrade or new billing period sends held mail, oldest first.
- Provider rejects your credentials?
- Backup service takes overTemplates can name a fallback service for auth or permanent errors.
- Held until fixedWithout a backup, messages are held and resent once the service is healthy again.
Hold queue
No credit? The request is accepted and stored. You get an email before anything expires, and you can release or discard held messages in bulk.
Overdraft buffer
Paid plans get 10% of their monthly quota as a buffer, so a slightly busier month just keeps sending.
Auto top-up
Pick a pack and a threshold – or top up on the first held message. Spending caps keep surprises off your card.
Health checks & failover
Every service is checked daily and on every auth error. Broken credentials trigger an alert, a dashboard banner and the backup service.
Usage alerts at 50, 80 and 100% and on your first held message.
Credit packs
Keep a small plan. Buy packs for the busy months.
Packs are one-off purchases valid for 3–12 months and work on every plan, Free included. Enter your expected volume per month and we will find the cheapest mix.
5,000 emails
valid 3 months
$10
$2 per 1,000
Buy this pack25,000 emails
valid 6 months
$39
$1.56 per 1,000
Buy this pack100,000 emails
valid 12 months
$129
$1.29 per 1,000
Buy this pack
Our recommendation
Free plan
Packs to buy
- January: 1× 5,000-email pack$10
- March: 1× 25,000-email pack$39
- July: 1× 25,000-email pack$39
- December: 1× 25,000-email pack$39
- Plan
- $0
- Packs
- $127
- Total for the year
- $127
A plan that covers your 25,000-email peak all year (Business 50k) would cost $468. You save $341 (73%).
Start freeFeatures
Everything a contact form needs – and a lot more
HTML templates with live preview
Full HTML, Handlebars conditions and loops, typed parameters with validation, versions with diff and rollback.
Your provider, your reputation
SMTP, Gmail, Outlook, Mailgun, SES, Postmark, Mailjet, Brevo and Resend, with a backup service per template.
Spam protection built in
Cloudflare Turnstile on all your forms in one click, domain allowlist, per-IP and per-key rate limits, headless-browser blocking and anomaly alerts.
Searchable history
Rendered content, parameters and an event timeline for every message. Resend in one click, export to CSV.
Delivery tracking
Delivered, bounced, complained, opened and clicked – straight from your provider’s webhooks, with hard bounces suppressed automatically.
Teams, roles and MFA
Invite teammates as owner, admin, developer, viewer or billing. TOTP, backup codes and an audit log for sensitive actions.
SDKs with typed parameters
Vanilla JS, React, React Native, Vue, Svelte and Node. Run npx frontmail types and your editor knows every template parameter.
Errors that explain themselves
One error format with a code, a message and a link to the docs. SDKs retry network errors and 5xx without sending twice.
Providers
Works with the email service you already have
Personal mailboxes for small sites, transactional providers for scale – with a step-by-step guide for each one in the docs.
- SMTPSeznam, Zoho, your own server…SMTP
- GmailOAuth
- Outlook / Microsoft 365OAuth
- Amazon SESAPI
- MailgunEU / USAPI
- PostmarkAPI
- MailjetAPI
- BrevoAPI
- ResendAPI
Why not call your provider’s API directly?
Amazon SES, Mailgun, Postmark or the Gmail API deliver the email. Everything around a public form – keys, bots, outages, templates, history – is left to your own backend. Frontmail is that backend, and it keeps sending through your provider.
| What you need | Provider API on its own | With Frontmail |
|---|---|---|
| Sending from a website or mobile app | Needs a secret API key or OAuth token, which must never reach the browser – so you build and run your own backend. | A public key and SDKs for the web, React Native, Kotlin and Swift. No server to build or run. |
| Stopping bots on a public form | Your backend has to add CAPTCHA, rate limits and origin checks. | Turnstile, domain allowlist, per-IP and per-key limits, and locked content whenever the recipient comes from the form. |
| Expired credentials or a provider outage | The send fails and your code decides what happens to the email. | Daily health checks, a backup service per template, and failed emails held and sent after you reconnect. |
| Templates | Each provider has its own template format and API – or the HTML lives in your code. | HTML editor with live preview, typed parameters, versions and language variants. The same template works with every provider. |
| History and delivery events | Each provider reports events its own way (webhooks, SNS notifications) and you store them yourself. | One searchable history with delivered, bounced, complained, opened and clicked for every provider. |
| Changing provider | Rewrite the integration. | Switch the service in the dashboard – your code stays the same. |
Frontmail does not replace your provider – emails still go out from your domain through your account. If you already run a backend that sends large volumes, calling your provider directly can cost less. Product names are trademarks of their owners.
Moving from EmailJS
Change one import
The @frontmail/emailjs-compat package exposes the same functions as @emailjs/browser. Recreate your service and template in Frontmail, swap the import, keep your code.
- 1Connect your email service and import your template HTML.
- 2Replace the package import and your keys.
- 3Ship. Optionally switch to @frontmail/browser later for typed parameters.
- import emailjs from '@emailjs/browser';
+ import emailjs from '@frontmail/emailjs-compat';
emailjs.init({ publicKey: 'YOUR_PUBLIC_KEY' });
emailjs
.sendForm('YOUR_SERVICE_ID', 'YOUR_TEMPLATE_ID', '#contact-form')
.then((response) => console.log('SUCCESS', response.status));How the two services compare
| Situation | EmailJS* | Frontmail |
|---|---|---|
| Monthly quota used up | Further requests are not sent until the quota resets or the plan changes. | Requests are accepted and held for up to 14 days (3 days on Free), then sent automatically after a top-up. |
| REST API rate limit | 1 request per second. | 2–50 requests per second depending on plan, plus a batch endpoint. |
| Seasonal peak | Move to a higher plan. | Keep your plan and buy a credit pack valid for 3–12 months. |
* EmailJS information as of September 2026, per emailjs.com/pricing. EmailJS is a trademark of its owner; Frontmail is not affiliated with EmailJS.
Compare Frontmail with other servicesPricing
Simple plans. Packs for the peaks.
Start free, upgrade when you need more. Yearly billing saves 20%.
Free
300 emails / month
$0/ month
Free forever
Start free- 3 templates
- No attachments
- History: 7 days
- 1 user
- 2 requests / second
- Hold queue: 3 days
- Domain allowlist & Turnstile
- “Sent via Frontmail” footer
Starter
3,000 emails / month
$7/ month
$84 billed yearly
Choose Starter- 10 templates
- Attachments up to 1 MB per request
- History: 30 days
- 1 user
- 5 requests / second
- Hold queue: 14 days
- 10% overdraft buffer
- Domain allowlist & Turnstile
- Most popular
Pro
10,000 emails / month
$15/ month
$180 billed yearly
Choose Pro- Unlimited templates
- Attachments up to 5 MB per request
- History: 90 days
- 5 users
- 20 requests / second
- Hold queue: 14 days
- 10% overdraft buffer
- Domain allowlist & Turnstile
Business
50,000 emails / month
$39/ month
$468 billed yearly
Choose Business 50k- Unlimited templates
- Attachments up to 25 MB per request
- History: 180 days
- Unlimited users
- 50 requests / second
- Hold queue: 14 days
- 10% overdraft buffer
- Domain allowlist & Turnstile
Business tiers
Credit packs
One-off purchase, available on every plan. Used after your monthly quota, soonest-expiring first.
Compare all plans
| Plan | Free | Starter | Pro | Business 50k | Business 100k | Business 200k |
|---|---|---|---|---|---|---|
| Price / month | $0 | $7 | $15 | $39 | $71 | $127 |
| Emails / month | 300 | 3,000 | 10,000 | 50,000 | 100,000 | 200,000 |
| Templates | 3 | 10 | Unlimited | Unlimited | Unlimited | Unlimited |
| Attachments | – | 1 MB | 5 MB | 25 MB | 25 MB | 25 MB |
| History | 7 days | 30 days | 90 days | 180 days | 180 days | 180 days |
| Users | 1 | 1 | 5 | Unlimited | Unlimited | Unlimited |
| Rate limit | 2 rps | 5 rps | 20 rps | 50 rps | 50 rps | 50 rps |
| Overdraft | – | 10% | 10% | 10% | 10% | 10% |
| Hold queue | 3 days | 14 days | 14 days | 14 days | 14 days | 14 days |
Prices exclude VAT. EU businesses with a valid VAT ID are invoiced under reverse charge.
Billing questions
Does unused quota roll over?
No – the monthly quota resets every billing period. Credit packs are different: they stay valid for 3, 6, or 12 months, so buy them when you need them.
What happens when I run out of credits?
Paid plans first use the overdraft buffer. After that, new messages are held (not rejected) and go out automatically once you buy a pack, auto top-up kicks in, you upgrade or a new period starts. If you prefer hard failures, switch your organization to reject mode and the API returns 402.
How is the overdraft billed?
Overdraft credits you actually used are added to your next invoice. Unused overdraft costs nothing.
Can I change or cancel my plan?
Upgrades apply immediately with a prorated charge. Downgrades and cancellations take effect at the end of the paid period. Packs you have already bought remain valid until they expire.
Which currency will I pay in?
Customers billed in the EU pay in euros, everyone else in US dollars. VAT is calculated at checkout based on your billing country and VAT ID.
How can I pay?
By card, Apple Pay or Google Pay, and SEPA Direct Debit where available. Every payment comes with an invoice you can download from the dashboard.
FAQ
Frequently asked questions
Is it safe to put a public key in my frontend?
Yes. A public key can only send with your templates, only from domains on your allowlist, and behind Turnstile and rate limits. Private keys are for servers only and never belong in browser code.
Do I need my own email provider?
Yes – Frontmail sends through a service you connect, so messages come from your domain and your reputation. A personal Gmail or Outlook account is fine for a small site.
What does the Free plan include?
300 emails a month, 3 templates, spam protection and 7 days of history. Emails include a small “Sent via Frontmail” footer. You can buy credit packs on Free too.
Where is my data stored?
In the AWS eu-central-1 region (Frankfurt, Germany). Provider credentials are encrypted with AWS KMS. Message history is kept only as long as your plan allows.
What if my Gmail or Outlook connection expires?
We check every service daily and immediately after an authentication error. You get an email and a dashboard banner; messages use your backup service or wait as held until you reconnect.
Can I send from a server too?
Yes. The Node SDK and REST API accept a private key, which skips the origin check and CAPTCHA and unlocks batch sending of up to 100 messages per request.
Why use Frontmail instead of Amazon SES, Mailgun or the Gmail API?
You use them together. Those APIs need a secret key, so they can’t be called from a browser or an app. Frontmail sits in between: it keeps the credentials, protects your form from bots, renders your templates and sends through the provider you connect.
Can I send emails with Amazon SNS?
SNS is a notification service: its email subscriptions send plain-text notifications to addresses that confirmed the subscription. That suits alerts, not emails for your customers. For email from your domain, connect Amazon SES – Frontmail turns its SNS delivery notifications into message statuses.
Ship the form today. Stop worrying about the busy season.
Free plan, no card, full API. Upgrade or add a pack whenever your traffic says so.