Outbound Email for AI Agents in Intercom

Intercom handles conversational support. MultiMail adds the approval gating, identity verification, and audit trail your AI agents need before sending email outside the thread.


Intercom's Fin AI agent and custom bots are effective at resolving support conversations — but when an agent needs to send a follow-up email outside the Intercom thread, you lose the oversight controls your team depends on. The message leaves through a shared mailbox with no approval step, no cryptographic proof of origin, and no audit trail.

MultiMail fills that gap. By routing agent-authored outbound email through MultiMail's REST API, you get per-message approval gating, DKIM-signed delivery from a verified sender identity, and a complete decision log — all without changing how Intercom handles inbound conversations.

The integration is a webhook-to-API bridge: Intercom fires a webhook when an agent drafts an outbound message, your backend calls MultiMail's `send_email` or `decide_email` endpoints, and the approval state flows back to Intercom via its Conversations API. Your human team approves in MultiMail's queue; the message sends only after explicit sign-off.

This pattern applies to any Intercom workflow that touches outbound email: churn-risk escalations drafted by Fin, onboarding sequences triggered by lifecycle events, or proactive outreach composed by a custom agent reading CRM signals.

Built for Intercom developers

Approval gating before delivery

Intercom's native outbound email has no per-message approval step for AI-authored content. MultiMail's `gated_send` mode holds every agent-drafted message in a review queue until a human approves it via the API or dashboard — then delivers it with a cryptographic signature proving the approval happened.

Cryptographic sender identity

Messages sent through MultiMail carry a DKIM signature tied to your verified domain and an `X-MultiMail-Agent` header identifying the agent that authored the message. Intercom's shared mailbox provides neither. This matters for CAN-SPAM compliance and for recipients who want to verify the message came from a real, accountable source.

Immutable decision log

Every `decide_email` call — approve or reject — is written to an append-only audit log with timestamp, approver identity, and the original draft. If a regulator, customer, or internal reviewer asks what your AI sent and who authorized it, you have a complete answer.

Separate mailbox per agent role

Use `create_mailbox` to provision dedicated addresses like `[email protected]` or `[email protected]`. Replies route back through MultiMail's inbound pipeline, keeping agent-originated threads separate from your human support queue in Intercom.

Webhook-native architecture

Intercom's workflow automation fires webhooks on conversation events. MultiMail's inbound webhooks handle delivery status, approval events, and replies — so the two platforms compose without polling loops or manual reconciliation.


Get started in minutes

Send an agent-drafted email with approval gating
python
import httpx

MULTIMAIL_API_KEY = "mm_live_your_key_here"
BASE_URL = "https://api.multimail.dev"

def send_agent_followup(conversation_id: str, customer_email: str, draft_body: str) -> dict:
    """
    Called from an Intercom webhook handler after Fin resolves a conversation.
    Routes the follow-up email through MultiMail with gated_send oversight.
    """
    payload = {
        "from": "[email protected]",
        "to": customer_email,
        "subject": "Following up on your support request",
        "body": draft_body,
        "oversight_mode": "gated_send",
        "metadata": {
            "source": "intercom",
            "conversation_id": conversation_id,
            "agent": "fin"
        }
    }

    response = httpx.post(
        f"{BASE_URL}/send_email",
        json=payload,
        headers={"Authorization": f"Bearer {MULTIMAIL_API_KEY}"}
    )
    response.raise_for_status()
    result = response.json()

    "cm"># result["message_id"] can be stored against conversation_id
    "cm"># for later approval status polling or webhook correlation
    return result

When Intercom's Fin agent resolves a conversation and wants to send a follow-up email, call MultiMail's send_email endpoint with gated_send oversight. The message is held until a human approves it.

Approve or reject a pending message from a review queue
python
import httpx
from typing import Literal

MULTIMAIL_API_KEY = "mm_live_your_key_here"
BASE_URL = "https://api.multimail.dev"

def get_pending_messages() -> list[dict]:
    response = httpx.get(
        f"{BASE_URL}/list_pending",
        headers={"Authorization": f"Bearer {MULTIMAIL_API_KEY}"}
    )
    response.raise_for_status()
    return response.json()["messages"]

def review_message(
    message_id: str,
    decision: Literal["approve", "reject"],
    reviewer: str,
    note: str = ""
) -> dict:
    """
    Approve or reject an agent-drafted outbound email.
    On approve, MultiMail delivers the message and signs it with DKIM.
    On reject, the message is cancelled and logged with the reviewer&"cm">#039;s note.
    """
    response = httpx.post(
        f"{BASE_URL}/decide_email",
        json={
            "message_id": message_id,
            "decision": decision,
            "reviewer": reviewer,
            "note": note
        },
        headers={"Authorization": f"Bearer {MULTIMAIL_API_KEY}"}
    )
    response.raise_for_status()
    return response.json()

# Example: approve the first pending message
pending = get_pending_messages()
if pending:
    result = review_message(
        message_id=pending[0]["message_id"],
        decision="approve",
        reviewer="[email protected]"
    )
    print(result["status"])  # "delivered"

Use list_pending to surface agent-drafted messages awaiting approval, then decide_email to approve or reject. This can be called from an internal admin tool or wired to a Slack command.

Intercom webhook handler that triggers MultiMail
javascript
import express from 'express';
import crypto from 'crypto';

const app = express();
app.use(express.json());

const MULTIMAIL_API_KEY = process.env.MULTIMAIL_API_KEY;
const INTERCOM_SECRET = process.env.INTERCOM_CLIENT_SECRET;
const MULTIMAIL_BASE = 'https://api.multimail.dev';

"cm">// Verify Intercom webhook signature
function verifyIntercomSignature(rawBody, signature) {
  const digest = crypto
    .createHmac('sha1', INTERCOM_SECRET)
    .update(rawBody)
    .digest('hex');
  return crypto.timingSafeEqual(
    Buffer.from(`sha1=${digest}`),
    Buffer.from(signature)
  );
}

app.post('/webhooks/intercom', express.raw({ type: 'application/json' }), async (req, res) => {
  const sig = req.headers['x-hub-signature'];
  if (!verifyIntercomSignature(req.body, sig)) {
    return res.status(401).json({ error: 'Invalid signature' });
  }

  const event = JSON.parse(req.body);

  if (event.topic === 'conversation.resolved' && event.data?.item?.source?.author?.type === 'bot') {
    const conversation = event.data.item;
    const customerEmail = conversation.contacts?.contacts?.[0]?.email;
    const summary = conversation.source?.body ?? '';

    if (customerEmail && summary) {
      const response = await fetch(`${MULTIMAIL_BASE}/send_email`, {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${MULTIMAIL_API_KEY}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          from: '[email protected]',
          to: customerEmail,
          subject: 'Your support case has been resolved',
          body: summary,
          oversight_mode: 'gated_send',
          metadata: {
            source: 'intercom',
            conversation_id: conversation.id
          }
        })
      });

      const result = await response.json();
      console.log('Queued for approval:', result.message_id);
    }
  }

  res.json({ received: true });
});

app.listen(3000);

A minimal Express.js handler that receives Intercom conversation-resolved webhooks and queues the follow-up email in MultiMail for human approval.

Provision a dedicated mailbox for your Intercom bot
python
import httpx

MULTIMAIL_API_KEY = "mm_live_your_key_here"
BASE_URL = "https://api.multimail.dev"

def provision_bot_mailbox(alias: str, display_name: str) -> dict:
    """
    Creates a dedicated mailbox for Intercom AI agent outbound email.
    Replies to this address route through MultiMail&"cm">#039;s inbound pipeline.
    """
    response = httpx.post(
        f"{BASE_URL}/create_mailbox",
        json={
            "address": f"{alias}@multimail.dev",
            "display_name": display_name,
            "oversight_mode": "gated_send",
            "webhook_url": "https://yourapp.com/webhooks/multimail"
        },
        headers={"Authorization": f"Bearer {MULTIMAIL_API_KEY}"}
    )
    response.raise_for_status()
    return response.json()

mailbox = provision_bot_mailbox(
    alias="intercom-bot",
    display_name="Support Bot (via Intercom)"
)
print(mailbox["address"])   # [email protected]
print(mailbox["mailbox_id"]) "cm"># use this when calling send_email

Create a dedicated outbound address for your Intercom AI agent so replies route separately from your human support queue.


Step by step

1

Create a MultiMail account and get an API key

Sign up at multimail.dev and generate a live API key (mm_live_...) from the dashboard. Use a test key (mm_test_...) during development — test mode queues messages but never delivers them.

bash
"cm"># Verify your key works
curl -s https://api.multimail.dev/list_pending \
  -H "Authorization: Bearer $MULTIMAIL_API_KEY" | jq .pending_count
2

Provision a dedicated mailbox for your Intercom bot

Use create_mailbox to give your Intercom AI agent its own address. This keeps bot-originated threads separate from your human support queue and routes replies back through MultiMail.

bash
curl -s -X POST https://api.multimail.dev/create_mailbox \
  -H "Authorization: Bearer $MULTIMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d &"cm">#039;{
    "address": "[email protected]",
    "display_name": "Support Bot",
    "oversight_mode": "gated_send",
    "webhook_url": "https://yourapp.com/webhooks/multimail"
  }&"cm">#039; | jq .mailbox_id
3

Set up the Intercom webhook to trigger MultiMail

In Intercom's Developer Hub, subscribe to conversation.resolved and conversation.created events. Point them at your backend handler, which validates the X-Hub-Signature header and calls MultiMail's send_email endpoint with the bot-drafted content and oversight_mode set to gated_send.

4

Wire up the approval review flow

Call list_pending periodically (or on webhook trigger) to surface messages awaiting review. Your team approves or rejects via decide_email. On approval, MultiMail delivers the message and fires your outbound webhook with the delivery receipt.

bash
"cm"># List pending approvals
curl -s https://api.multimail.dev/list_pending \
  -H "Authorization: Bearer $MULTIMAIL_API_KEY" | jq &"cm">#039;.messages[] | {id: .message_id, to: .to, subject: .subject}'

"cm"># Approve a specific message
curl -s -X POST https://api.multimail.dev/decide_email \
  -H "Authorization: Bearer $MULTIMAIL_API_KEY" \
  -H "Content-Type: application/json" \
  -d &"cm">#039;{"message_id": "msg_abc123", "decision": "approve", "reviewer": "[email protected]"}'
5

Verify delivery and check the audit log

After approving a message, use read_email with the message_id to confirm delivery status, DKIM signature verification, and the approver record. This is your evidence trail for CAN-SPAM compliance and internal audits.

bash
curl -s https://api.multimail.dev/read_email \
  -G --data-urlencode "message_id=msg_abc123" \
  -H "Authorization: Bearer $MULTIMAIL_API_KEY" \
  | jq &"cm">#039;{status: .status, delivered_at: .delivered_at, approved_by: .decision.reviewer, dkim: .dkim_verified}'

Common questions

Does MultiMail replace Intercom's native email channel?
No. Intercom handles inbound conversation management, triage, and Fin AI responses. MultiMail handles outbound email that originates from an AI agent and needs approval gating or cryptographic identity — typically follow-up emails sent after a conversation closes. The two work in parallel; you do not migrate your Intercom setup to use MultiMail.
Can I use gated_send for some message types and autonomous for others?
Yes. You set oversight_mode per message in the send_email call, not per mailbox. A renewal reminder drafted by an agent can go through gated_send while an automated delivery receipt uses autonomous. Audit logging applies to both modes regardless.
How do I route customer replies back into Intercom?
Configure a webhook_url on your MultiMail mailbox. When a customer replies, MultiMail fires your webhook with the inbound message payload. Your handler can then call Intercom's Conversations API to create a new reply on the original conversation thread, keeping context intact.
Does this integration require an Intercom app or OAuth?
No app installation is required. The integration uses Intercom's outbound webhook subscriptions (available on all plans) and Intercom's REST API for reading conversation data. You store your own Intercom access token and MultiMail API key in your backend environment — no OAuth flow between the two platforms.
How does CAN-SPAM compliance work for AI-authored messages?
CAN-SPAM requires commercial emails to identify the sender, include a physical address, and honor opt-outs. MultiMail's DKIM signing and X-MultiMail-Agent headers establish sender identity. Your outbound templates must still include the required physical address and unsubscribe mechanism. The decide_email audit log provides the human-in-the-loop record required by some internal compliance policies, but it does not substitute for required CAN-SPAM content elements.
What happens if a reviewer rejects a message?
The message is permanently cancelled — it is never delivered. MultiMail writes the rejection to the audit log with the reviewer identity, timestamp, and any note they provided. The original draft remains readable via read_email for post-mortem review. You can use the metadata field on the original send_email call (e.g., conversation_id) to correlate the rejection back to the Intercom conversation.

Explore more

The only agent email with a verifiable sender

Email infrastructure built for AI agents. Verifiable identity, graduated oversight, and a 38-tool MCP server. Formally verified in Lean 4.