# Send email from Render

Render blocks outbound SMTP on free web services. Connections to ports 25, 465 and 587 never leave Render, so a mail library that sends through an SMTP server fails with `Connection timeout` or `ETIMEDOUT`, even when the host, username and password are right. Paid instance types can send over SMTP.

HTTPS isn't blocked on any instance type. There are two ways to send through Groundmail from [Render](https://render.com):

| Your app | Use | Code change |
|----------|-----|-------------|
| You control the code | The Groundmail API or an SDK, over HTTPS | Replace the send call |
| It only speaks SMTP (Ghost, n8n, a framework's mailer) | The SMTP relay on port 2525, which isn't one of the blocked ports | None: change the SMTP settings |

---

## Prerequisites

- A Groundmail account with a [verified sending domain](https://docs.groundmail.dev/domains). A subdomain such as `mail.yourdomain.com` works well.
- An API key (`gm_…`) from **API keys** in the dashboard.

---

## 1. Send with the API

In the Render dashboard, open your service's **Environment** page, add `GROUNDMAIL_API_KEY` with the key as its value, and save. Render redeploys the service with it. Then send with an SDK.

**Node.js**

```bash
npm install groundmail
```

```js
import { Groundmail } from 'groundmail'

const groundmail = new Groundmail(process.env.GROUNDMAIL_API_KEY)

await groundmail.emails.send({
  from: 'App <no-reply@mail.yourdomain.com>',
  to: 'user@example.com',
  subject: 'Reset your password',
  html: '<p>Click the link to reset your password.</p>',
})
```

Already on Nodemailer? Swap the SMTP transport for the [Nodemailer transport](https://docs.groundmail.dev/frameworks/node), which sends over HTTPS, and keep your `sendMail` calls.

**Python**

```bash
pip install groundmail
```

```python
import os
from groundmail import Groundmail

groundmail = Groundmail(os.environ["GROUNDMAIL_API_KEY"])
groundmail.emails.send(
    from_="App <no-reply@mail.yourdomain.com>",
    to="user@example.com",
    subject="Reset your password",
    html="<p>Click the link to reset your password.</p>",
)
```

Go, PHP and Ruby have SDKs too: see [SDKs](https://docs.groundmail.dev/sdks/python). Any other language can call `POST https://api.groundmail.dev/emails` with the key: see the [API reference](https://docs.groundmail.dev/api/emails).

---

## 2. Keep SMTP

If your app can only send over SMTP, point it at Groundmail's relay on port **2525**:

| Setting | Value |
|---------|-------|
| Host | `smtp.groundmail.dev` |
| Port | `2525` |
| Encryption | STARTTLS |
| Username | `groundmail` |
| Password | An SMTP credential from **SMTP** in the dashboard |

Add these as environment variables on the service, using the names your app reads. On a paid instance type, port `587` works too. See [SMTP](https://docs.groundmail.dev/smtp).

---

## Troubleshooting

| What you see | What to do |
|--------------|------------|
| `Connection timeout` or `ETIMEDOUT` when sending | Your app is connecting to port 25, 465 or 587 from a free web service. Switch to the API, or change the port to `2525`. |
| `401` from the API | The service doesn't have `GROUNDMAIL_API_KEY`, or it was added after the last deploy. Check the **Environment** page and redeploy. |
| `403` with a domain error | The `from` address isn't on a verified domain. See [Domains](https://docs.groundmail.dev/domains). |
