Send email with SMTP
Send email from any app, framework or plugin that supports SMTP, using your SendMero API key as the password.
If your app already sends mail over SMTP, you can switch to SendMero by changing its mail settings. There is no new SDK to install. Prefer JSON over HTTP? Use the REST API instead; see SMTP or the REST API? below.
Quickstart
- Verify your sending domain. Add the domain you send from and publish its DNS records. Your messages' From address must be on this domain. Add your domain →
- Create an API key. The same key you use for the REST API works as your SMTP password. Create an API key →
- Enter these settings in your app:
| Setting | Value |
|---|---|
| Host | smtp.sendmero.com |
| Port with STARTTLS | 587 (or 2587) |
| Port with implicit TLS (SSL/TLS) | 465 (or 2465) |
| Username | sendmero |
| Password | Your SendMero API key, including its live_ prefix |
That is all the setup there is. The username is always sendmero, and there is no separate SMTP password to create.
Send your first email
Pick your language or framework, replace the from address with one on your verified domain, set SENDMERO_API_KEY to your key, and run it.
SMTP_USERNAME='sendmero'
SMTP_PASSWORD="$SENDMERO_API_KEY" # your API key
curl --ssl-reqd --url 'smtp://smtp.sendmero.com:587' \
--user "$SMTP_USERNAME:$SMTP_PASSWORD" \
--mail-from 'hello@example.com' \
--mail-rcpt 'recipient@example.net' \
--upload-file - <<'EOF'
From: Example Store <hello@example.com>
To: recipient@example.net
Subject: Hello from SendMero
X-SendMero-Metadata: {"order_id":"88231"}
Sent over SMTP.
EOF
# Implicit TLS: use smtps://smtp.sendmero.com:465 instead of smtp://...:587 --ssl-reqd.
When SendMero accepts the message, your library receives this reply:
250 2.0.0 Ok: queued as msg_9f2c6a1e4b7d4c0e8a5b3d2f1e0c9b8a
msg_… is the message ID. Keep it: you can paste it into Activity in the dashboard to find the email. Accepted means SendMero has taken the message for sending; it is not a delivery confirmation.
Choose a port and encryption
SendMero only accepts SMTP on an encrypted connection (TLS 1.2 or later). Pick the port that matches what your library supports:
| Encryption | Port | Notes |
|---|---|---|
| STARTTLS (the connection starts plain, then upgrades) | 587 | The usual choice. Libraries call this "STARTTLS" or "TLS". |
| SSL/TLS (encrypted from the first byte) | 465 | Use it if your library only offers "SSL". |
| STARTTLS | 2587 | Use if your host blocks port 587. |
| SSL/TLS | 2465 | Use if your host blocks port 465. |
Build your message
Compose the message with your mail library as you normally would. This is how SendMero treats each part:
| To do this | What to do |
|---|---|
| Set the sender | Use an address on your verified domain as From. A display name works: Example Store <hello@example.com>. |
| Send HTML and plain text | Send both parts (a multipart/alternative message) as your library does by default. |
| Cc and Bcc | Add them as usual. Bcc recipients are not shown to anyone else. |
| Set Reply-To | Add a Reply-To header or use your library's reply-to option. |
| Attach files | Attach them as usual. The whole message, attachments included, must stay under about 90 KB. |
| Add an unsubscribe link | Add a List-Unsubscribe header, and List-Unsubscribe-Post: List-Unsubscribe=One-Click for one-click unsubscribe. |
| Attach your own data (metadata) | Add an X-SendMero-Metadata header with a JSON object, for example {"order_id":"88231"}. It is kept with the message and appears in Activity and in webhook events. It is never sent to the recipient. See Attach metadata. |
| Add your own headers | Headers that start with X- are kept, up to 10 custom headers in total (List-* headers count too). X-SendMero-* headers are reserved for SendMero. Message-ID, Date and similar headers are set by SendMero. |
| Send to several people | Up to 100 recipients per message. For more, send more than one message. |
A message needs at least one To recipient. Inline images (cid: references) arrive as ordinary attachments.
Attach metadata
Metadata is your own data about a message, such as an order or customer ID. Over SMTP you pass it in one header, as a JSON object of text values:
X-SendMero-Metadata: {"order_id":"88231","customer_id":"c-42"}
- It is the same metadata the REST API takes: at most 10 keys, key names of letters, digits and underscores (up to 40 characters), text values up to 256 characters, and 2,048 bytes in total.
- It appears with the message in Activity and in the
metadatafield of webhook events, so you can match an email to your own records. - It is not sent to the recipient. SendMero removes the header before the email goes out.
- Use text values. A number such as
{"qty":3}is refused; write{"qty":"3"}. - If the header isn't valid JSON, or breaks a rule, the message is refused with a
554reply that says what to fix. Nothing is sent.
Most mail libraries add a custom header with one line. The examples above show it for each language. Non-ASCII values (such as Zürich) are fine; your library encodes the header and SendMero decodes it.
After you send
- Find the message. Open Activity and search by the
msg_…ID or the recipient to see whether it was delivered, bounced or deferred. - Get notified. Webhooks report delivery events for messages sent over SMTP the same way as for the REST API.
- If it didn't send, the reply tells you why. See below.
Replies you may see
Your mail library treats a 4xx reply as "try again later" and a 5xx reply as "give up". Most libraries retry 4xx replies by themselves.
| Reply | What it means | What to do |
|---|---|---|
250 | Accepted, queued as msg_…. | Nothing. Keep the message ID. |
451 | A temporary problem, or your workspace reached a sending limit. | Retry later. |
452 4.5.3 | More than 100 recipients. | Split the message. |
421 | Too many connections or too many wrong keys from your IP address. | Close idle connections or fix your key, then wait and retry. |
535 | The API key is wrong, expired or revoked, or the username is not sendmero. | Check the username and use a current key. |
538 | You tried to log in before starting encryption. | Turn on STARTTLS or SSL/TLS in your app. |
550 5.7.1 | The From domain isn't set up, verified or ready, or sending is paused for the workspace. The reply says which. | Fix the domain in Sending Domains. |
552 | The message is too large. | Make it smaller; the limit is about 90 KB. |
554 5.6.0 | The message was refused, for example it has no To recipient, an invalid field, or invalid X-SendMero-Metadata. The reply says why. | Correct the message. |
554 5.7.0 | You are out of email credits. | Top up credits, then send again. |
Limits
| Limit | Value |
|---|---|
| Message size, attachments included | About 90 KB |
| Recipients per message | 100 |
| Open connections from one IP address | 20 |
| Idle connection | Closed after 60 seconds |
| Wrong API keys | After 10 within 10 minutes, connections from that IP address are refused for 15 minutes |
Your workspace's daily and monthly sending limits and your email credits apply exactly as they do for the REST API. See Rate Limits & Retries.
Troubleshooting
"Test connection" passes, but my email doesn't send.
SendMero checks your API key when you send a message, not when you connect. Most "test connection" buttons only connect, so they pass even with a wrong key. Send a real test email to confirm your settings. A wrong key shows up as a 535 reply.
The connection times out or is refused.
Your network or host may block the port. Try 2587 (STARTTLS) or 2465 (SSL/TLS) instead.
I get a certificate or TLS error.
Check that the host is exactly smtp.sendmero.com and that the encryption setting matches the port: STARTTLS for 587 and 2587, SSL/TLS for 465 and 2465. Your library must support TLS 1.2 or later.
Every message gets 535.
The password must be your whole API key, starting with live_, with no spaces or quotes around it. Confirm the key is still active under Credentials in the dashboard.
I get 550.
The From address must be on a domain that shows as verified under Sending Domains. A verified example.com does not cover mail.example.com; verify the exact domain you send from.
My message is refused with a metadata error.
X-SendMero-Metadata must be a JSON object of text values within the limits in Attach metadata. The 554 reply names the problem, for example metadata: at most 10 keys are allowed.
I need test mode. Test mode is a REST API feature and isn't available over SMTP. To try SMTP, send a message to an address you own.
SMTP or the REST API?
Both use the same API key, the same verified domains, and the same sending limits and credits, so you can use either, or both.
| SMTP | REST API | |
|---|---|---|
| Best for | Existing apps, frameworks and plugins that already send over SMTP | New code that can make HTTP requests |
| Request | A normal email message | A JSON body |
metadata on the message | Yes, in the X-SendMero-Metadata header | Yes, in the body |
| Test mode | No | Yes |
| Custom headers | List-* and X- headers (not X-SendMero-*) | Any header that is not reserved |
| Result | A 250 reply with the message ID | JSON with the message ID |
| Errors | SMTP reply codes (above) | error.code and an HTTP status (Error Codes) |