# Send email from Coolify

Two things on a [Coolify](https://coolify.io) server send email: the apps you deploy, and Coolify itself (deployment, backup and server alerts). Both can send through Groundmail from your own domain. Apps use the API key or the SMTP relay; Coolify's notifications use the SMTP relay.

---

## Prerequisites

- A Groundmail account with a [verified sending domain](https://docs.groundmail.dev/domains). A subdomain such as `mail.yourdomain.com` works well.
- For apps: an API key (`gm_…`) from **API keys**, or an SMTP credential if the app only speaks SMTP.
- For Coolify's notifications: an SMTP credential (`gmsmtp_…`) from **SMTP** in the dashboard. The password is shown once, so copy it.

---

## Apps you deploy

### Add the API key

1. In Coolify, open the application and select **Environment Variables**.
2. Add `GROUNDMAIL_API_KEY` with your key as the value. In **Developer view** you can paste it as a `.env` line instead.
3. Your app only needs the key at runtime, so set **Build time** to *Not available during build*. That keeps it out of the build logs and image layers.
4. Save, then **Restart** the app. (A **Redeploy** is only needed when a build-time value changes.)

Production and preview deployments have separate variable sections; add the key to each one that sends.

For a Docker Compose app, reference the variable in your compose file and Coolify lists it under **Environment Variables** for you to fill in. `:?` makes Coolify refuse to deploy while it's empty:

```yaml
services:
  app:
    environment:
      - GROUNDMAIL_API_KEY=${GROUNDMAIL_API_KEY:?}
```

### Send

**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>',
})
```

Other stacks: [Python](https://docs.groundmail.dev/sdks/python), [Go](https://docs.groundmail.dev/sdks/go), [PHP](https://docs.groundmail.dev/sdks/php), [Ruby](https://docs.groundmail.dev/sdks/ruby), [Laravel](https://docs.groundmail.dev/frameworks/laravel), [Rails](https://docs.groundmail.dev/frameworks/rails), or `POST https://api.groundmail.dev/emails` from anything: see the [API reference](https://docs.groundmail.dev/emails).

### Apps that only speak SMTP

Self-hosted apps such as Ghost, n8n, Plausible or WordPress take SMTP settings. Put the [SMTP relay](https://docs.groundmail.dev/smtp) settings in their environment variables:

| Setting | Value |
|---------|-------|
| Host | `smtp.groundmail.dev` |
| Port | `587` (or `2525`) |
| Encryption | STARTTLS. Leave "secure", "SSL" or "implicit TLS" off: there's no port 465. |
| Username | `groundmail` |
| Password | Your SMTP credential (`gmsmtp_…`) |
| From address | An address on your verified domain |

---

## Coolify's own notification email

Coolify emails you about deployments, backups, scheduled tasks and servers. To send those through Groundmail:

1. In Coolify, open **Notifications** and select **Email**.
2. Set **Email service** to *Use team email settings*.
3. Fill in **From name** and **From address** (both required). The from address must be on your verified domain.
4. In the **SMTP server** section:

| Field | Value |
|-------|-------|
| Host | `smtp.groundmail.dev` |
| Port | `587` |
| Encryption | **StartTLS** |
| SMTP username | `groundmail` |
| SMTP password | Your SMTP credential (`gmsmtp_…`) |
| Timeout | Leave empty, or `30` |

5. Click **Save changes** in the SMTP server section, then set **SMTP delivery** to enabled and save.
6. Under **Notification events**, pick the events you want, click **Send test** and enter an address you can read. The test shows up under **Emails** in the Groundmail dashboard with its delivery status.

Don't pick **TLS/SSL**: that's implicit TLS for port 465, which Groundmail doesn't offer, so the connection fails.

**Several teams on one self-hosted instance?** Put the same settings in **Settings → Email** once, send a test, then set each team's **Email service** to *Use system-wide settings*.

---

## Troubleshooting

| Problem | Fix |
|---------|-----|
| Connection timeout to `smtp.groundmail.dev:587` | Your server's host blocks outbound 587 (DigitalOcean and Vultr do on new accounts). Use port `2525` with the same settings, or send from apps over HTTPS with the API key. |
| TLS handshake error, or the test hangs | Encryption is set to TLS/SSL. Use StartTLS on port 587 or 2525. |
| `535` authentication failed | The username must be `groundmail` and the password an SMTP credential, not an API key. Credentials are shown once; create a new one if you lost it. |
| Saving the email settings fails | From name and from address are both required. |
| `GROUNDMAIL_API_KEY` is undefined in the app | Restart the app after saving variables. Check the variable is in the production (or preview) section the deployment uses. |
| `550 … domain is not verified` | The from address isn't on a domain you verified under **Domains**. |

Related: [SMTP relay](https://docs.groundmail.dev/smtp) · [Tools with SMTP settings](https://docs.groundmail.dev/smtp/tools) · [Node.js SDK](https://docs.groundmail.dev/frameworks/node) · [Railway](https://docs.groundmail.dev/integrations/railway)
