Skip to content

Repository files navigation

📧 MagicMail - Email Business Suite for Strapi v5

Professional-grade multi-account email management with smart routing, OAuth 2.0 support, and complete security compliance — 100% free and open source

NPM VersionLicenseStrapi Version

💚 Fully free & open source (MIT). Every feature is included for everyone — no license key, no activation, no paid tiers, and no usage limits.


🌟 Why MagicMail?

Stop fighting with .env files and email configuration! MagicMail brings professional email management to Strapi v5 with:

  • 100% Free & Open Source - Every feature included, no license key, tiers, or limits (MIT)
  • 6 Email Providers - Gmail, Microsoft 365, Yahoo, SMTP, SendGrid, Mailgun
  • WhatsApp Messaging - Send messages via WhatsApp (FREE!)
  • OAuth 2.0 Authentication - No passwords needed for Gmail, Microsoft, Yahoo
  • Smart Routing Rules - Route emails by type, recipient, subject, or custom conditions
  • WhatsApp Fallback - Auto-send via WhatsApp if email fails
  • Automatic Failover - Never lose an email when rate limits hit
  • Beautiful Admin UI - Manage everything from Strapi Admin Panel
  • Zero Configuration - No .env files, everything in the database
  • Email Designer Compatible - Works seamlessly with strapi-plugin-email-designer-5
  • GDPR/CAN-SPAM Compliant - Built-in List-Unsubscribe headers
  • Professional Security - TLS 1.2+, DKIM, SPF, DMARC validation

📸 Screenshots

Email Accounts Dashboard

Email Accounts DashboardManage unlimited email accounts with live stats and real-time monitoring

Add Email Account - Step 1

Add Account Step 1Choose from 6 different email providers with OAuth 2.0 support

Add Email Account - Step 2

Add Account Step 2Configure SMTP settings or connect with OAuth

Add Email Account - Step 3

Add Account Step 3Complete setup with rate limits and test connection

Email Templates

Email TemplatesCreate and manage email templates with the visual designer

Email Designer

Email DesignerDrag-and-drop email editor with real-time preview

Template Version History

Version HistoryTrack changes and restore previous template versions

Template Send Test

Send TestTest your templates before sending to production

Routing Rules & Templates

Routing RulesDefine intelligent routing rules based on email type, recipient, subject

Email Analytics

Email AnalyticsTrack email performance with detailed analytics and statistics

Code Integration

Code SnippetSimple API integration with your Strapi application


WhatsApp Messaging (NEW!)

MagicMail now includes FREE WhatsApp messaging - send messages directly from your Strapi application!

Why WhatsApp?

FeatureEmailWhatsApp
Open Rate~20%~98%
Delivery SpeedMinutesInstant
Spam Folder RiskHighNone
User PreferenceDecliningGrowing
CostVariesFREE

Quick Setup (4 Steps)

  1. Navigate to Admin Panel -> MagicMail -> WhatsApp
  2. Connect - Scan QR code with WhatsApp mobile app
  3. Verify - Check connection status shows "Connected"
  4. Send - Start sending messages programmatically!

Sending WhatsApp Messages

Method 1: Direct WhatsApp Send

// Send WhatsApp message directlyawaitstrapi.plugin('magic-mail').service('whatsapp').sendMessage('+491234567890',// Phone number with country code'Hello! This is a test message from MagicMail.');

Method 2: Unified Messaging API

// Send via unified API - auto-detects channelawaitstrapi.plugin('magic-mail').service('email-router').sendMessage({channel: 'whatsapp',// or 'email' or 'auto'phoneNumber: '+491234567890',message: 'Your order #12345 has been shipped!'});// Auto-detect: sends WhatsApp if phoneNumber provided, email if to providedawaitstrapi.plugin('magic-mail').service('email-router').sendMessage({channel: 'auto',phoneNumber: '+491234567890',// Has phone -> WhatsAppmessage: 'Shipping notification'});awaitstrapi.plugin('magic-mail').service('email-router').sendMessage({channel: 'auto',to: 'user@example.com',// Has email -> Emailsubject: 'Shipping Notification',message: 'Your order has been shipped!'});

Method 3: REST API

// POST /api/magic-mail/send-whatsappawaitfetch('/api/magic-mail/send-whatsapp',{method: 'POST',headers: {'Content-Type': 'application/json','Authorization': 'Bearer YOUR_STRAPI_API_TOKEN'},body: JSON.stringify({phoneNumber: '+491234567890',message: 'Hello from MagicMail!'})});// POST /api/magic-mail/send-message (unified)awaitfetch('/api/magic-mail/send-message',{method: 'POST',headers: {'Content-Type': 'application/json','Authorization': 'Bearer YOUR_STRAPI_API_TOKEN'},body: JSON.stringify({channel: 'whatsapp',phoneNumber: '+491234567890',message: 'Order confirmed!'})});

WhatsApp Use Cases

1. Email Fallback If email delivery fails, automatically send via WhatsApp:

// In Routing Rules, enable "WhatsApp Fallback"// Set "WhatsApp Phone Field" to 'phoneNumber'awaitstrapi.plugin('magic-mail').service('email-router').send({to: 'user@example.com',phoneNumber: '+491234567890',// Fallback phonesubject: 'Important Update',html: '<h1>Update</h1>',type: 'transactional'});// If email fails -> auto-sends via WhatsApp!

2. Admin Notifications Get instant WhatsApp alerts for critical events:

// Example: Notify admin when email quota exceededconstadminPhone='+4917612345678';awaitstrapi.plugin('magic-mail').service('whatsapp').sendMessage(adminPhone,'[ALERT] Email quota exceeded for SendGrid account!');

3. Urgent Transactional Messages Send time-sensitive messages instantly:

// OTP/Verification codesawaitstrapi.plugin('magic-mail').service('whatsapp').sendMessage(userPhone,`Your verification code: 123456\n\nValid for 5 minutes.`);// Order updatesawaitstrapi.plugin('magic-mail').service('whatsapp').sendMessage(customerPhone,`Order #${orderId} is out for delivery!\nTrack: ${trackingUrl}`);

WhatsApp Status API

// Check connection statusconststatus=awaitstrapi.plugin('magic-mail').service('whatsapp').getStatus();// { isConnected: true, phoneNumber: '+49...', name: 'Business Account' }// Check if phone number is on WhatsAppconstexists=awaitstrapi.plugin('magic-mail').service('whatsapp').checkNumber('+491234567890');// { exists: true, jid: '491234567890@s.whatsapp.net' }

Integration with Magic-Link Plugin

When both MagicMail and Magic-Link are installed:

  • Magic-Link automatically uses MagicMail's WhatsApp service
  • Only ONE WhatsApp connection needed (managed here in MagicMail)
  • Send magic links via WhatsApp from Magic-Link settings
  • Unified WhatsApp management for all plugins

Quick Start

Installation

Requires Node.js 20.19 or newer and Strapi 5.50 or newer.

npm install strapi-plugin-magic-mail
# or
yarn add strapi-plugin-magic-mail

Enable Plugin

Create or update config/plugins.ts:

exportdefault()=>({'magic-mail': {enabled: true,},});

Build & Start

npm run build
npm run develop

Add Your First Email Account

  1. Navigate to Admin Panel → MagicMail → Email Accounts
  2. Click "Add Account"
  3. Choose your provider (Gmail OAuth, SMTP, etc.)
  4. Fill in credentials
  5. Click "Test" to verify
  6. Done! 🎉

📧 Supported Email Providers

ProviderTypeAuthenticationFeatures
GmailOAuth 2.0Google OAuthGmail API, Attachments, Auto DKIM
Microsoft 365OAuth 2.0Azure ADGraph API, Attachments, Tenant Support
Yahoo MailOAuth 2.0Yahoo OAuthSMTP OAuth2, Attachments
SMTPCredentialsUsername/PasswordUniversal, DKIM Optional, Custom Servers
SendGridAPI KeySendGrid APITransactional, Marketing, Templates
MailgunAPI KeyMailgun APIBulk Sending, Analytics

💡 How to Send Emails

Method 1: Strapi Native Email Service (Recommended!)

MagicMail automatically intercepts Strapi's email service - no code changes needed!

// This works in ANY Strapi plugin or controller:awaitstrapi.plugin('email').service('email').send({to: 'user@example.com',subject: 'Welcome to Our Platform!',text: 'Plain text version',html: '<h1>Welcome!</h1><p>Thanks for signing up!</p>',});// ✅ MagicMail automatically:// - Selects best account (via routing rules or priority)// - Checks rate limits// - Handles failover if needed// - Logs the email// - Updates statistics

Benefits:

  • Zero code changes - Existing plugins work automatically
  • Email Designer compatible - Works with strapi-plugin-email-designer-5
  • Fallback safe - Falls back to original email service if MagicMail fails
  • Drop-in replacement - Just enable and go!

Method 2: Direct MagicMail API

For explicit control over account selection:

// Force a specific accountawaitstrapi.plugin('magic-mail').service('email-router').send({to: 'customer@example.com',subject: 'Order Confirmation',html: '<h1>Your Order #12345</h1>',accountName: 'SendGrid Marketing',// Force this accounttype: 'transactional',priority: 'high',});

Sending with Attachments

awaitstrapi.plugin('email').service('email').send({to: 'customer@example.com',subject: 'Invoice #12345',html: '<h1>Invoice Attached</h1>',attachments: [{filename: 'invoice.pdf',path: './uploads/invoice-12345.pdf',},{filename: 'receipt.pdf',content: Buffer.from(pdfData),contentType: 'application/pdf',},],});

Supported attachment formats:

  • ✅ PDF, Word, Excel, PowerPoint
  • ✅ Images (PNG, JPG, GIF, WebP)
  • ✅ Text files (TXT, CSV, JSON)
  • ✅ Archives (ZIP, RAR)
  • ✅ Any file type!

Advanced: Priority & Marketing Emails

// High priority emailawaitstrapi.plugin('magic-mail').service('email-router').send({to: 'vip@example.com',subject: 'Urgent: Action Required',html: '<h1>Important Update</h1>',priority: 'high',// Adds X-Priority and Importance headers});// Marketing email with unsubscribe (GDPR/CAN-SPAM compliant)awaitstrapi.plugin('magic-mail').service('email-router').send({to: 'subscriber@example.com',subject: 'Weekly Newsletter',html: '<h1>This Week'sUpdates</h1>',type: 'marketing',unsubscribeUrl: 'https://yoursite.com/unsubscribe?id=123',// Automatically adds List-Unsubscribe header!});

🎨 Email Designer Suite (NEW!)

Design beautiful emails visually with the integrated email designer!

✨ Features

Every Email Designer feature is included for free:

FeatureIncluded
Visual Designer
Unlimited Templates
Drag & Drop + Mustache
Import / Export
Template Versioning
Email Analytics

📧 Creating Email Templates

1. Navigate to Email Templates Tab

Go to MagicMail → Email Templates in the admin panel.

2. Create New Template

Click "Create Template" and use the visual designer to build your email.

3. Add Variables with Mustache

Use Mustache syntax for dynamic content:

<h1>Welcome {{user.firstName}}!</h1><p>Thanks for joining {{company.name}}</p>

4. Save & Use

Each template gets a unique Reference ID (e.g., 100) that you use when sending.

💌 Sending Templated Emails

Method 1: Using Template ID

// Send email using templateawaitstrapi.plugin('magic-mail').service('email-router').send({to: 'user@example.com',templateId: 100,// Your template reference IDtemplateData: {user: {firstName: 'John',lastName: 'Doe',email: 'john@example.com',},company: {name: 'ACME Corp',url: 'https://acme.com',},orderNumber: '12345',orderTotal: '$199.99',},});// ✅ MagicMail will:// - Load template #100// - Render it with your data (Mustache)// - Route via smart routing// - Send via best account

Method 2: Via Strapi Email Service

// Also works with standard Strapi email service!awaitstrapi.plugin('email').service('email').send({to: 'user@example.com',templateId: 100,templateData: {user: {firstName: 'Jane'},resetUrl: 'https://yoursite.com/reset?token=xyz',},});

🎯 Template Categories

Templates can be categorized for automatic routing:

  • transactional - Order confirmations, receipts
  • marketing - Newsletters, promotions
  • notification - System alerts, updates
  • custom - Anything else

Automatic Routing by Category:

// Create routing rule: All marketing templates → SendGrid// Then just send:awaitstrapi.plugin('magic-mail').service('email-router').send({to: 'subscriber@example.com',templateId: 200,// Marketing category templatetemplateData: {offer: '50% OFF'},});// ✅ Automatically routes via SendGrid (based on category)

🔄 Template Versioning

Every time you save a template, a new version is created automatically:

// Get all versionsconstversions=awaitstrapi.plugin('magic-mail').service('email-designer').getVersions(templateId);// Restore old versionawaitstrapi.plugin('magic-mail').service('email-designer').restoreVersion(templateId,versionId);

📦 Import/Export Templates

Export all templates:

consttemplates=awaitstrapi.plugin('magic-mail').service('email-designer').exportTemplates();// Save to filefs.writeFileSync('templates.json',JSON.stringify(templates,null,2));

Import templates:

consttemplates=JSON.parse(fs.readFileSync('templates.json'));constresults=awaitstrapi.plugin('magic-mail').service('email-designer').importTemplates(templates);console.log(`Imported ${results.filter(r=>r.success).length} templates`);

🎨 Visual Designer Features

Powered by Unlayer Email Editor:

  • ✅ Drag & Drop Interface
  • ✅ Pre-built Content Blocks
  • ✅ Image Upload & Management
  • ✅ Custom Fonts & Colors
  • ✅ Responsive Design
  • ✅ Mobile Preview
  • ✅ HTML/Text Editor
  • ✅ Merge Tags Support
  • ✅ Save/Load Designs

📊 Template Statistics

conststats=awaitstrapi.plugin('magic-mail').service('email-designer').getStats();console.log(stats);// {// total: 15,// active: 12,// inactive: 3,// byCategory: [// { category: 'transactional', count: 8 },// { category: 'marketing', count: 4 },// { category: 'notification', count: 3 }// ],// maxTemplates: -1, // unlimited (all features are free)// remaining: -1 // unlimited// }

🚀 Best Practices

1. Use Template Categories

// Set category when creating template
category: 'marketing'// Auto-routes to marketing account

2. Test Templates Before Using

// Test render before sendingconstrendered=awaitstrapi.plugin('magic-mail').service('email-designer').renderTemplate(100,{user: {firstName: 'Test'}});console.log(rendered.html);// Preview HTML

3. Version Control

// Template version history is always enabled (free for everyone).

4. Organize with Tags

// Add tags to templates
tags: ['onboarding','welcome-series','v2']

🎯 Smart Routing Rules

Create intelligent routing rules to send emails through specific accounts based on conditions.

Example Use Cases

1. Route Marketing Emails via SendGrid:

Match Type: Email Type
Match Value: marketing
Target Account: SendGrid Marketing
Priority: 10

2. Route VIP Customers via Priority SMTP:

Match Type: Recipient
Match Value: @vip-customers.com
Target Account: Priority SMTP
Fallback Account: Gmail OAuth
Priority: 9

3. Route Password Reset Emails:

Match Type: Subject
Match Value: Password Reset
Target Account: Transactional SMTP
Priority: 8

Routing Priority

Rules are evaluated from highest to lowest priority (1-10):

  • Priority 10 = Evaluated first (most specific rules)
  • Priority 1 = Evaluated last (catch-all rules)

If no rule matches, the Primary Account is used.


🔐 Provider Setup Guides

Gmail OAuth Setup

1. Google Cloud Console

  1. Go to console.cloud.google.com
  2. Create a new project or select existing
  3. Enable Gmail API
  4. Create OAuth 2.0 Client ID
  5. Add redirect URI: http://localhost:1337/magic-mail/oauth/gmail/callback
  6. Copy Client ID and Client Secret

2. In MagicMail

  1. Choose "Gmail OAuth" provider
  2. Paste Client ID and Client Secret
  3. Click "Connect with Google"
  4. Authorize in popup
  5. Done! ✅

Required Scopes:

  • https://www.googleapis.com/auth/gmail.send
  • https://www.googleapis.com/auth/userinfo.email

Microsoft 365 OAuth Setup

1. Azure Portal

  1. Go to portal.azure.com
  2. Navigate to Azure Active Directory → App registrations
  3. Click "New registration"
  4. Name: "MagicMail"
  5. Account type: "Accounts in this organizational directory only"
  6. Copy Application (client) ID AND Directory (tenant) ID

2. Add Redirect URI

http://localhost:1337/magic-mail/oauth/microsoft/callback

3. API Permissions

Add these Delegated permissions under Microsoft Graph:

  • Mail.Send - Send emails as the signed-in user
  • User.Read - Read user profile
  • offline_access - Maintain access (refresh tokens)
  • openid - Sign users in
  • email - View users' email address

4. Grant Admin Consent (Required!)

5. Create Client Secret

  1. Certificates & secretsNew client secret
  2. Copy the VALUE (not the Secret ID)
  3. Store it securely!

6. In MagicMail

  1. Choose "Microsoft OAuth" provider
  2. Paste Tenant ID, Client ID, and Client Secret
  3. Click "Connect with Microsoft"
  4. Authorize
  5. Done! ✅

Yahoo Mail OAuth Setup

1. Yahoo Developer Console

  1. Go to developer.yahoo.com/apps
  2. Click "Create an App"
  3. Fill in app details

2. Add Redirect URI

http://localhost:1337/magic-mail/oauth/yahoo/callback

3. API Permissions

  • Mail - Send and manage emails
  • OpenID Connect - User authentication

4. In MagicMail

  1. Choose "Yahoo Mail OAuth" provider
  2. Paste Client ID and Client Secret
  3. Click "Connect with Yahoo"
  4. Done! ✅

SMTP Setup (Universal)

Works with ANY SMTP server:

Host: smtp.gmail.com (or your SMTP server)
Port: 587 (STARTTLS) or 465 (SSL/TLS)
Username: your-email@domain.com
Password: your-password (or App Password)

Popular SMTP Servers:

  • Gmail:smtp.gmail.com:587 (use App Password!)
  • Outlook:smtp-mail.outlook.com:587
  • Office365:smtp.office365.com:587
  • Custom: Your own mail server

Gmail App Password:

  1. Google Account → Security → 2-Step Verification
  2. App passwords → Generate
  3. Use the 16-character password in MagicMail

Optional: DKIM Signing

For custom domains, you can add DKIM:

// In config field (advanced users):{dkim: {domainName: 'yourdomain.com',keySelector: 'default',privateKey: '-----BEGIN PRIVATE KEY-----\n...'}}

SendGrid Setup

1. Get API Key

  1. Go to app.sendgrid.com
  2. Settings → API Keys → Create API Key
  3. Scope: Mail Send (Full Access)
  4. Copy the API key

2. In MagicMail

  1. Choose "SendGrid" provider
  2. Paste API Key
  3. Done! ✅

Mailgun Setup

1. Get API Key & Domain

  1. Go to app.mailgun.com
  2. Settings → API Security → Copy Private API Key
  3. Sending → Domains → Copy your verified domain

2. In MagicMail

  1. Choose "Mailgun" provider
  2. Enter Domain (e.g., mg.yourdomain.com)
  3. Paste Private API Key
  4. Done! ✅

🛡️ Security Features

Encryption

  • AES-256-GCM encryption for all credentials
  • No plain text passwords in database
  • OAuth tokens encrypted at rest
  • Secure token refresh mechanism

Transport Security

  • TLS 1.2+ enforced (SMTP)
  • Certificate verification enabled
  • HTTPS only for API providers

Email Authentication

  • DKIM signing (optional for SMTP, automatic for OAuth)
  • SPF validation support
  • DMARC compliance - All providers pass DMARC checks
  • Proper Message-ID generation (RFC 5322)

Content Security

  • XSS prevention - No <script> tags allowed
  • Input validation - Email format, subject length
  • Spam trigger detection - Warns about suspicious patterns
  • MIME type validation

Compliance Headers

  • List-Unsubscribe (RFC 8058) - GDPR/CAN-SPAM compliant
  • Auto-Submitted (RFC 3834) - Prevents auto-responder loops
  • Precedence: bulk for marketing emails
  • X-Priority and Importance headers

📊 Features Overview

Multi-Account Management

  • Unlimited email accounts
  • Provider-specific configuration
  • Active/Inactive status
  • Primary account designation
  • Per-account priority (1-10)
  • Daily and hourly rate limits

Smart Routing Engine

  • Email Type Routing - transactional, marketing, notification
  • Recipient Matching - Route by email domain or address
  • Subject Matching - Route by subject keywords
  • Template Matching - Route by template name
  • Custom Field Matching - Flexible custom conditions
  • Priority-based evaluation - Higher priority rules match first
  • Fallback accounts - Automatic failover per rule

Rate Limiting & Failover

  • Per-account daily limits
  • Per-account hourly limits
  • Automatic counter reset (hourly/daily)
  • Smart failover to backup accounts
  • Rate limit hit detection
  • Account health monitoring

Analytics & Monitoring

  • Real-time statistics dashboard
  • Emails sent today (per account and total)
  • Total emails sent (lifetime)
  • Active/Inactive account count
  • Success/Failure tracking
  • Last used timestamps
  • Visual progress bars for rate limits

Testing Features

  • Test Direct - Test specific account directly
  • Test Strapi Service - Verify Email Designer compatibility
  • Priority Testing - Test high/normal priority headers
  • Marketing Email Testing - Test List-Unsubscribe headers
  • Detailed test results - Shows all security features applied

🔧 Configuration

Basic Setup (No .env Required!)

All configuration is done via the Admin Panel. However, for production deployments, you can set:

# Optional - Base URL for OAuth callbacksURL=https://yourdomain.com# Optional - Encryption key (auto-generated if not provided)ENCRYPTION_KEY=your-32-character-secret-key

Account Configuration

Each account can have:

Basic Settings:

  • Name (unique identifier)
  • Description
  • Provider type
  • From Email
  • From Name
  • Reply-To Email

Security:

  • OAuth credentials (encrypted)
  • SMTP credentials (encrypted)
  • API keys (encrypted)
  • DKIM configuration (optional)

Rate Limiting:

  • Daily email limit (0 = unlimited)
  • Hourly email limit (0 = unlimited)
  • Priority (1-10, higher = preferred)

Status:

  • Active/Inactive
  • Primary account designation

🎨 API Reference

Send Email (Standard Method)

awaitstrapi.plugin('email').service('email').send({to: 'recipient@example.com',from: 'sender@example.com',// Optional - uses account defaultsubject: 'Email Subject',text: 'Plain text content',html: '<h1>HTML content</h1>',// Optional advanced options:replyTo: 'reply@example.com',type: 'transactional',// or 'marketing', 'notification'priority: 'normal',// or 'high'accountName: 'Specific Account',// Force specific accountunsubscribeUrl: 'https://site.com/unsubscribe',// For marketing emailsattachments: [{filename: 'document.pdf',path: './path/to/file.pdf',contentType: 'application/pdf',},],});

Send Email (Direct MagicMail API)

awaitstrapi.plugin('magic-mail').service('email-router').send({to: 'user@example.com',subject: 'Test Email',html: '<p>Content</p>',accountName: 'Gmail OAuth',// Optional - force specific accounttype: 'transactional',priority: 'normal',});

Get All Accounts

constaccounts=awaitstrapi.plugin('magic-mail').service('account-manager').getAllAccounts();

Test Account

constresult=awaitstrapi.plugin('magic-mail').service('account-manager').testAccount(accountId,'test@example.com',{priority: 'high',type: 'marketing',unsubscribeUrl: 'https://example.com/unsubscribe',});

🧪 Testing Your Setup

Test via Admin UI

  1. Go to Email Accounts
  2. Click Test button on any account
  3. Enter recipient email
  4. Select test options:
    • Priority: Normal / High
    • Email Type: Transactional / Marketing / Notification
    • Unsubscribe URL: (for marketing emails)
  5. Choose test method:
    • Test Direct - Direct send via account
    • Test Strapi Service - Via Strapi email service (tests Email Designer compatibility)

Test via Code

// Test email with all security featuresawaitstrapi.plugin('magic-mail').service('account-manager').testAccount(accountId,'your-email@example.com',{priority: 'high',type: 'marketing',unsubscribeUrl: 'https://yoursite.com/unsubscribe',});

Verify Headers

To verify security headers are applied:

In Gmail:

  1. Open email → Click ⋮ (three dots)
  2. "Show original"
  3. Look for:
    X-Mailer: MagicMail/1.0
    X-Priority: 1 (Highest)
    Importance: high
    List-Unsubscribe: <https://...>
    Message-ID: <...>
    DKIM-Signature: ...
    

In Outlook/Microsoft:

  1. Email → File → Properties
  2. View "Internet headers"
  3. Should show "High Importance" with red exclamation mark

🔒 Security Compliance

Email Authentication

StandardStatusDescription
DKIMDomainKeys Identified Mail - Signature validation
SPFSender Policy Framework - Sender verification
DMARCDomain-based Authentication - Policy enforcement
TLS 1.2+Transport Layer Security - Encrypted transmission
AES-256-GCMCredential encryption at rest

Regulatory Compliance

RegulationStatusImplementation
GDPRList-Unsubscribe header for marketing emails
CAN-SPAMOne-click unsubscribe mechanism (RFC 8058)
RFC 5322Proper email format and headers
RFC 3834Auto-Submitted header prevents loops
RFC 2156Priority and Importance headers

Security Validation

Every email is validated for:

  • ✅ Valid recipient email format
  • ✅ Non-empty subject line
  • ✅ Subject length (warns if > 200 chars)
  • ✅ Content presence (text or html required)
  • ✅ No <script> tags in HTML
  • ✅ No javascript: protocol in links
  • ✅ Spam trigger detection (warns only)

📈 Analytics & Monitoring

Dashboard Stats

Global Stats:

  • Emails sent today (all accounts)
  • Total emails sent (lifetime)
  • Active accounts count

Per-Account Stats:

  • Emails sent today
  • Total emails sent
  • Rate limit usage (visual progress bars)
  • Last used timestamp
  • Success/failure rate

Email Logging

Every email is logged with:

  • Recipient
  • Sender
  • Subject
  • Account used
  • Status (sent/failed)
  • Timestamp
  • Email type
  • Error message (if failed)

Access logs via:

constlogs=awaitstrapi.entityService.findMany('plugin::magic-mail.email-log',{filters: {status: 'sent'},sort: {createdAt: 'desc'},limit: 100,});

🔄 Integration with Email Designer

MagicMail is fully compatible with strapi-plugin-email-designer-5!

How It Works

  1. Install Email Designer:

    npm install strapi-plugin-email-designer-5
  2. Create email templates in Email Designer

  3. Send via template:

    // Email Designer internally uses strapi.plugin('email').service('email').send()// MagicMail automatically intercepts it!
  4. Your email is automatically:

    • ✅ Routed through MagicMail's smart routing
    • ✅ Sent via the best account (based on rules)
    • ✅ Rate limited and failover protected
    • ✅ Logged and tracked

No configuration needed - it just works! 🎉


🚨 Troubleshooting

Email Not Received

1. Check Logs

# Look for errors in Strapi console
[magic-mail] ❌ Email send failed: ...

2. Check Account Status

  • Is the account marked as "Active"?
  • Test the account using the Test button
  • Check rate limits haven't been exceeded

3. Check Spam Folder

  • First emails from new accounts may land in spam
  • Check spam/junk folders
  • Mark as "Not Spam" to train filters

4. Verify Credentials

  • SMTP: Username and password correct?
  • Gmail: Using App Password (not regular password)?
  • OAuth: Tokens may have expired - reconnect

DMARC Failures

For Custom Domains:

  1. Set up SPF record:

    v=spf1 include:_spf.google.com ~all
    
  2. Set up DKIM:

    • Generate DKIM key pair
    • Add public key to DNS
    • Add private key to MagicMail SMTP config
  3. Set up DMARC:

    v=DMARC1; p=quarantine; rua=mailto:dmarc@yourdomain.com
    

For OAuth Providers (Gmail, Microsoft, Yahoo):

  • ✅ DKIM handled automatically
  • ✅ SPF handled automatically
  • ✅ DMARC should pass automatically

Rate Limit Errors

If you hit rate limits:

  • Increase daily/hourly limits in account settings
  • Add more accounts for load balancing
  • Set up routing rules to distribute load
  • Check provider-specific limits:
    • Gmail: 500/day (free), 2000/day (workspace)
    • SendGrid: Varies by plan
    • Mailgun: Varies by plan

OAuth Connection Issues

Gmail OAuth:

  • Ensure Gmail API is enabled
  • Check redirect URI matches exactly
  • Clear browser cookies and try again

Microsoft OAuth:

  • Verify all 5 permissions are granted
  • Grant admin consent (required!)
  • Use correct Tenant ID
  • Check Client Secret hasn't expired

Yahoo OAuth:

  • Verify app is approved by Yahoo
  • Check API permissions are enabled

🏗️ Architecture

Plugin Structure

magic-mail/
├── admin/ # React Admin UI
│ └── src/
│ ├── components/
│ │ ├── AddAccountModal.jsx # Multi-step account setup
│ │ └── PluginIcon.jsx # Sidebar icon
│ └── pages/
│ ├── App.jsx # Main app with tabs
│ ├── HomePage.jsx # Email accounts page
│ └── RoutingRules.jsx # Routing rules page
├── server/ # Backend
│ └── src/
│ ├── bootstrap.js # Overrides Strapi email service
│ ├── controllers/
│ │ ├── accounts.js # CRUD for accounts
│ │ ├── oauth.js # OAuth flows
│ │ └── routing-rules.js # CRUD for routing rules
│ ├── services/
│ │ ├── email-router.js # Core routing logic
│ │ ├── account-manager.js # Account management
│ │ └── oauth.js # OAuth token exchange
│ ├── content-types/
│ │ ├── email-account/ # Account schema
│ │ ├── email-log/ # Email log schema
│ │ └── routing-rule/ # Routing rule schema
│ └── utils/
│ └── encryption.js # AES-256-GCM encryption
└── package.json

Data Flow

Email Request
↓
Strapi Email Service (intercepted!)
↓
MagicMail Email Router
↓
Routing Rules Engine
↓
Account Selection (priority/rules)
↓
Rate Limit Check
↓
Provider-Specific Sender
↓
Email Log & Stats Update
↓
Response

🎯 Use Cases

Multi-Tenant SaaS

// Each tenant gets their own email account// Route by custom field:// Routing Rule:// Match Type: Custom Field// Match Value: tenant-123// Target Account: Tenant 123 Gmailawaitstrapi.plugin('email').service('email').send({to: 'customer@example.com',subject: 'Order Confirmation',html: '<h1>Order #456</h1>',customField: 'tenant-123',// Matches routing rule});

High-Volume Email Sending

// Distribute load across multiple accounts// Account 1: Priority 10, Limit 500/day// Account 2: Priority 9, Limit 500/day// Account 3: Priority 8, Limit 500/day// → Total: 1500 emails/day with automatic load balancing!

Marketing Campaigns

// Route marketing emails via SendGrid// Routing Rule:// Match Type: Email Type// Match Value: marketing// Target Account: SendGrid Marketingawaitstrapi.plugin('email').service('email').send({to: 'subscriber@example.com',subject: 'Weekly Newsletter',html: template,type: 'marketing',unsubscribeUrl: 'https://yoursite.com/unsubscribe?id=123',});// ✅ Automatically routes via SendGrid// ✅ Adds List-Unsubscribe header// ✅ GDPR/CAN-SPAM compliant

VIP Customer Emails

// Route VIP customers via a priority account// Routing Rule:// Match Type: Recipient// Match Value: @vip-domain.com// Target Account: Priority SMTP// Fallback Account: Gmail OAuthawaitstrapi.plugin('email').service('email').send({to: 'ceo@vip-domain.com',subject: 'Exclusive Offer',html: content,priority: 'high',});// ✅ Routes via Priority SMTP// ✅ High priority headers added// ✅ Automatic fallback if the priority account is unavailable

🔌 Email Provider Comparison

FeatureGmail OAuthMicrosoft OAuthYahoo OAuthSMTPSendGridMailgun
Auth MethodOAuth 2.0OAuth 2.0OAuth 2.0PasswordAPI KeyAPI Key
Free Tier500/dayVariesLimitedVaries100/day5000/month
Attachments
HTML Emails
DKIM AutoOptional
Custom Headers
Priority Headers
SecurityExcellentExcellentGoodGoodExcellentExcellent
DeliverabilityExcellentExcellentGoodVariesExcellentExcellent
Best ForPersonal/SmallEnterprisePersonalCustomMarketingBulk/Dev

🌍 Production Deployment

Environment Variables

# Base URL (required for OAuth callbacks in production)URL=https://yourdomain.com# Database (Strapi default)DATABASE_CLIENT=postgresDATABASE_HOST=127.0.0.1DATABASE_PORT=5432DATABASE_NAME=strapiDATABASE_USERNAME=strapiDATABASE_PASSWORD=password# Required in production. Keep this stable across deploys and backups.# Generate: node -e "console.log(require('crypto').randomBytes(32).toString('hex'))"MAGIC_MAIL_ENCRYPTION_KEY=your-generated-secret-with-at-least-32-bytes# Optional dedicated OAuth-state signing secret. APP_KEYS is used otherwise.MAGIC_MAIL_OAUTH_STATE_SECRET=your-generated-secret-with-at-least-32-bytes

OAuth Callback URLs

Update redirect URIs in your OAuth apps:

Gmail:

https://yourdomain.com/magic-mail/oauth/gmail/callback

Microsoft:

https://yourdomain.com/magic-mail/oauth/microsoft/callback

Yahoo:

https://yourdomain.com/magic-mail/oauth/yahoo/callback

Recommended Provider Settings

For Production Apps:

Use CaseRecommended ProviderConfiguration
TransactionalSendGrid or MailgunHigh daily limit, dedicated IP
MarketingSendGridList management, analytics
NotificationsSMTP or Gmail OAuthMedium limits, reliable
InternalMicrosoft 365Company domain, OAuth
DevelopmentMailgun SandboxFree testing

📚 Advanced Topics

Custom Routing Logic

Create complex routing rules:

// Rule 1: VIP customers via a priority account{name: "VIP Customer Emails",matchType: "recipient",matchValue: "@vip-customers.com",accountName: "Priority SMTP",fallbackAccountName: "Gmail OAuth",priority: 10,isActive: true}// Rule 2: Password resets via fast account{name: "Password Reset Emails",matchType: "subject",matchValue: "Password Reset",accountName: "Fast Gmail",priority: 9,isActive: true}// Rule 3: Marketing via SendGrid{name: "Marketing Campaigns",matchType: "emailType",matchValue: "marketing",accountName: "SendGrid Marketing",priority: 8,isActive: true}

DKIM Configuration (Advanced)

For custom domains with SMTP:

1. Generate DKIM Keys:

openssl genrsa -out dkim_private.pem 1024
openssl rsa -in dkim_private.pem -pubout -out dkim_public.pem

2. Add to DNS:

default._domainkey.yourdomain.com TXT "v=DKIM1; k=rsa; p=MIGfMA0GCSqGSIb3DQEBAQUAA..."

3. Add to MagicMail SMTP Account:

// In account config (edit account → credentials):{host: "smtp.yourdomain.com",port: 587,user: "...",pass: "...",dkim: {domainName: "yourdomain.com",keySelector: "default",privateKey: "-----BEGIN PRIVATE KEY-----\n..."}}

Rate Limit Strategy

Best practices for high-volume sending:

// Account Setup:// Account A: Priority 10, Daily Limit: 500// Account B: Priority 9, Daily Limit: 500 // Account C: Priority 8, Daily Limit: 500// → Total capacity: 1500 emails/day// MagicMail automatically:// 1. Uses Account A until limit hit// 2. Switches to Account B// 3. Switches to Account C// 4. All transparent to your code!

🤝 Contributing

We welcome contributions!

Found a bug?Open an issue

Have a feature idea?Start a discussion

Want to contribute code?

  1. Fork the repo
  2. Create a feature branch
  3. Make your changes
  4. Submit a pull request

License

MIT License

Copyright © 2025 Schero D.

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

MagicMail is fully free and open source. Every feature is available to everyone with no license key, tier, activation, or usage limit.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


🙏 Credits

Built with:

Inspired by:

  • Professional email requirements
  • Multi-tenant application needs
  • Developer experience first

💬 Support

Need help?


⭐ Show Your Support

If MagicMail helps your project, please:

  • ⭐ Star the repo on GitHub
  • 📢 Share with your team
  • 🐦 Tweet about it

🔒 Security Advisories & Dependency Overrides

MagicMail's direct dependencies are audited on every release, but two transitive paths are governed by upstream packages we do not control. If your own npm audit flags either of them, add the matching entry to your Strapi project'spackage.json (not this plugin's — npm overrides only take effect on the root project):

{
"overrides": {
// GHSA-xq3m-2v4x-88gg — protobufjs <7.5.5 arbitrary code execution.// Reaches us via baileys → libsignal → protobufjs. We already ship// this override for local plugin development; apply it in your// Strapi project so the fix propagates to the installed tree."protobufjs": "^7.5.5"
}
}

After editing package.json, run:

rm -rf node_modules package-lock.json
npm install
npm audit

The critical protobufjs advisory disappears once the override is in place. Remaining @strapi/design-system → lodash advisories are Strapi-core issues and will clear up automatically when you upgrade @strapi/strapi to the latest patch release.

If you don't use the WhatsApp delivery feature at all, you can also install without the Baileys optional paths via npm install strapi-plugin-magic-mail --ignore-scripts — the plugin already guards every Baileys import with a try/catch and will log "WhatsApp features disabled" rather than crash.


Made for the Strapi Community

MagicMail - Because email management should be magical, not painful.

About

Enterprise-grade multi-account email management with smart routing, OAuth 2.0 support, and complete security compliance

Topics

Resources

Stars

4 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages