Skip to main content
Technology & EngineeringEmail Services235 lines

Mailgun

Send transactional and marketing email with Mailgun. Use this skill when the project needs to integrate Mailgun for email sending via API or SMTP, mailing lists, email validation, template management, route-based inbound processing, event tracking, or deliverability optimization. Covers the Mailgun REST API, templates, mailing lists, routes, webhooks, and email validation.

Quick Summary33 lines
You are an email operations specialist who integrates Mailgun into projects. Mailgun
provides a developer-friendly API for transactional and marketing email with strong
support for mailing lists, inbound routing, and email validation.

## Key Points

- Use recipient variables for batch personalization — more efficient than individual sends
- Validate email addresses before adding to mailing lists
- Use tags on every send for filtering events and analytics
- Set up custom tracking domains for branded click/open tracking
- Use Mailgun routes for inbound email processing instead of polling
- Monitor events dashboard for delivery issues
- Use dedicated IPs when sending 50K+ emails/day
- Sending to mailing lists without unsubscribe handling
- Not checking email validation results before bulk sends
- Using the sandbox domain in production
- Ignoring permanent failure webhooks — address will keep bouncing
- Sending marketing email through transactional infrastructure without separation

## Quick Example

```bash
npm install mailgun.js form-data
```

```typescript
const validation = await mg.validate.get('user@example.com');
if (validation.result === 'undeliverable') {
  // Don't send — address is bad
}
```
skilldb get email-services-skills/mailgunFull skill: 235 lines
Paste into your CLAUDE.md or agent config

Mailgun Email Integration

You are an email operations specialist who integrates Mailgun into projects. Mailgun provides a developer-friendly API for transactional and marketing email with strong support for mailing lists, inbound routing, and email validation.

Core Philosophy

API and SMTP parity

Mailgun offers identical functionality through REST API and SMTP. Use the API for modern applications and SMTP for legacy systems. Both support tags, variables, and tracking — choose based on your architecture, not feature needs.

Mailing lists are first-class

Unlike services where you bolt on list management, Mailgun's mailing lists are deeply integrated. You can send to a list address, manage subscribers, and handle unsubscribes natively without external tools.

Routes enable email-driven workflows

Mailgun's route system matches incoming email by recipient or header pattern and forwards, stores, or webhooks the message. This enables reply processing, support ticket creation, and email-driven automation.

Setup

Install

npm install mailgun.js form-data

Initialize

import Mailgun from 'mailgun.js';
import formData from 'form-data';

const mailgun = new Mailgun(formData);
const mg = mailgun.client({
  username: 'api',
  key: process.env.MAILGUN_API_KEY,
  url: 'https://api.mailgun.net', // or https://api.eu.mailgun.net for EU
});

Key Techniques

Simple send

await mg.messages.create('yourdomain.com', {
  from: 'App <noreply@yourdomain.com>',
  to: ['user@example.com'],
  subject: 'Your password reset link',
  text: 'Reset: https://...',
  html: '<p>Click <a href="...">here</a> to reset.</p>',
  'o:tag': ['security', 'password_reset'],
  'v:userId': '123',
});

Template send

Create templates in the Mailgun dashboard or via API, then send with variables.

// Create template via API
await mg.domains.domainTemplates.create('yourdomain.com', {
  name: 'password-reset',
  description: 'Password reset email',
  template: '<p>Hi {{name}}, click <a href="{{resetUrl}}">here</a></p>',
});

// Send with template
await mg.messages.create('yourdomain.com', {
  from: 'App <noreply@yourdomain.com>',
  to: ['user@example.com'],
  subject: 'Reset your password',
  template: 'password-reset',
  'h:X-Mailgun-Variables': JSON.stringify({
    name: 'Alice',
    resetUrl: 'https://...',
  }),
});

Batch send with recipient variables

Send personalized email to many recipients in one API call (up to 1,000).

await mg.messages.create('yourdomain.com', {
  from: 'App <noreply@yourdomain.com>',
  to: ['user1@example.com', 'user2@example.com'],
  subject: 'Your weekly summary, %recipient.name%',
  html: '<p>Hi %recipient.name%, here is your summary...</p>',
  'recipient-variables': JSON.stringify({
    'user1@example.com': { name: 'Alice', id: '1' },
    'user2@example.com': { name: 'Bob', id: '2' },
  }),
});

Scheduled send

await mg.messages.create('yourdomain.com', {
  from: 'App <noreply@yourdomain.com>',
  to: ['user@example.com'],
  subject: 'Trial ending tomorrow',
  html: trialEndingHtml,
  'o:deliverytime': 'Thu, 25 Dec 2025 09:00:00 UTC',
});

Mailing lists

// Create list
await mg.lists.create({
  address: 'newsletter@yourdomain.com',
  name: 'Newsletter',
  access_level: 'readonly',
});

// Add member
await mg.lists.members.createMember('newsletter@yourdomain.com', {
  address: 'user@example.com',
  name: 'Alice',
  vars: JSON.stringify({ plan: 'pro' }),
  subscribed: true,
});

// Send to list
await mg.messages.create('yourdomain.com', {
  from: 'Updates <updates@yourdomain.com>',
  to: ['newsletter@yourdomain.com'],
  subject: 'What shipped this week',
  html: newsletterHtml,
});

Email validation

Verify addresses before sending to reduce bounces.

const validation = await mg.validate.get('user@example.com');
if (validation.result === 'undeliverable') {
  // Don't send — address is bad
}

Inbound routes

// Create a route that forwards matching inbound email to your webhook
await mg.routes.create({
  priority: 0,
  expression: 'match_recipient("support@yourdomain.com")',
  action: ['forward("https://yourdomain.com/api/webhooks/mailgun-inbound")', 'store()'],
  description: 'Support inbox',
});

Webhook Processing

EventAction
deliveredMark delivered in message log
failed (permanent)Suppress address
failed (temporary)Log, monitor for repeated failures
complainedSuppress from non-essential sends
openedUpdate engagement metrics
clickedUpdate engagement metrics
unsubscribedUpdate subscription state
export async function POST(req: Request) {
  const form = await req.formData();
  const event = form.get('event') as string;
  const recipient = form.get('recipient') as string;

  switch (event) {
    case 'failed':
      const severity = form.get('severity') as string;
      if (severity === 'permanent') {
        await suppressAddress(recipient, 'hard_bounce');
      }
      break;
    case 'complained':
      await suppressAddress(recipient, 'complaint');
      break;
    case 'unsubscribed':
      await updateSubscription(recipient, false);
      break;
  }

  return new Response('OK');
}

EU vs US Region

Mailgun offers EU and US hosting. For GDPR compliance, use the EU region:

const mg = mailgun.client({
  username: 'api',
  key: process.env.MAILGUN_API_KEY,
  url: 'https://api.eu.mailgun.net', // EU region
});

Domains must be configured in the matching region.

Best Practices

  • Use recipient variables for batch personalization — more efficient than individual sends
  • Validate email addresses before adding to mailing lists
  • Use tags on every send for filtering events and analytics
  • Set up custom tracking domains for branded click/open tracking
  • Use Mailgun routes for inbound email processing instead of polling
  • Monitor events dashboard for delivery issues
  • Use dedicated IPs when sending 50K+ emails/day

Anti-Patterns

  • Sending to mailing lists without unsubscribe handling
  • Not checking email validation results before bulk sends
  • Using the sandbox domain in production
  • Ignoring permanent failure webhooks — address will keep bouncing
  • Sending marketing email through transactional infrastructure without separation
  • Hardcoding API keys instead of using environment variables

Install this skill directly: skilldb add email-services-skills

Get CLI access →

Related Skills

Mailjet

Send transactional and marketing email with Mailjet. Use this skill when the project needs to integrate Mailjet for email delivery via REST API or SMTP, template management with MJML, contact list management, segmentation, real-time event tracking, send-time optimization, and A/B testing. Covers the Send API v3.1, template language, contact management, and event webhooks.

Email Services318L

Mailtrap

Send and test email with Mailtrap. Use this skill when the project needs to integrate Mailtrap for email testing in development, transactional email sending in production, email previewing, HTML validation, spam score checking, or sandbox email capture. Covers both Mailtrap Email Testing (sandbox) and Mailtrap Email Sending (production transactional API).

Email Services187L

Nodemailer

Send email with Nodemailer in Node.js. Use this skill when the project needs to send email via SMTP, integrate with any SMTP relay (Gmail, Outlook, SES, custom), send attachments, embed images, use HTML templates, or build custom email infrastructure without a managed email API. Covers SMTP transports, pooled connections, attachments, HTML templating, OAuth2, and common relay configurations.

Email Services224L

Plunk

Send transactional and marketing email with Plunk. Use this skill when the project needs to integrate Plunk for open-source email, transactional sends, automated sequences, contact management, or self-hosted email infrastructure. Covers the Plunk API, events-based email triggers, automations, contacts, and self-hosting.

Email Services160L

Postmark

Send transactional email with Postmark. Use this skill when the project needs to integrate Postmark for high-deliverability transactional email, server-side templates, inbound email processing, message streams, bounce handling, or DMARC reporting. Covers the Postmark API, template system, message streams, webhooks, and deliverability features.

Email Services211L

React Email

Build email templates with React Email. Use this skill when the project needs to create type-safe, component-based email templates using React, preview emails during development, render to HTML for any email provider, or build a shared email design system. Covers React Email components, preview server, rendering, and integration with Resend, SendGrid, Postmark, AWS SES, and Nodemailer.

Email Services233L