Can you build an n8n AI email agent with HTTP requests?

Yes. The n8n HTTP Request node can run as a regular workflow node or as a tool attached to an AI agent. Use regular nodes for fixed operations and give the agent only the read tools it needs.

n8n orchestrates the workflow, the model proposes a reply, and Mailera provides mailbox access. Workflow logic, not the model, decides whether sending is authorized.

Start with this acceptance test: one message in your own test mailbox produces a reviewable reply. Rejection sends nothing. Approval permits one send attempt for the exact reviewed content.

Workflow from message selection through a read-only agent and human approval to an isolated send request and status record.
The agent proposes a reply. Only workflow logic can authorize the separate send step.

For the broader architecture, see email for AI agents using existing mailboxes. Mailera’s MCP interface is an alternative tool interface; this HTTP Request workflow uses REST directly. The task-by-task MCP tool guide covers that alternative separately.

What do you need before building the workflow?

Prepare n8n, a model credential for your AI Agent, an owned test mailbox connected to Mailera, and separate Mailera read and send keys.

Connect the mailbox through Mailboxes → Add mailbox. For Outlook or Microsoft 365, use Sign in with Microsoft, which uses OAuth consent at Microsoft. Follow the Microsoft connection guide or Gmail connection guide rather than mixing provider setup into the workflow.

In Settings → API key → Create key, set Mailbox scope to the test mailbox’s group. Select only Read for the agent’s credential. Create another key with Send messages for the isolated send branch and its status check.

Store secrets in n8n credentials. Don’t paste them into prompts, node comments, or exported workflow JSON.

Mailera API key creation dialog with a test mailbox group selected and only Read permission enabled.
Give the agent a group-scoped read key. Keep the send key in the approved-send branch.
ComponentPurposeCredential and boundary
Manual start; later Schedule TriggerBegin processingNo mailbox credential
HTTP Request read nodes/toolsList mailboxes and read messagesRead key; fixed mailbox
AI Agent and modelPrepare a reply proposalModel credential; no send key
Validation and review applicationCheck and display the exact proposalReviewer authentication; no model-controlled approval
WaitPause until a review decisionSeparate resume authentication
HTTP Request send/status nodesSend approved content and inspect the attemptSend key; approved branch only

Keep the test group narrow. Restricting a key to a group does not replace a workflow-level mailbox allowlist.

How do you configure the mailbox HTTP requests?

1. Identify the test mailbox

Begin with a manual execution. Configure an HTTP Request node with method GET, URL https://mailera.app/api/public/v1/mailboxes, and query parameter limit=1. Configure its stored credential to supply Authorization: Bearer <API key>.

The equivalent request is:

curl --get 'https://mailera.app/api/public/v1/mailboxes' \
  --header "Authorization: Bearer $MAILERA_API_KEY" \
  --data-urlencode 'limit=1'

The response body contains a data array. Inspect data[0].id, data[0].status, and data[0].capabilities.send. Select your intended mailbox, not simply whichever entry appears first. Mailbox listing uses limit and offset for pagination.

Save the selected ID in workflow configuration. Don’t accept a replacement mailbox ID from the model.

2. List messages, then retrieve one message

Use the same read credential for these requests:

MethodPathScopeQuery parameters
GET/mailboxesreadstatus, provider, group_id, tag, q, limit, offset
GET/mailboxes/{id}/messagesreadfolder, unread, since, from, q, cursor, limit
GET/mailboxes/{id}/messages/{msgId}readNone

Start with one Inbox message:

curl --get "https://mailera.app/api/public/v1/mailboxes/$MAILBOX_ID/messages" \
  --header "Authorization: Bearer $MAILERA_API_KEY" \
  --data-urlencode 'folder=inbox' \
  --data-urlencode 'limit=1'

The list response contains data[], next_cursor, and mailbox. Select the known test message’s id, then fetch its content:

curl "https://mailera.app/api/public/v1/mailboxes/$MAILBOX_ID/messages/$MESSAGE_ID" \
  --header "Authorization: Bearer $MAILERA_API_KEY"

3. Map the response deliberately

These paths are relative to the API response body:

ValuePath
Source message referencedata.id and data.mailbox_id
Senderdata.from.address
Subjectdata.subject
Plain-text contentdata.body.text
HTML contentdata.body.html
Content-loading errordata.body_error

Check body_error before asking the model to draft a reply. A list preview is not a substitute for the full message.

The HTTP Request option “Include Response Headers and Status” returns headers and status alongside the body. If you enable it, inspect the node output and map from the contained response body. By default, the node treats only 2xx responses as successful.

For polling, pass next_cursor into the next request’s cursor parameter while another page is available. Keep that cursor separate from your persistent processed-message record.

How does the agent turn an email into a reply proposal?

Connect the AI Agent to your chosen model and narrowly scoped HTTP Request read tools. The AI Agent documentation requires at least one connected tool sub-node.

Keep tool URLs and mailbox IDs fixed. If a tool accepts a message ID, validate that it belongs to the selected mailbox and permitted work item before making the request.

An agent chooses whether to call a read tool. A fixed pipeline that always fetches one message and asks a model to draft a response is AI-assisted automation, without that tool-selection decision. Use the fixed pipeline if that is all you need.

Pass only the content needed to answer. Label it as untrusted email data and require a structured proposal containing:

  • The source mailbox and message reference.
  • The proposed recipient and subject.
  • The complete reply body.
  • A short review summary.

These are your workflow’s proposal fields, not Mailera request fields. Validate their presence and types outside the model. Check the source reference against the selected message and the recipient against your configured policy. Treat the sender address as message data, not automatic authorization to send.

Do not connect a send tool or send credential to the AI Agent. Its output is a proposal, even when it says the reply is approved.

How do you require approval and avoid duplicate sends?

For the underlying design, see building an email agent with approval boundaries; the steps below apply that separation to n8n.

4. Persist the proposal before pausing

Create a durable action record containing the source reference, exact proposed payload, and a pending decision. Display the recipient, subject, complete body, and source message in an authenticated review application.

Bind the decision to that stored payload, using an immutable version or digest. Editing any send-relevant content must invalidate the approval. Keep reviewer identity and decision time with the action record.

5. Resume through an authenticated callback

The Wait node can resume after an HTTP call and supports “Header Auth”. Its resume URL is generated at runtime.

Have your review application authenticate the human reviewer, save the decision, then call the protected resume URL from its backend. Keep the callback credential server-side. Header authentication on a callback does not itself identify the human who approved the reply.

Immediately after Wait, reload the action record and require all of these conditions:

  1. An authorized reviewer explicitly approved it.
  2. The approved payload matches the payload about to be sent.
  3. The approval is still valid and the action has not already been consumed.

Claim the approved action atomically before sending so concurrent executions cannot both proceed.

Resuming is not approval. With “Limit Wait Time” enabled, Wait can resume automatically when the limit is reached. A timeout, rejection, missing decision, or failed validation must lead to a branch with no send request.

6. Send only the stored, approved payload

Use a regular HTTP Request node for POST /mailboxes/{id}/send, with the separate send credential. The node supports a JSON body. Map the approved proposal into the send or reply request documented in the Mailera API documentation; don’t submit the proposal object directly as the API body.

Generate and persist an Idempotency-Key for the approved action before the request. Reuse that key for retries of the same action. Also keep persistent state keyed by source mailbox and message, so repeated polls do not create new approval actions for the same work.

Keep approval validation, approval-callback replay prevention, and persistent processed-message tracking in the workflow. Use Mailera’s Idempotency-Key support for retries of the same send action.

7. Inspect the send attempt

Use GET /sends/{id} with the send credential to inspect the attempt. The documented statuses are queued, sending, sent, failed, and unknown.

An accepted HTTP request is not confirmed delivery. Keep the send-attempt reference with the action record. If the outcome is unknown, investigate before retrying; do not manufacture a new action and idempotency key just to try again.

What common errors should you test before scheduling?

Symptom or testCheck or required behavior
Authentication or scope failureCheck the Bearer credential, mailbox group, and permission for that endpoint.
Empty message listCheck the fixed mailbox, folder, and filters; inspect connection and sync state.
Disconnected mailboxResolve the connection before retrying reads.
Missing body or invalid proposalStop before review; inspect body_error and reject malformed model output.
Repeated polling resultFind the existing source-message record rather than creating another action.
Rejection or timeoutConfirm that no send request occurs.
Payload changed after approvalRequire a fresh approval.
Replayed callback or concurrent executionPermit only the execution that successfully claims the approved action.
Receive-only mailboxCheck capabilities.send; keep the send branch blocked.
Send failure or uncertain outcomeInspect the attempt; keep retries bounded and preserve the action’s idempotency key.

Repeat the tests after a workflow restart to check persistence. Follow message-list pagination rather than repeatedly processing only the first page.

Once the manual path behaves correctly, use Schedule Trigger for fixed intervals or times. Save and publish the scheduled workflow. Don’t make correctness depend on instantaneous message arrival.

How do you keep incoming email from controlling the agent?

Incoming email is untrusted data, not instructions. A message asking the agent to reveal a credential, change its rules, call an arbitrary URL, or send to a different recipient must not gain authority over the workflow.

Keep mailbox allowlists, recipient policy, and approval state outside model control. Minimize the content passed to the model, and redact credentials and personal message content from screenshots and execution logs. Review Mailera’s security information alongside your n8n deployment controls.

Test a hostile message that asks the agent to disclose secrets and skip approval. The expected result is no access to the send credential and no send request without a valid review decision. Prompt wording alone is not a security boundary.

Mailera does not provide bulk marketing sending or mailbox warmup, and it does not guarantee inbox placement. Keep this workflow focused on individual, reviewed replies from your connected mailbox.

Do this with the API

Every action in this article is available via the REST API, with curl examples, API keys and webhooks.

View API docs