mcpField
S
smtp2go-api

smtp2go-api

github.com/jezwebOther1.1k110 installsUpdated 3w ago
Repository

About smtp2go-api

A developer skill guide for integrating applications with the SMTP2GO v3 API to send transactional email and SMS. It also documents templates, attachments, webhooks, activity search, suppression lists, and delivery statistics.

Key features

  1. 01Transactional email and SMS sending
  2. 02MIME messages and file attachments
  3. 03Template creation and sending
  4. 04Delivery event webhooks
  5. 05Activity search and delivery statistics

Use cases

  1. 01Sending transactional emails from an application
  2. 02Delivering SMS through SMTP2GO
  3. 03Receiving delivery, bounce, and engagement events
  4. 04Reviewing delivery activity and email statistics

Install

Copy the command and run it in a terminal.

$npx skills add https://github.com/jezweb/claude-skills --skill smtp2go-api

After installing, type/smtp2go-apiin Claude Code to confirm it loaded.

Bundled files

References and scripts installed along with SKILL.md.

README.md
.claude-plugin/
plugin.json
references/
endpoints.md

Details

From the project README

SMTP2GO API Integration

Build email and SMS delivery with the SMTP2GO transactional API.

Quick Start

// Send email with SMTP2GO
const response = await fetch('https://api.smtp2go.com/v3/email/send', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
  },
  body: JSON.stringify({
    sender: '[email protected]',
    to: ['[email protected]'],
    subject: 'Hello from SMTP2GO',
    html_body: '<h1>Welcome!</h1><p>Your account is ready.</p>',
    text_body: 'Welcome! Your account is ready.',
  }),
});

const result = await response.json();
// { request_id: "uuid", data: { succeeded: 1, failed: 0, email_id: "1er8bV-6Tw0Mi-7h" } }

Base URLs

RegionBase URL
Globalhttps://api.smtp2go.com/v3
UShttps://us-api.smtp2go.com/v3
EUhttps://eu-api.smtp2go.com/v3
AUhttps://au-api.smtp2go.com/v3

Authentication

Two methods supported:

// Method 1: Header (recommended)
headers: {
  'X-Smtp2go-Api-Key': 'your-api-key'
}

// Method 2: Request body
body: JSON.stringify({
  api_key: 'your-api-key',
  // ... other params
})

Get API keys from SMTP2GO dashboard: Sending > API Keys

Core Endpoints

Send Standard Email

POST /email/send

interface EmailSendRequest {
  // Required
  sender: string;           // Verified sender email
  to: string[];             // Recipients (max 100)
  subject: string;

  // Content (at least one required)
  html_body?: string;
  text_body?: string;

  // Optional
  cc?: string[];            // CC recipients (max 100)
  bcc?: string[];           // BCC recipients (max 100)
  reply_to?: string;
  custom_headers?: Array<{ header: string; value: string }>;
  attachments?: Attachment[];
  inlines?: InlineImage[];

  // Templates
  template_id?: string;
  template_data?: Record<string, any>;

  // Subaccounts
  subaccount_id?: string;
}

interface Attachment {
  filename: string;
  mimetype: string;
  fileblob?: string;        // Base64-encoded content
  url?: string;             // OR URL to fetch from
}

interface InlineImage {
  filename: string;
  mimetype: string;
  fileblob: string;
  cid: string;              // Content-ID for HTML reference
}

Response:

interface EmailSendResponse {
  request_id: string;
  data: {
    succeeded: number;
    failed: number;
    failures: string[];
    email_id: string;
  };
}
Send MIME Email

POST /email/mime

For pre-encoded MIME messages:

const response = await fetch('https://api.smtp2go.com/v3/email/mime', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
  },
  body: JSON.stringify({
    mime_email: mimeEncodedString,
  }),
});

Attachments

Base64 Encoding
// Convert file to base64
const fileBuffer = await file.arrayBuffer();
const base64 = btoa(String.fromCharCode(...new Uint8Array(fileBuffer)));

const email = {
  sender: '[email protected]',
  to: ['[email protected]'],
  subject: 'Document attached',
  text_body: 'Please find the document attached.',
  attachments: [{
    filename: 'report.pdf',
    fileblob: base64,
    mimetype: 'application/pdf',
  }],
};
URL Reference (Cached 24h)
const email = {
  sender: '[email protected]',
  to: ['[email protected]'],
  subject: 'Image attached',
  text_body: 'Photo from our event.',
  attachments: [{
    filename: 'photo.jpg',
    url: 'https://cdn.example.com/photos/event.jpg',
    mimetype: 'image/jpeg',
  }],
};
Inline Images in HTML
const email = {
  sender: '[email protected]',
  to: ['[email protected]'],
  subject: 'Newsletter',
  html_body: '<h1>Welcome</h1><img src="cid:logo123" alt="Logo">',
  inlines: [{
    filename: 'logo.png',
    fileblob: logoBase64,
    mimetype: 'image/png',
    cid: 'logo123',  // Reference in HTML as src="cid:logo123"
  }],
};

Limits: Maximum total email size: 50 MB (content + attachments + headers)

Templates

Create Template

POST /template/add

const response = await fetch('https://api.smtp2go.com/v3/template/add', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
  },
  body: JSON.stringify({
    template_name: 'welcome-email',
    html_body: '<h1>Welcome, {{ name }}!</h1><p>Thanks for joining {{ company }}.</p>',
    text_body: 'Welcome, {{ name }}! Thanks for joining {{ company }}.',
  }),
});
Send with Template
const email = {
  sender: '[email protected]',
  to: ['[email protected]'],
  subject: 'Welcome aboard!',
  template_id: 'template-uuid-here',
  template_data: {
    name: 'John',
    company: 'Acme Corp',
  },
};

Template Syntax: HandlebarsJS with {{ variable }} placeholders.

Template Endpoints
EndpointMethodDescription
/template/addPOSTCreate new template
/template/editPOSTUpdate existing template
/template/deletePOSTRemove template
/template/searchPOSTList/search templates
/template/viewPOSTGet template details

Webhooks

Configure webhooks to receive real-time delivery notifications.

Event Types

Email Events:

EventDescription
processedEmail queued for delivery
deliveredSuccessfully delivered
openRecipient opened email
clickLink clicked
bounceDelivery failed
spamMarked as spam
unsubscribeUser unsubscribed
resubscribeUser resubscribed
rejectBlocked (suppression/sandbox)

SMS Events:

EventDescription
sendingProcessing
submittedSent to provider
deliveredConfirmed delivery
failedDelivery failed
rejectedNetwork blocked
opt-outRecipient opted out
Webhook Payload (Email)
interface WebhookPayload {
  event: string;
  time: string;           // Event timestamp
  sendtime: string;       // Original send time
  sender: string;
  from_address: string;
  rcpt: string;           // Recipient
  recipients: string[];
  email_id: string;
  subject: string;
  bounce?: string;        // Bounce type if applicable
  client?: string;        // Email client (for opens)
  'geoip-country'?: string;
}
Webhook Configuration

POST /webhook/add

await fetch('https://api.smtp2go.com/v3/webhook/add', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
  },
  body: JSON.stringify({
    url: 'https://api.yourdomain.com/webhooks/smtp2go',
    events: ['delivered', 'bounce', 'spam', 'unsubscribe'],
  }),
});
Webhook Endpoints
EndpointMethodDescription
/webhook/viewPOSTList webhooks
/webhook/addPOSTCreate webhook
/webhook/editPOSTUpdate webhook
/webhook/removePOSTDelete webhook

Retry Policy: Up to 35 retries over 48 hours. Timeout: 10 seconds.

Statistics

Email Summary

POST /stats/email_summary

Combined report of bounces, cycles, spam, and unsubscribes.

const response = await fetch('https://api.smtp2go.com/v3/stats/email_summary', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
  },
  body: JSON.stringify({}),
});
Statistics Endpoints
EndpointMethodDescription
/stats/email_summaryPOSTCombined statistics
/stats/email_bouncesPOSTBounce summary (30 days)
/stats/email_cyclePOSTEmail cycle data
/stats/email_historyPOSTHistorical data
/stats/email_spamPOSTSpam reports
/stats/email_unsubsPOSTUnsubscribe data

Activity Search

POST /activity/search (Rate limited: 60/min)

Search for email events:

const response = await fetch('https://api.smtp2go.com/v3/activity/search', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
  },
  body: JSON.stringify({
    // Filter parameters
  }),
});

Note: Returns max 1,000 items. For real-time data, use webhooks instead.

Suppressions

Manage email addresses that should not receive emails.

Add Suppression

POST /suppression/add

await fetch('https://api.smtp2go.com/v3/suppression/add', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
  },
  body: JSON.stringify({
    email: '[email protected]',
  }),
});
Suppression Endpoints
EndpointMethodDescription
/suppression/addPOSTAdd to suppression list
/suppression/viewPOSTView suppressions
/suppression/removePOSTRemove from list

SMS

POST /sms/send

const response = await fetch('https://api.smtp2go.com/v3/sms/send', {
  method: 'POST',
  headers: {
    'Content-Type': 'application/json',
    'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
  },
  body: JSON.stringify({
    to: ['+61400000000'],  // Max 100 numbers
    message: 'Your verification code is 123456',
  }),
});
SMS Endpoints
EndpointMethodDescription
/sms/sendPOSTSend SMS
/sms/receivedPOSTView received SMS
/sms/sentPOSTView sent SMS
/sms/summaryPOSTSMS statistics

Response Codes

CodeStatusDescription
200OKSuccess
400Bad RequestInvalid parameters
401UnauthorizedInvalid/missing API key
402Request FailedValid params, request failed
403ForbiddenInsufficient permissions
404Not FoundResource not found
429Too Many RequestsRate limited
5xxServer ErrorSMTP2GO server issue
Error Response Format
interface ErrorResponse {
  request_id: string;
  data: {
    error: string;
    error_code: string;
    field_validation_errors?: Record<string, string>;
  };
}

Common error codes:

  • E_ApiResponseCodes.ENDPOINT_PERMISSION_DENIED - API key lacks permission
  • E_ApiResponseCodes.NON_VALIDATING_IN_PAYLOAD - Invalid JSON/email format
  • E_ApiResponseCodes.API_EXCEPTION - General API error

Rate Limiting

  • Activity Search: 60 requests/minute
  • Email Search (deprecated): 20 requests/minute
  • Other endpoints: Configurable per API key

Handling 429:

async function sendWithRetry(payload: any, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch('https://api.smtp2go.com/v3/email/send', {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
      },
      body: JSON.stringify(payload),
    });

    if (response.status === 429) {
      await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
      continue;
    }

    return response.json();
  }
  throw new Error('Rate limit exceeded after retries');
}

Cloudflare Workers Integration

// wrangler.jsonc
{
  "name": "email-service",
  "vars": {
    "SMTP2GO_REGION": "api"  // or "us-api", "eu-api", "au-api"
  }
}

// .dev.vars
SMTP2GO_API_KEY=api-XXXXXXXXXXXX
// src/index.ts
export default {
  async fetch(request: Request, env: Env) {
    const baseUrl = `https://${env.SMTP2GO_REGION}.smtp2go.com/v3`;

    // Send transactional email
    const response = await fetch(`${baseUrl}/email/send`, {
      method: 'POST',
      headers: {
        'Content-Type': 'application/json',
        'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
      },
      body: JSON.stringify({
        sender: '[email protected]',
        to: ['[email protected]'],
        subject: 'Order Confirmation',
        template_id: 'order-confirmation-template',
        template_data: {
          order_id: '12345',
          total: '$99.00',
        },
      }),
    });

    const result = await response.json();
    return Response.json(result);
  },
} satisfies ExportedHandler<Env>;

interface Env {
  SMTP2GO_API_KEY: string;
  SMTP2GO_REGION: string;
}

Sender Verification

Before sending, verify your sender identity:

  1. Sender Domain (Recommended): Add and verify domain in SMTP2GO dashboard for SPF/DKIM alignment
  2. Single Sender Email: Verify individual email address

Unverified senders are rejected with 400 error.

Common Patterns

Contact Form Handler
export async function handleContactForm(formData: FormData, env: Env) {
  const name = formData.get('name') as string;
  const email = formData.get('email') as string;
  const message = formData.get('message') as string;

  const response = await fetch('https://api.smtp2go.com/v3/email/send', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'X-Smtp2go-Api-Key': env.SMTP2GO_API_KEY,
    },
    body: JSON.stringify({
      sender: '[email protected]',
      to: ['[email protected]'],
      reply_to: email,
      subject: `Contact form: ${name}`,
      text_body: `From: ${name} <${email}>\n\n${message}`,
      html_body: `
        <p><strong>From:</strong> ${name} &lt;${email}&gt;</p>
        <hr>
        <p>${message.replace(/\n/g, '<br>')}</p>
      `,
    }),
  });

  if (!response.ok) {
    throw new Error('Failed to send email');
  }

  return response.json();
}
Webhook Handler
export async function handleWebhook(request: Request) {
  const payload = await request.json();

  switch (payload.event) {
    case 'bounce':
      // Handle bounce - update user record, retry logic
      console.log(`Bounce: ${payload.rcpt} - ${payload.bounce}`);
      break;

    case 'unsubscribe':
      // Update preferences
      console.log(`Unsubscribe: ${payload.rcpt}`);
      break;

    case 'spam':
      // Add to suppression, alert team
      console.log(`Spam report: ${payload.rcpt}`);
      break;
  }

  return new Response('OK', { status: 200 });
}

Troubleshooting

IssueCauseSolution
401 UnauthorizedMissing/invalid API keyCheck API key in header or body
400 sender not verifiedUnverified sender domainVerify domain in SMTP2GO dashboard
429 Too Many RequestsRate limit exceededImplement exponential backoff
Attachment too largeOver 50MB totalCompress or use URL references
Template variables not replacedWrong syntaxUse {{ variable }} Handlebars syntax
Webhook not receiving eventsTimeout/errorsCheck endpoint returns 200 within 10s

References


Last Updated: 2026-02-06 API Version: v3.0.3

Comments

Markdown supported