#Mailgun's
Spent a week with Mailgun's support debugging a login creation issue.

The reason? Password has to meet certain requirements, but Mailgun never communicates them. You only get a random error message and that's it.

Even support provided me incorrect requirements.

Catastrophic UX.
August 28, 2026 at 3:05 PM
Welp, I have failed to successfully jump through #Mailgun's hoops over the space of a month.

So that's my #Ghost blog f**ked at the moment.

This is incredibly frustrating as I've been trying to self-host for the first time.

Ghost's reliance on Mailgun as its default is a huge weakness.

#GhostCMS
May 8, 2025 at 3:27 PM
it's pretty easy, your main cost is going to be the VPS, I have like a 7 euro hetzner one that's more than enough. a domain, free letsencrypt SSL, free cloudflare for cache/dns, and I use mailgun's pay-as-you-go tier for send, which is $1per1000 emails so if you're low volume it's under $20/mo
December 19, 2024 at 7:46 PM
Check out my latest article for Mailgun.👇

"Mailgun's webhooks notify your application when email events occur–such as deliveries, bounces, or opens – allowing it to process events as they happen."📩

#programming

www.mailgun.com/blog/dev-lif...
Automate Email Monitoring with Mailgun Webhooks & Datadog | Mailgun
Track email events in real time with Mailgun’s webhooks and Datadog. Automate alerts, monitor deliveries, clicks, and failures, and optimize email performance effortlessly.
www.mailgun.com
March 13, 2025 at 5:10 AM
Self-hosting a newsletter is terrible. I'm currently at the phase where I'm trying to work around Mailgun's 9 emails per hour limit until they decide I'm not a spammer.
February 6, 2025 at 9:47 PM
There's a new post for subscribers today that is stalled in Mailgun's email system … you can view it directly on the website, or wait until the announcement (finally) appears.
theapiarist.org/are-slow-rel...
#beekeeping #wedonothavethetechnology
Are slow-release oxalic acid strips the solution?
Slow-release oxalic acid (OA) strips are for use on colonies rearing brood, in contrast to one-shot trickled or vaporised OA. Are they an effective solution for winter treatment when predicting…
theapiarist.org
July 31, 2026 at 6:31 PM
Well I was supposed to upload another episode of Emails Not Dead today but my MacBook has decided to hit the ol dusty trail and retire.

Please listen to our season opener with @bwestnedge.bsky.social on how we’re trying to make DMARC easier!

www.mailgun.com/resources/po...
Podcasts | Mailgun Resource Center | Mailgun
Check out Mailgun's podcast, Email's Not Dead. Listen to industry experts and email geeks discuss and debate topics impacting email and how we communicate.
www.mailgun.com
April 9, 2025 at 4:36 PM
Afraid I haven't done the setup process with Ghost 6.0 so it may be a little different but I documented the Pikapods process I went through here. Mailgun's the hardest bit but not all that bad!
Substack to Ghost import guide for 2024: How I migrated my newsletter
How to migrate a newsletter to a self-hosted Ghost installation.
www.readonlymemo.com
August 28, 2025 at 3:17 AM
✅ The earlier critical outage affecting Mailgun's EU Messaging has been resolved. All services are fully operational. View full incident report at https://watchrr.app/service/mailgun
September 4, 2026 at 2:36 PM
Mailgun back up? Yes. Mailgun's official status page reports recovery. You can stop second-guessing your config, but keep an eye on retries while traffic settles.
September 4, 2026 at 1:17 PM
Sinch Launches Mailgun Inspect for Enhanced Email Testing on Salesforce's AgentExchange#USA#Stockholm#Salesforce#AgentExchange#Sinch_Mailgun
Sinch Launches Mailgun Inspect for Enhanced Email Testing on Salesforce's AgentExchange
Discover how Sinch Mailgun's new tool, Mailgun Inspect, enhances email testing for marketers directly within Salesforce, improving campaign reliability.
third-news.com
September 1, 2026 at 2:09 PM
Is Mailgun having problems right now? Yes—Mailgun's official status page is reporting a critical incident: EU Messaging Outage. Check your retries before changing production.
August 28, 2026 at 2:16 AM
Today on a slightly unreliable Internet connection I discovered that the Mailgun admin portal tries to load _fifteen megabytes_ of JavaScript in order even to open, and now honestly I'm kind of convinced we should just pack this whole internet thing up, it might be time
August 12, 2026 at 8:34 AM
✅ The earlier major outage affecting Mailgun's Click and Open Tracking Degraded service is now RESOLVED. All systems are fully operational. View full incident report at https://watchrr.app/service/mailgun
August 11, 2026 at 7:08 AM
Having trouble with Mailgun? Mailgun's official status page has confirmed a major incident: Click and Open Tracking Degraded. So no, it may not be just your setup.
August 11, 2026 at 5:59 AM
Building a Transactional Email CLI with Mailgun and Python
If your app needs to send a welcome email, a password reset link, or an order confirmation, you don't need to stand up a mail server. You need one HTTP call. This tutorial builds a small Python CLI that sends transactional email through Mailgun's API, then checks whether Mailgun actually delivered it. By the end, you'll have replaced "sending email" with a simpler model: call an API, read the response, done. ## What you need before starting Before you start, gather the following: * Basic Python knowledge. * Python installed. * A Mailgun account (the free tier works). * The `requests` library (`pip install requests`). ## What you'll build The app is a small CRUD tool with four actions: * Send an email. * List what's been sent. * Check delivery status. * Delete a record. Two files do the real work: * `mailgun_client.py` — the only file that talks to Mailgun; it sends emails and checks their status. * `storage.py` — logs each sent email to a local JSON file, so there's something to check later. `main.py` wires these two together into a menu, and `config.py` loads your Mailgun credentials. Neither file does anything Mailgun-specific. This tutorial moves through them quickly and spends most of its time on `mailgun_client.py`, where the real subject lives. ## Set up your Mailgun account Sign up for a free Mailgun account. Every account starts with a sandbox domain — a Mailgun-provided domain you can send test emails from immediately, without verifying your own domain's DNS records. Grab two things from the dashboard, both under **Sending → Domain settings** : * Your **domain** (the sandbox domain, e.g. `sandboxXXXX.mailgun.org`, or your own verified domain) * Your **API key** One sandbox-specific rule catches people the first time: sandbox domains only deliver to _authorized recipients_. Before you can send yourself a test email, add your own address under **Authorized Recipients** in the dashboard. Skip this step, and Mailgun accepts the request but never delivers it — exactly the silent failure the status-check step later in this tutorial is built to catch. ## Configure your credentials Store your API key, domain, and sender address as environment variables — never in code. `config.py` loads them with a small dotenv reader (no extra dependencies), then fails fast if anything's missing: MAILGUN_API_KEY = os.environ.get("MAILGUN_API_KEY") MAILGUN_DOMAIN = os.environ.get("MAILGUN_DOMAIN") MAILGUN_SENDER = os.environ.get("MAILGUN_SENDER") MAILGUN_BASE_URL = os.environ.get("MAILGUN_BASE_URL", "https://api.mailgun.net/v3") `MAILGUN_BASE_URL` defaults to Mailgun's US host. If your account is on Mailgun's EU region, set this to `https://api.eu.mailgun.net/v3` instead — worth knowing before a mismatched region costs you a confusing 401. With `MAILGUN_API_KEY`, `MAILGUN_DOMAIN`, and `MAILGUN_SENDER` set in a `.env` file, the app is ready to talk to Mailgun. ## Send the email This function delivers on the tutorial's promise. Everything before it was setup; everything after it is bookkeeping. def send_email(to, subject, body, sender): response = requests.post( f"{MAILGUN_BASE_URL}/{MAILGUN_DOMAIN}/messages", auth=("api", MAILGUN_API_KEY), data={ "from": sender, "to": to, "subject": subject, "text": body, }, ) response.raise_for_status() return response.json() A transactional email, structurally, is four fields: `from`, `to`, `subject`, `text`. Mailgun's Messages API takes exactly those four as form fields on a `POST` to `/{domain}/messages`. There's no envelope object, no MIME construction, no SMTP handshake — you build a dictionary and make one request. Two details here are easy to get wrong the first time: * **Auth is HTTP Basic Auth, not a bearer token.** The username is the literal string `"api"`; your API key is the password. `requests` handles the encoding through the `auth=` tuple — but if you're used to APIs that expect `Authorization: Bearer <token>`, this is a different shape. * **The payload is form-encoded, not JSON.** `data={...}` sends `application/x-www-form-urlencoded`, which is what Mailgun's Messages API expects — even though the _response_ comes back as JSON. Passing `json=` here instead of `data=` is a common first mistake, and the resulting error doesn't make the cause obvious. `response.raise_for_status()` turns a 4xx or 5xx response into a Python exception immediately, instead of letting a failed send look successful. `response.json()` hands back Mailgun's confirmation, including a message ID — the thread that connects sending an email to checking on its delivery later. ## Confirm the email actually delivered Here's the detail that matters most: **Mailgun accepting your request is not the same as Mailgun delivering your email.** A `200` response means "I've queued this to send," not "your recipient has it." Confirming delivery means asking Mailgun a second, separate question. Mailgun doesn't expose a "get status by message ID" endpoint. Instead, you query its Events API — a log of everything that's happened to your domain's messages — and filter by ID: def get_delivery_status(message_id): clean_id = message_id.strip("<>") response = requests.get( f"{MAILGUN_BASE_URL}/{MAILGUN_DOMAIN}/events", auth=("api", MAILGUN_API_KEY), params={"message-id": clean_id}, ) response.raise_for_status() events = response.json().get("items", []) if not events: return "unknown" return events[0].get("event", "unknown") Two quirks are worth knowing before you hit them: * The message ID `send_email()` returns is wrapped in angle brackets (`<abc123@sandbox...mailgun.org>`), but the Events filter expects the bare ID. `strip("<>")` handles the mismatch. * The event log can lag a few seconds behind the send. Check status immediately after sending, and you may get `"unknown"` back — not because anything failed, but because Mailgun hasn't logged the event yet. Waiting a moment and checking again usually resolves it. `events[0]` is the most recent event for that message — typically `delivered`, `accepted`, or `failed`. That single string is confirmation that the email didn't just leave your app; it actually arrived. ## Wire the send and status functions into the app `main.py` calls these two functions and logs the result. The send step looks like this: result = mailgun_client.send_email( to=to, subject=subject, body=body, sender=config.MAILGUN_SENDER, ) record = storage.create_record({ "to": to, "mailgun_message_id": result["id"], "status": "queued", # ... }) `storage.py` writes that record to a local JSON file — not because Mailgun requires it, but because Mailgun doesn't keep "your" list of sent emails, only a raw event log. The local record is what lets you look up a message ID later and ask `get_delivery_status()` about it. ## Run the app $ python main.py --- Mailgun Transactional Email Manager --- 1. Send a new email (Create) 2. List logged emails (Read) 3. Refresh delivery status (Update) 4. Delete a logged email (Delete) 5. Quit Choose an option: 1 Recipient email: you@example.com Subject: Test send Body text: Hello from the Mailgun API. Sent. Local record #1 created. Mailgun says: Queued. Thank you. Choose option 3 and enter `1`, and the app queries the Events API and updates the record — `queued` becomes `delivered` (or `accepted`, depending on timing). If it still shows `unknown`, wait a few seconds and check again; that's the event-log lag, not a bug. ## Treat sending email as an API call Nowhere in this project is there SMTP configuration, a mail server, or a queuing system to install. There's one `POST` to send an email and one `GET` to confirm it arrived — both plain HTTP calls made with `requests`. That's the mental model worth keeping: sending email from an app isn't a mail-server problem. It's an API call. **The repository for the code link : https://github.com/anthonyonyenaobijeffery-debug/Sending-Transactional-Emails-in-Python-with-Mailgun**
dev.to
July 6, 2026 at 12:03 AM
I applaud Mailgun’s efforts to provide a translation of their error messages into Douchebro English. Thoughtful!
November 2, 2024 at 2:45 PM
today we learned that mailgun's inbound SMTP servers respond with `250 Great success` to a successful end-of-data and `221 See you later. Yours truly, Mailgun` to a `QUIT`
September 14, 2025 at 7:06 PM
You mean something like Mailgun‘s templates? Ideally I‘d also like to replace SES with a service that operates within the EU. www.scaleway.com/en/transacti... sounds promising.
Transactional Email (TEM) | Scaleway
Easily send transactional emails and enjoy instant delivery, backed by Scaleway’s secure & sovereign infrastructure, ensuring high deliverability and scalability.
www.scaleway.com
February 3, 2026 at 8:38 AM
Luego el tema del correo tienes varias opciones, pero sería el último gasto.
Al principio cualquier servicio gratuito puede valer, yo uso mucho www.mailgun.com/es/productos... que crece contigo...
Email Sending Service Solutions - Transactional Email API Service For Developers | Mailgun
Discover Mailgun’s email-sending service with API, SMTP, and inbound routing. With easy setup and up-to-date SDKs, sending and receiving emails is effortless.
www.mailgun.com
April 5, 2026 at 3:34 PM
Mailgun's email validation API can catch invalid addresses before they ever hit your list.

Mailgun is… https://emailexacto.com/learn/mailgun
https://emailexacto.com/learn/mailgun
Mailgun | EmailExacto Learn
Mailgun | EmailExacto Learn
emailexacto.com
May 13, 2026 at 1:03 PM
Mail not sending due to Mailgun's use of wildcard SSL certificate. The Basics Nextcloud Server version (e.g., 29.x.x) : 31.0.6.2 Operating system and version (e.g., Ubuntu 24.04) : Linux 6.15.4...

Origin | Interest | Match
Awakari App
awakari.com
July 7, 2025 at 12:59 PM
So stripping out Mailgun and their links keeps them from tracking what email, browser, device, etc. you're using. All of which, while not exactly PII, is easily merged with other data to find you.

Not a huge deal, but just makes me feel more comfortable signing up for newsletters.
August 25, 2023 at 9:39 PM