Send Email from n8n: SMTP Node or HTTP Request Node
Two ways to send email from n8n on your own domain: the Send Email node over SMTP or an HTTP Request node to the API. Credentials, expressions and batching.
n8n can send email two ways, and both work with a mailbox on your own domain. The Send Email node speaks SMTP and needs nothing but the mailbox's login. The HTTP Request node calls the send API and gives you the delivery log and the API's own limits. Pick SMTP for a quick workflow and the API when the workflow is part of a product. Here is the exact setup for each, the expression syntax for dynamic recipients, and the two settings that stop a loop from tripping the send limits.
Quick answer
For SMTP: add a Send Email node, create SMTP credentials with host mail.oqumail.com, port 587, SSL/TLS off (that means STARTTLS), and the mailbox address and password as user and password. For the API: add an HTTP Request node, POST to the send endpoint, use a Header Auth credential named Authorization with the value Bearer and your key, and send a JSON body where to is an array.
Option 1: the Send Email node over SMTP
- Create a mailbox for the workflow on your domain, for example alerts@yourdomain.com, so automated mail does not come from a person's address.
- In n8n add a Send Email node. Under Credential choose Create New (SMTP).
- Host: mail.oqumail.com. Port: 587. SSL/TLS: off. n8n then upgrades the connection with STARTTLS, which is what port 587 expects. Turning SSL/TLS on with port 587 is the classic mistake and fails with a TLS handshake error.
- User: the full mailbox address. Password: the mailbox's webmail password.
- From Email: the same mailbox address. To Email: a fixed address, or an expression such as {{ $json.email }} from the previous node.
- Run the node once with Test step and check the mailbox's Sent folder; the message is there like any other sent mail.
Option 2: the HTTP Request node and the API
Use this when you want every send in the delivery log, when the workflow runs often, or when the same key is used by other services. Create an API key on the sending mailbox in the OquMail dashboard, then configure the node:
Method: POST
URL: https://api.oqumail.com/api/v1/emails
Authentication: Generic Credential Type -> Header Auth
Name: Authorization
Value: Bearer oqm_live_xxxxxxxxxxxxxxxx
Send Body: on, Body Content Type: JSON, Specify Body: Using JSON
{
"to": ["{{ $json.email }}"],
"subject": "Welcome, {{ $json.name }}",
"text": "Thanks for signing up. Reply to this email if you need a hand.",
"fromName": "Acme"
}Expressions that work
- A recipient from the previous node: "to": ["{{ $json.email }}"]. The square brackets stay; the API wants an array.
- Several recipients from a list: "to": {{ JSON.stringify($json.emails) }} when emails is already an array.
- A value from an earlier node by name: {{ $('Webhook').item.json.body.email }}.
- Text with a line break: use \n inside the string, for example "Order " + $json.id + "\nTotal: " + $json.total.
- HTML body: set "html" instead of or alongside "text", and build it with the Set node first so the JSON stays readable.
Free business email on your own domain
OquMail gives you up to 15 mailboxes on your domain — free — with guided SPF/DKIM/DMARC, webmail, IMAP/SMTP for any mail app, and a send API. Setup is a few DNS records; changes usually take effect within minutes, occasionally up to 48 hours. Start at oqumail.com.
Stop a loop from tripping the send limits
A workflow that loops over a hundred rows and sends one email each will hit the per-minute burst limit on the mailbox and start getting 403 responses. Two node settings fix it:
- On the HTTP Request node open Options and enable Batching: batch size 1, batch interval 1500 ms. The node then spaces the sends out.
- Enable Retry On Fail with a wait of 5000 ms and two or three tries, so a transient failure is retried rather than dropped.
- If the workflow sends more than a few hundred messages a day, it is a newsletter and belongs in a list tool, not a transactional mailbox. The free plan allows 250 sends a day per mailbox.
Handling failures
- Set the node's On Error to Continue (using error output) and connect the error branch to a Slack, Telegram or second email node that tells you a send failed.
- Add an Error Trigger workflow that catches any failed execution across the instance; n8n runs it automatically.
- A 401 from the API means the credential value is wrong or the key was revoked; a 400 almost always means to was sent as a string.
- For SMTP, "Invalid login" means the mailbox password changed; "wrong version number" or a handshake error means SSL/TLS is on where it should be off.
Pitfalls specific to n8n
- Pasting the key into the URL or body instead of a credential. Credentials are encrypted at rest and stay out of exported workflow JSON.
- Self-hosted n8n on a VPS where outbound port 25 is blocked. Irrelevant for both options above: SMTP uses 587 and the API uses 443.
- Running the workflow on every webhook test while building it, and emailing a real customer ten times. Point to to your own address until the workflow is finished.
- Using a person's mailbox for automation. When they leave or change their password, every workflow breaks at once.
Common questions
Which option should I pick?
SMTP if the workflow is internal and sends a handful of messages a day: it is one credential and no API key. The API if the send is part of a product flow or you want the delivery log, the per-key limits and the ability to revoke one integration without changing a password.
Can I attach a file?
Yes with both. The Send Email node takes binary data from a previous node as an attachment. The API takes an attachments array with filename, contentType and contentBase64; use a Code node or the Move Binary Data node to base64-encode the file first.
Does it work on n8n Cloud?
Yes. Both nodes are standard, and nothing here depends on self-hosting.