Guides

Replit send email: an HTTPS API through your own SMTP

Yes, a Replit app can send email. The dependable way is an HTTPS call from your server code, with the key in Replit Secrets. Here’s Node.js and Python code, the publishing step people miss, and an option for static sites.

Last updated November 3, 2026

SMTP or an HTTPS API?

Replit’s documentation doesn’t list outbound SMTP ports as blocked, so an SMTP library may work. An HTTPS API is still the simpler choice: it’s the same kind of request your app already makes to other services, there’s no SMTP password stored in your Replit project, and you get a clear JSON error when something fails. Replit also limits how many outgoing connections an app can open in a given period, which favors one quick HTTPS request over holding SMTP sessions open.

FormSMTP gives you that HTTPS API while still sending through your own SMTP account, so the email comes from your Gmail, Google Workspace, Microsoft 365, Zoho or hosting mailbox. Replit Agent also has connectors for several email services; FormSMTP is the option for any mailbox 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. Any mailbox with SMTP access works: Gmail or Google Workspace, Microsoft 365, Zoho, your web host’s mailbox, or a sending service. Personal Outlook.com and Hotmail addresses can’t be used, because Microsoft only lets them sign in with OAuth.

In Settings → Security, set Allowed recipients to your own address if the app only notifies you, or to your users’ domain (for example @yourcompany.com) if it emails a known group. Set Max API emails per hour to what you expect to send. Copy the API key (it starts with fs_).

2Store the key in Replit Secrets

Open Secrets in your project, select New Secret, and add FORMSMTP_API_KEY with your API key. Replit encrypts it and exposes it to your code as an environment variable. You can also ask Replit to open its secure secret form; either way, keep the key out of chat messages and Git.

Secrets you add in the editor don’t carry over to your published app. Add FORMSMTP_API_KEY again in the Publishing pane. Secrets aren’t available to Static deployments at all; see the form option below.

3Add a route that sends the email

A small contact endpoint for your app. It emails you, uses the visitor’s address as reply-to, and drops bots that fill in a hidden field. Replit passes the port to use in the PORT environment variable.

js
// index.js (npm install express)
import express from "express";

const app = express();
app.use(express.json());
app.use(express.urlencoded({ extended: false }));
app.use(express.static("public"));

async function sendEmail(message) {
  const res = await fetch("https://app.formsmtp.com/api/v1/send", {
    method: "POST",
    headers: {
      Authorization: `Bearer ${process.env.FORMSMTP_API_KEY}`,
      "Content-Type": "application/json",
    },
    body: JSON.stringify(message),
  });
  const data = await res.json();
  if (!data.success) throw new Error(data.error);
  return data.messageId;
}

app.post("/api/contact", async (req, res) => {
  const { name, email, message, website } = req.body;
  if (website) return res.json({ ok: true }); // honeypot
  if (!name || !email || !message) return res.status(400).json({ ok: false, error: "Please fill in every field." });
  try {
    await sendEmail({
      to: "you@yourdomain.com",
      replyTo: email,
      subject: `New message from ${name}`,
      text: message,
    });
    res.json({ ok: true });
  } catch (err) {
    console.error("FormSMTP:", err.message); // the details stay in your logs
    res.status(502).json({ ok: false, error: "Sorry, your message couldn't be sent. Please try again later." });
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, "0.0.0.0", () => console.log(`Listening on ${PORT}`));

The same sendEmail() call works for anything else your app sends: welcome emails, receipts, alerts. Just change to, and make sure Allowed recipients covers it.

4Test, then publish

Point your page’s form at /api/contact (a plain <form method="POST" action="/api/contact"> works, or a fetch() call that sends JSON), open the Preview and send yourself a message. It arrives from your own address and shows up under Logs in FormSMTP.

When it works, open Publishing, choose Autoscale or Reserved VM (they run a server; Static doesn’t), add FORMSMTP_API_KEY to the production secrets, and publish. Check the Logs tab in the Publishing pane if anything fails.

Static deployment? Use the form endpoint

A Static deployment serves files only and can’t read Secrets, so it can’t hold an API key. Post the form straight to FormSMTP with the public form key instead. Set Allowed websites to https://your-app.replit.app and any custom domain, and Allowed recipients to your address.

html
<form action="https://app.formsmtp.com/api/v1/form/YOUR_FORM_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 Replit site">
  <input type="text" name="_gotcha" style="display:none" tabindex="-1" autocomplete="off">
  <button type="submit">Send message</button>
</form>

Want an inline “Thanks!” message instead of a thank-you page? See the JavaScript guide.

Troubleshooting

  • Works in the editor, fails when published. The production deployment doesn’t have FORMSMTP_API_KEY. Add it in the Publishing pane and republish.
  • “Missing API key”. The environment variable is empty: check the secret’s exact name, and that you’re not on a Static deployment.
  • “That is a form key”. You used the fk_ key with /send. Server code needs the fs_ API key.
  • “Recipient not allowed for this project”. The to address isn’t covered by Allowed recipients.
  • A 502 with an SMTP message. Your mail server refused the message, and the error says why. Usually it’s the password (Gmail needs an App Password) or a From address that doesn’t match the account.

FAQ

Can Replit send emails?

Yes. Any Replit app with a server can call an email API over HTTPS. With FormSMTP, that call sends through your own SMTP account, so the email comes from your own address.

Does Replit block SMTP ports?

Replit’s documentation doesn’t say so. We still recommend an HTTPS API: it uses the same kind of connection as the rest of your app, and your SMTP password never has to live in your Replit project.

Can I send from my Gmail account?

Yes. Connect Gmail in FormSMTP with an App Password (see the Gmail guide), and your Replit app sends through it via the API.

Is the free plan enough?

For notifications and contact forms, usually. FormSMTP’s free plan includes 1,000 emails a month, and Pro is $5 a month for 50,000.

More guides

Get a Founding Pass

10,000 emails a month, free for your first year. Pass No. 0008 is next: 1,993 of 2,000 left, no card.