Email & SMTP
Connect your own SMTP provider so a project sends auth codes, welcome emails, API sends and broadcasts from your domain, or rely on the rate-limited shared sender for auth email.
Each project can send email through an SMTP server you configure for it. That covers the automatic auth emails, the Email API and marketing broadcasts. Projects without SMTP still send auth emails through a shared OrbitNest sender, with rate limits and the built-in templates.
How project email works
| Channel | Triggered by | With project SMTP | Without project SMTP |
|---|---|---|---|
| Auth emails | Project auth flows (sign-up, email OTP sign-in, password recovery) | Sent through your SMTP, with your custom templates if saved | Sent through the shared sender with the built-in templates |
| Email API | Your server or edge function calling POST /api/project/:slug/email/send | Sent through your SMTP | Fails with 400 |
| Marketing broadcasts | A workspace admin sending from Studio, or the admin API | Sent through your SMTP | Every recipient fails |
| Template previews | A workspace admin sending a test from the template editor | Sent through your SMTP | Fails with 400 |
To test auth without sending any email, turn on debug mode.
Emails OrbitNest sends for you
| Template type | Sent when | |
|---|---|---|
| Verification code | otp_verification | POST /api/projects/:projectId/auth/signup, signup-with-email and signin-with-email |
| Password reset code | password_reset | POST /api/projects/:projectId/auth/recover (alias recover-password), when the email belongs to an existing user |
| Welcome email | welcome | After verify-signup creates a new user |
- Verification and reset codes are 4 digits and expire after 10 minutes.
- If the code email fails, the auth request fails too.
- The welcome email is sent in the background. If it fails, the error is logged and sign-up still succeeds.
- If no account exists for the address, password recovery and email sign-in still return a success response and send nothing.
See Authentication for the full flows.
Note
Studio account emails, such as workspace invitations, Studio sign-up codes and support notifications, are sent by OrbitNest itself. They never use your project's SMTP.
Shared sender for auth email
When a project has no SMTP configured, or SMTP is turned off, the three auth emails above are sent by OrbitNest's own mail server:
- From:
"<Project name> via OrbitNest"at an OrbitNest address. - Reply-To: a
no-replyaddress at the OrbitNest domain, so replies are not delivered. - Content: the built-in templates only, branded with your project name, logo and brand color. Your saved custom templates are used only with your own SMTP.
- Rate limits: 100 emails per hour per project, and 5 per hour to the same recipient. Over either limit, the auth request returns
429with codeSHARED_EMAIL_RATE_LIMITEDand nothing is sent.
The shared sender carries auth email only. The Email API, broadcasts and template previews always need project SMTP.
Use your own SMTP in production
Your own SMTP removes the rate limits, sends from your domain, and uses your custom templates.
Configure SMTP in Studio
Open your project and go to Settings → SMTP. Project settings are only visible to workspace admins, and only admins can change them.
| Field | API field | Required | Default | Notes |
|---|---|---|---|---|
| Host | smtp_host | Yes | For example smtp.sendgrid.net. Must be a public host (see Allowed hosts) | |
| Port | smtp_port | Yes | 587 | 1–65535 |
| Username | smtp_user | No | Leave blank for an unauthenticated relay. Encrypted at rest. The API returns it masked: nor***@myapp.com, or *** if the username is not an email address | |
| Password | smtp_password | Yes for a new login | Encrypted at rest and never returned. Leave it blank to keep the current password | |
| SSL/TLS | smtp_secure | No | Off | On means implicit TLS (port 465). Off means STARTTLS (port 587) |
| From Email | smtp_from_email | Yes | The sender address. It must be allowed by your provider | |
| From Name | smtp_from_name | No | The display name for the sender | |
| Enable SMTP | smtp_enabled | No | On | When off, the project behaves as if no SMTP is configured |
Click Save. After the settings are saved, a Test section and a Delete Configuration option appear.
Need credentials? → Open guide has setup steps and values for Gmail, Outlook / Microsoft 365, SendGrid, Mailgun, Amazon SES and Custom / Postfix.
Ports and TLS
587with SSL/TLS off uses STARTTLS. This is the recommended setting.465with SSL/TLS on uses implicit TLS. Many cloud hosts block outbound port 465, so use 587 if you can.- Connections time out after 10 seconds, and an idle socket times out after 15 seconds.
Allowed hosts
The SMTP host must resolve to a public address. Saving a host that is, or resolves to, a private, loopback, link-local or other internal address returns 400 (SMTP host "…" is not allowed (private, loopback or internal address).). The same applies to localhost and names ending in .local, .internal, .localhost, .lan or .corp. A host that doesn't resolve also returns 400.
The host is checked again on every send, and OrbitNest connects to the address it checked. A relay on your own private network, such as a local Postfix, can't be used.
Provider notes
- Gmail: use an App Password, which requires 2-Step Verification. Gmail rewrites the From header to the authenticated account, so a different From Email only shows up if you add it as a verified "Send mail as" alias in Gmail.
- SendGrid: the username is the literal string
apikey, and the password is an API key with Mail Send permission. - Amazon SES: use the SMTP credentials SES generates, not your AWS access keys, and the host for your region (
email-smtp.<region>.amazonaws.com). In the SES sandbox, both the From address and every recipient must be verified identities. - Mailgun: use the SMTP credentials for your sending domain, not the API key. EU accounts use
smtp.eu.mailgun.org.
Authenticate your domain
Set up SPF, DKIM and DMARC for your sending domain with your provider. Without them, the first emails from a new domain often land in spam.
Send a test email
In Settings → SMTP → Test, enter an address and click Send. OrbitNest connects with your saved settings, verifies the connection, and sends a short test message. Tests are limited to 10 per minute per IP address.
The API returns 200 even when the test fails, so check the success field:
{ "success": false, "message": "SMTP test failed: Invalid login: 535 Authentication failed" }- Connection-level failures (refused, timed out, unreachable, TLS errors) all return the same message:
Could not connect to the SMTP server. Check the host, port and SSL/TLS setting. - Credential-like values are removed from error messages before they are returned.
Sender identity
These apply to email sent through your project SMTP:
- From:
"From Name" <from_email>, or just the address if no name is set. - Reply-To: your From Email, so replies reach your inbox.
- Branding: auth emails use your project name, the logo from Settings → General → Logo and the brand color from the template editor. See Email templates.
Mail from the shared sender uses a different identity. See Shared sender.
Debug mode
The Debug mode toggle in Settings → General is for testing without email:
- Sign-up, email OTP sign-in and password recovery skip sending email and accept the fixed code
1234. - Welcome emails are still attempted. If sending fails, the failure is only logged.
Caution
While debug mode is on, anyone who knows a user's email address can sign in to that account with 1234. Turn it off before real users sign up.
Manage SMTP with the API
These endpoints use a Studio admin access token, which is the access_token returned by POST /api/auth/signin. They do not accept project API keys. :projectId must be the project UUID, which appears in the Studio URL /projects/<id>/....
| Method | Path | Role | Description |
|---|---|---|---|
GET | /api/projects/:projectId/smtp | Any workspace member | Read settings. The password is never returned |
PUT | /api/projects/:projectId/smtp | Admin | Create or replace settings |
POST | /api/projects/:projectId/smtp/test | Admin | Send a test email to test_email |
DELETE | /api/projects/:projectId/smtp | Admin | Remove all SMTP settings. Auth email then goes through the shared sender, and the Email API and broadcasts stop working |
curl -X PUT "https://api.orbitnest.io/api/projects/$PROJECT_ID/smtp" \
-H "Authorization: Bearer $ORBITNEST_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"smtp_host": "email-smtp.us-east-1.amazonaws.com",
"smtp_port": 587,
"smtp_secure": false,
"smtp_user": "YOUR_SMTP_USERNAME",
"smtp_password": "YOUR_SMTP_PASSWORD",
"smtp_from_email": "noreply@my-app.com",
"smtp_from_name": "My App",
"smtp_enabled": true
}'PUT replaces every field it does not treat as a credential. Any field you leave out goes back to its default: port 587, SSL off, no From Name, enabled. smtp_user and smtp_password are the exception: if you leave them out or send an empty string, the stored values are kept. Omit both for an unauthenticated relay.
GET and PUT return the current settings:
{
"smtp_host": "email-smtp.us-east-1.amazonaws.com",
"smtp_port": 587,
"smtp_secure": false,
"smtp_user": "***",
"smtp_from_email": "noreply@my-app.com",
"smtp_from_name": "My App",
"smtp_enabled": true,
"is_configured": true
}is_configured is true when a host and From Email are stored.
Send a test email:
curl -X POST "https://api.orbitnest.io/api/projects/$PROJECT_ID/smtp/test" \
-H "Authorization: Bearer $ORBITNEST_ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "test_email": "you@example.com" }'The MCP server can also read and update these settings with the orbitnest_get_smtp_settings and orbitnest_update_smtp_settings tools.
Troubleshooting
When a verification or reset email can't be sent, the auth endpoint returns 503 with one of these hints, or 429 for the shared-sender limit:
| Response | Likely fix |
|---|---|
429 SHARED_EMAIL_RATE_LIMITED | Wait for the hourly window to pass, or add SMTP settings to remove the limit |
| This project has no email (SMTP) configured and the shared OrbitNest sender is unavailable | Add SMTP settings, or turn on debug mode for testing |
| The shared OrbitNest sender could not deliver the email | Try again shortly, or add SMTP settings |
| Could not reach the configured SMTP server | Check the host and port and your firewall. Try 587 with SSL/TLS off |
| SSL/TLS handshake failed | On port 587, turn SSL/TLS off. Only port 465 uses SSL/TLS on |
| SMTP authentication failed | Check the username and password. For Gmail, use an App Password |
| SMTP server rejected the From address | Use a verified sender identity. In the SES sandbox, verify the recipient too |