{
  "version": "https://jsonfeed.org/version/1.1",
  "title": "MailKite — Field notes",
  "home_page_url": "https://mailkite.dev/blog/",
  "feed_url": "https://mailkite.dev/feed.json",
  "description": "Notes on developer email infrastructure, inbound webhooks, AI agents, and building safely fast.",
  "language": "en-US",
  "items": [
    {
      "id": "https://mailkite.dev/blog/self-healing-software-agentic-era/",
      "url": "https://mailkite.dev/blog/self-healing-software-agentic-era/",
      "title": "Build software that heals itself in the agentic era",
      "summary": "In the agentic era, an AI agent can write the fix — but letting one patch production is terrifying unless the architecture makes it safe. Here's a software-design pattern for self-healing systems: never crash, turn every failure into a structured anonymous signature, and let an agent close the loop behind a sandbox and adversarial gates. Our open-source MIME parser is the worked example; the pattern applies far beyond it.",
      "date_published": "2026-07-15T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "agents",
        "security",
        "open-source"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/agent-inbox-security-by-design/",
      "url": "https://mailkite.dev/blog/agent-inbox-security-by-design/",
      "title": "You can't prompt your way out of prompt injection",
      "summary": "Part two. In the last post I admitted I'd opened a security hole: I gave an agent an inbox and told it to follow instructions in emails. Here's the architecture I landed on — ACL-gated by design, so a fully hijacked agent still can't do any damage.",
      "date_published": "2026-07-08T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "agents",
        "security"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/agent-security-blind-spot/",
      "url": "https://mailkite.dev/blog/agent-security-blind-spot/",
      "title": "Why aren't we seeing more agent security discussions?",
      "summary": "Agents are writing our codebases and running on our platforms — and the security conversation hasn't caught up. A field note on the vectors that came back, and one I opened on myself.",
      "date_published": "2026-07-01T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "agents",
        "security"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/amazon-ses-alternative/",
      "url": "https://mailkite.dev/blog/amazon-ses-alternative/",
      "title": "The Amazon SES alternative for developers",
      "summary": "Amazon SES is the cheapest way to send at scale and the most assembly-required way to do anything else: sending starts sandboxed behind an AWS approval, bounce and complaint handling is your Lambda to write, and receiving means raw MIME dropped in an S3 bucket you fetch and parse yourself. Here's a fair comparison, and what MailKite does differently — send the moment DNS verifies, inbound as parsed JSON, no S3/SNS/Lambda/IAM.",
      "date_published": "2026-07-01T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "comparison",
        "ses",
        "deliverability"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/byte-identical-mime-failures/",
      "url": "https://mailkite.dev/blog/byte-identical-mime-failures/",
      "title": "I wrote the same email parser three times — and the hard part was making them fail identically",
      "summary": "Parsing MIME in Node, Python, and Go is the easy part. Getting all three to break the same way on the same broken email — and to say so with the same hash — is where the real work is. Here's how, and the two lessons that transfer to any polyglot library.",
      "date_published": "2026-06-24T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "inbound",
        "tutorial"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/mailgun-routes-alternative/",
      "url": "https://mailkite.dev/blog/mailgun-routes-alternative/",
      "title": "The honest Mailgun Routes alternative",
      "summary": "Mailgun Routes is a filter-expression engine for inbound mail: you write match_recipient/match_header rules that fire forward() and store() actions, and Mailgun POSTs the parsed message to your endpoint as form-encoded fields. MailKite is a routes alternative that drops the rule DSL — point an address or catch-all at a webhook and the message arrives as a single JSON payload with decoded text/html, SPF/DKIM/DMARC results, and signed attachment URLs. Here's a fair comparison, and where I won't overclaim.",
      "date_published": "2026-06-24T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "comparison",
        "inbound",
        "mailgun"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/deliverability-black-box-shared-ips/",
      "url": "https://mailkite.dev/blog/deliverability-black-box-shared-ips/",
      "title": "Deliverability is a black box, and shared IPs let strangers tank you",
      "summary": "On shared-IP transactional email, a stranger's spam can sink your inbox placement — and the provider hands you a black box instead of an answer. Here's what actually moves the needle: real SPF/DKIM/DMARC, a monitored stream, and an auth field you can read.",
      "date_published": "2026-06-17T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "deliverability",
        "trust"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/give-your-agent-an-inbox/",
      "url": "https://mailkite.dev/blog/give-your-agent-an-inbox/",
      "title": "Give your AI agent its own email inbox",
      "summary": "An AI agent that can't receive email is half-deaf. Here's how to give an agent a real, scoped address on your own domain — inbound parsed to JSON, an event.received loop, and autonomous replies over the same API you already use.",
      "date_published": "2026-06-10T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "agents",
        "tutorial",
        "inbound"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/receive-email-in-python/",
      "url": "https://mailkite.dev/blog/receive-email-in-python/",
      "title": "Receive email in Python (Django & FastAPI)",
      "summary": "Install mailkite-dev, point a domain at MailKite, and receive parsed inbound email as JSON in a Django view or a FastAPI handler. The one rule that matters: verify the signature against the raw request body — request.body in Django, await request.body() in FastAPI.",
      "date_published": "2026-06-03T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "inbound",
        "tutorial",
        "python",
        "webhooks"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/killed-my-account-no-warning/",
      "url": "https://mailkite.dev/blog/killed-my-account-no-warning/",
      "title": "They killed my account with no warning",
      "summary": "The developer-email industry has a pattern: silent suspensions, unappealable bans, and free tiers that vanish the moment they cost the vendor money. Here's the pattern, the receipts, and the stance we took to not become another one.",
      "date_published": "2026-05-27T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "trust",
        "comparison"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/support-inbox-nextjs/",
      "url": "https://mailkite.dev/blog/support-inbox-nextjs/",
      "title": "Build a support inbox in Next.js (email in, tickets out)",
      "summary": "Point support@yourdomain at MailKite, parse the inbound email to JSON, and POST it to a Next.js Route Handler. Verify the signature against the raw body, create a ticket, and auto-reply — the whole loop, in real code.",
      "date_published": "2026-05-20T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "tutorial",
        "nextjs",
        "inbound",
        "webhooks"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/sendgrid-inbound-parse-alternative/",
      "url": "https://mailkite.dev/blog/sendgrid-inbound-parse-alternative/",
      "title": "The honest SendGrid Inbound Parse alternative",
      "summary": "SendGrid Inbound Parse POSTs your inbound mail as multipart/form-data and leaves the parsing, decoding, and attachment handling to you — with a well-earned reputation for encoding and attachment mangling. Here's a fair comparison, what MailKite does differently (fully parsed JSON, auth results, signed attachment URLs, no daily cap), and what it doesn't.",
      "date_published": "2026-05-13T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "comparison",
        "inbound",
        "sendgrid"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/cloudflare-email-routing-cant-reply/",
      "url": "https://mailkite.dev/blog/cloudflare-email-routing-cant-reply/",
      "title": "Cloudflare Email Routing can't reply — here's how to send from your domain",
      "summary": "Cloudflare Email Routing forwards inbound mail beautifully and Email Workers hand you the raw message — but there's no first-class way to reply or send from your own domain. Here's exactly where the gap is, why the 'just add Email Service' answer is more assembly than it sounds, and how to receive parsed JSON and reply from one API instead.",
      "date_published": "2026-05-06T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "comparison",
        "cloudflare",
        "tutorial"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/email-attachments-without-corruption/",
      "url": "https://mailkite.dev/blog/email-attachments-without-corruption/",
      "title": "Handling email attachments without losing the £ sign",
      "summary": "Inbound attachments are where email parsing goes to die — inline base64 that bloats every webhook, and charset bugs that turn £ into Â£. Here's why it happens, why SendGrid Inbound Parse is infamous for it, and what a clean attachments[] array with signed URLs looks like instead.",
      "date_published": "2026-04-29T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "inbound",
        "attachments",
        "tutorial"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/verify-inbound-webhooks-hmac/",
      "url": "https://mailkite.dev/blog/verify-inbound-webhooks-hmac/",
      "title": "Verify your inbound email webhooks (HMAC — and why you must)",
      "summary": "An unverified webhook endpoint is an open door: anyone can POST a fake email.received event. Here's how to verify the HMAC signature in Node, Python, and Go — and why the raw body matters.",
      "date_published": "2026-04-22T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "webhooks",
        "security",
        "tutorial"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/reply-by-email-in-your-app/",
      "url": "https://mailkite.dev/blog/reply-by-email-in-your-app/",
      "title": "Reply-by-email: handling inbound replies in your app",
      "summary": "When users reply to your notification emails, capture the reply, thread it to the right conversation, and respond — either with an inline ack or a real outbound message.",
      "date_published": "2026-04-15T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "inbound",
        "tutorial",
        "webhooks"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/parse-inbound-email-to-json-node/",
      "url": "https://mailkite.dev/blog/parse-inbound-email-to-json-node/",
      "title": "Parse inbound email to JSON in Node.js",
      "summary": "A hands-on Node.js walkthrough: point a domain at MailKite and receive every inbound email as clean, decoded JSON in one webhook — verify it, then read text, html, and attachments.",
      "date_published": "2026-04-08T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "inbound",
        "tutorial",
        "nodejs",
        "webhooks"
      ]
    },
    {
      "id": "https://mailkite.dev/blog/receiving-email-nobody-warns-you/",
      "url": "https://mailkite.dev/blog/receiving-email-nobody-warns-you/",
      "title": "Receiving email is the part nobody warns you about",
      "summary": "Sending email is a solved problem. Receiving it — turning real-world MIME into something your app can use — is where everyone quietly loses a week. Here's why inbound is the hard direction, how each option punts, and what one clean webhook looks like instead.",
      "date_published": "2026-04-01T00:00:00.000Z",
      "author": {
        "name": "Gabe"
      },
      "tags": [
        "inbound",
        "webhooks",
        "tutorial"
      ]
    }
  ]
}