πŸ“–

Choco Mailer Documentation

Complete guide to using the email marketing platform

Welcome to Choco Mailer

A professional, self-hosted email marketing platform with smart account rotation, real-time tracking, multi-provider support, and campaign management built for high-volume email delivery.

πŸ“§

Bulk Sending

πŸ“Š

Tracking

πŸ”„

Rotation

✨

AI Spinner

Key Features at a Glance

πŸ“¨

Single & Bulk Email

Send individual emails or run large campaigns with multi-threaded delivery (up to 1000 threads).

πŸ”„

Smart Account Rotation

Round-robin, random, or least-used rotation across unlimited accounts with daily limits.

πŸ‘οΈ

Email Tracking

Track opens, clicks, and IPs with custom tracking domains and detailed analytics reports.

πŸ–₯️

Multi-Provider Support

Microsoft Graph API, SMTP (Gmail, Outlook, Yahoo, Zoho, SendGrid, Mailgun, Amazon SES), and Firebase / GCP.

✨

AI Content Spinner

Auto-generate subject and body variations using OpenAI, Google Gemini, or Claude.

πŸ›‘οΈ

Safety & Protection

Auto account suspension, failure tracking, brute force protection, and error categorization.

πŸš€ Quick Start Guide

Get up and running in 5 steps:

1

Log In

Access the dashboard using your admin or client credentials. Admin users have full access; client users have limited access.

2

Import Accounts

Go to the Import tab and add accounts via Microsoft Graph API or SMTP. You need at least one active sending account.

3

Configure Settings

Visit Settings to configure rotation mode, daily limits, delay, thread count, and optionally enable tracking and AI spinner.

4

Compose & Send

Use Single Email for one-off emails, or Bulk Send for campaigns. Write content using the rich text editor or raw HTML.

5

Monitor & Track

View campaign progress in Campaigns, check delivery history in History, and analyze open/click rates in tracking reports.

πŸ”’ Login & User Roles

Choco Mailer supports two user roles with different access levels:

FeatureAdminClient
Single Emailβœ“βœ“
Bulk Sendβœ“βœ“
Campaignsβœ“βœ“
Historyβœ“βœ“
Email Listsβœ“βœ“
Unsubscribesβœ“βœ“
SMTP Accountsβœ“βœ—
Disabled Accountsβœ“βœ—
Settingsβœ“βœ—
Logsβœ“βœ—
Brute Force Protection: After 5 failed login attempts within 5 minutes, the IP is locked out for 15 minutes.

✏️ Single Email

Send individual emails to a single recipient with full control over content and sender.

Fields

FieldRequiredDescription
Send FromNoChoose a specific account or leave as "Auto" to use rotation. (Admin only)
RecipientYesThe email address to send to
CCNoCarbon copy recipients
BCCNoBlind carbon copy recipients
SubjectYesEmail subject line
MessageYesEmail body β€” use the rich text Editor, raw HTML, or Preview mode
AttachmentsNoDrag & drop or browse files. Max 25 MB total, up to 10 files per email.
Editor Modes: Switch between Editor (rich text), HTML (raw code), and Preview using the toggle buttons above the message area.
Tip: Save your email as a template using "Save as Template", and load saved templates using the "Templates" button next to the subject field.

πŸ“¨ Bulk Send

Run large email campaigns with multi-threaded delivery, real-time progress tracking, and campaign controls.

How to Send a Campaign

  1. Enter a Campaign Name
  2. Add Recipients β€” paste emails one per line, or load from an Email List
  3. Write your Subject and Message
  4. Optionally check "Validate accounts before sending"
  5. Select a Tracking Domain if you want branded tracking links
  6. Click Send Campaign

Campaign Controls

⏸️

Pause

Temporarily halt sending

▢️

Resume

Continue from where you paused

⏹️

Stop

Permanently stop the campaign

Tip: Use "Remove Duplicates" to clean your recipient list before sending. The system also automatically skips unsubscribed emails.

πŸ“ Campaigns

View, manage, and analyze all your email campaigns from a single dashboard.

Campaign Statuses

RunningPausedCompletedStoppedDraft

Campaign Details

  • Total, sent, failed counts and success rate
  • Per-recipient delivery status with timestamps
  • Email content preview (subject and body)
  • Tracking report (opens, clicks, IPs)
  • Option to resend failed emails

Filtering & Sorting

  • Search by campaign name or UUID
  • Filter by status, sort by newest/oldest/name/most recipients
  • Export/import campaigns as JSON
  • Paginated results for large campaign lists

πŸ• Send History

Complete log of every email sent through the platform with powerful filtering.

FilterOptions
Time RangeLast 1hr, 6hr, 12hr, Today, Yesterday, 7 days, 30 days, Custom range
CampaignFilter by specific campaign
StatusSuccess, Failed, Retried
TypeSingle, Bulk, Retry, Test
Error TypeFilter by specific error categories
Email Details: Click the eye icon on any row to view full email details including recipient, sender, subject, body, and error message.

🏒 Graph App Permission

Import Microsoft 365 accounts using application permissions. One Azure AD app can send as all users in a tenant β€” no refresh tokens needed.

Required Fields

FieldRequiredDescription
App NameNoA friendly label for this Azure AD app
Tenant IDYesYour Azure AD tenant identifier (GUID)
Client IDYesThe application (client) ID from Azure AD
Client SecretYesA client secret value created in Azure AD
User EmailsYesEmail addresses to send as (one per line)
Azure AD Setup: Your app needs the Mail.Send application permission with admin consent.
App permission accounts don't require individual refresh tokens β€” a single app registration covers all users in the tenant.

πŸ”‘ Graph Delegated

Import Microsoft accounts using delegated permissions with refresh tokens. Each account authenticates individually via OAuth.

JSON Import Format

{
  "apps": [{
    "app_name": "My Azure App",
    "client_id": "xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
    "client_secret": "your-client-secret",
    "accounts": [{ "email": "user@domain.com", "refresh_token": "0.AAAA..." }]
  }]
}

Account Management

  • Validate All: Check that all refresh tokens are still valid
  • Filter & Search: Filter by status, sort by sent count, search by email
  • Bulk Actions: Activate, deactivate, or delete multiple accounts
  • Pagination: 10 to 5000 accounts per page
Required Permissions: Mail.Send, Mail.ReadWrite, offline_access, User.Read

πŸ–₯️ SMTP Accounts

Add SMTP accounts for direct server-based email sending.

Supported Presets

Gmail
Outlook
Yahoo
Zoho
SendGrid
Mailgun
Amazon SES
Custom
Provider Selection: Go to Settings β†’ Email Provider to choose SMTP only, Graph API only, Firebase / GCP only, both, or all providers.

🚫 Disabled Accounts

Accounts automatically suspended due to errors, categorized by ban type.

🚫 Permanent Ban

Cannot be re-enabled. Only delete is available.

  • Invalid credentials or token errors
  • Account suspended by Microsoft
  • 2 consecutive unknown failures

⏰ Soft Ban (Daily Limit)

Can be restored manually or resets the next day.

  • Daily sending limit exceeded
  • Rate limiting / quota errors
  • Temporary throttling

πŸ”„ Account Rotation

Automatically distribute email sending across multiple accounts to stay within limits and improve deliverability.

ModeBehavior
Round RobinCycles through accounts in order, one after another
RandomRandomly selects an account for each email
Least UsedPicks the account with the fewest sends today
Real-time: Rotation mode and daily limit changes apply immediately to running campaigns β€” no restart needed.
Recommended: 100 emails/day per account for safe sending.

πŸ”₯ Firebase Billing Accounts

Manage Google Cloud billing accounts used for Firebase project creation, connected via OAuth2 for automated project management.

Required Fields

FieldRequiredDescription
Display NameYesA friendly label to identify this billing account
EmailYesThe Google account email address
PasswordNoThe account password
TOTP SecretNoTwo-factor authentication secret (base32). Shows a live 6-digit code with 30s countdown.

πŸ”₯ Firebase Delivery Management

Manage tenants, custom domains, and user access across all provisioned Firebase projects. Access via the Delivery Management inner tab inside Firebase / GCP.

Bulk Actions

ActionDescription
Create TenantsCreate Firebase Auth tenants on selected projects with real-time progress overlay.
Check TenantsVerify status and health of existing tenants. If none selected, all projects are checked.
Delete TenantsRemove all tenants from the selected projects.
Setup DomainConfigure a custom domain for the selected projects.
User AccessManage which users can access the selected projects.
Warning: Deleting tenants is irreversible. Make sure no active campaigns depend on them.
Use Check Tenants periodically before running campaigns. If no projects are selected, all projects are checked automatically.

πŸ“„ Templates

Save and reuse email templates with dynamic variables for personalized campaigns.

  • Save: Click "Save as Template" from Single Email or Bulk Send
  • Load: Click "Templates" to open the Template Manager
  • Edit: Modify name, subject, and body from the Template Manager
  • Preview: View rendered template before loading
  • Delete: Remove templates you no longer need

πŸ“§ Email Lists

Import and manage recipient email lists for use in bulk campaigns.

Supported Formats

.txt.csv.xlsx
  • Import from file upload or paste emails directly
  • Automatic email validation and deduplication
  • Load directly into Bulk Send recipients
  • Rename, delete, filter by date range, and export lists

🚷 Unsubscribe Management

Manage email unsubscriptions with automatic link generation and recipient filtering.

How It Works

  1. Add {{unsubscribe_url}} to your email template footer
  2. Each recipient gets a unique, token-based unsubscribe link
  3. When clicked, recipients see an unsubscribe page to select a reason
  4. Unsubscribed emails are automatically skipped in future campaigns
  • View all unsubscribers with reason and campaign info
  • Manually add or remove emails from the unsubscribe list
  • Bulk import / export unsubscribers
  • Search, filter, and view stats

πŸ“Ž Attachments

Attach files to both single and bulk emails via Graph API or SMTP.

LimitValue
Max total size25 MB (combined across all files)
Max file count10 files per email
Bulk campaigns: Every recipient receives the same set of attached files.
Large attachments increase send time and may trigger spam filters.

πŸ“­ List-Unsubscribe Headers

Choco Mailer automatically adds RFC 8058 compliant List-Unsubscribe headers to improve deliverability and inbox placement.

When your template contains {{unsubscribe_url}}, two headers are automatically added:

List-Unsubscribe: <https://your-domain.com/api/unsubscribe/TOKEN>
List-Unsubscribe-Post: List-Unsubscribe=One-Click
  • Gmail, Outlook, and Yahoo show a visible "Unsubscribe" button in the email header
  • Improves sender reputation and reduces spam complaints
  • One-Click unsubscribe (RFC 8058) is the modern standard
Always include {{unsubscribe_url}} in your templates β€” it enables both the in-body link and the header-based one-click unsubscribe.

πŸ‘οΈ Email Tracking

Track email opens, link clicks, and recipient engagement with pixel-based tracking and link rewriting.

How Tracking Works

πŸ‘οΈ

Open Tracking

A 1Γ—1 transparent pixel is injected into HTML emails. When the recipient opens the email and loads images, the pixel fires and records the open event with timestamp, IP, and user agent.

πŸ–±οΈ

Click Tracking

All links in the email are rewritten to pass through the tracking server. When clicked, the click is recorded and the user is redirected to the original URL.

Tracking Metrics

MetricDescription
Total OpensTotal number of times emails were opened (includes repeat opens)
Unique OpensNumber of unique recipients who opened the email
Open RateUnique opens Γ· total sent Γ— 100%
Total ClicksTotal link clicks across all recipients
Click RateUnique clickers Γ· total sent Γ— 100%
Click-to-Open RateUnique clickers Γ· unique openers Γ— 100%
UnsubscribesNumber of recipients who unsubscribed from this campaign
Top Clicked LinksRanking of most-clicked URLs in the email
Open tracking requires the recipient's email client to load images. Some clients block images by default, so actual open rates may be higher than reported.

🌐 Tracking Domains

Use custom domains for branded tracking links instead of your server's IP or default domain.

Setup Steps

  1. Go to Settings β†’ Custom Tracking Domain
  2. Enter your domain (e.g., track.yourdomain.com)
  3. Click "Add" β€” the system generates a TXT DNS record for verification
  4. Add the TXT record to your domain's DNS settings
  5. Click "Verify" β€” the system checks the DNS record
  6. Once verified, click "Activate" to start using the domain
Auto SSL: When a domain is activated, the system automatically configures Caddy reverse proxy with SSL certificates for HTTPS tracking links.
You can have multiple tracking domains and select which one to use per campaign from the Bulk Send tab.

πŸ“Š Reports & Export

Generate and download detailed campaign reports in multiple formats.

πŸ“„ PDF Report

Professional PDF with campaign summary, tracking stats, and detailed recipient data.

πŸ“Š Excel Report

Spreadsheet with all tracking data, opens, clicks, and recipient details for analysis.

How to export: Open a campaign β†’ Click "View Tracking Report" β†’ Click "Export Report" β†’ Choose PDF or Excel.

βš™οΈ Settings

Configure all aspects of the email sending engine. Settings marked Real-time apply immediately to running campaigns.

SettingDefaultAppliesDescription
Email ProviderSMTPReal-timeSMTP Only, Graph API Only, Firebase / GCP Only, Both (Graph + SMTP), or All Providers
Rotation EnabledOnReal-timeToggle account rotation
Rotation ModeRound RobinReal-timeRound Robin, Random, Least Used
Daily Limit100Real-timeMax emails per account per day (1–10,000)
Delay25s fixedReal-timeFixed or random range (1–300 seconds)
Thread Count5New campaignsParallel sending threads (1–1,000)
Max Retries2Real-timeRetry attempts before banning (1–5)
TrackingOffNew campaignsEnable open/click tracking
Firebase Sender NameEmptyReal-timeCustom "From" display name for Firebase / GCP accounts. Leave empty to use the default tenant display name.
Real-time settings take effect immediately on running campaigns without needing to restart them.

✨ AI Content Spinner

Automatically generate unique subject line and body variations for each email to improve deliverability and avoid spam filters.

Supported AI Providers

OpenAI

GPT-4o-mini

Google Gemini

Gemini API

Anthropic Claude

Claude API

How It Works

  • Subject Variations: AI generates 1–20 unique subject line variations from your original
  • Body Variations: Local synonym-based spinning creates 1–10 body versions
  • Each email in the campaign gets a randomly selected variation
  • If AI fails, the system falls back to the local spinner

Setup

  1. Go to Settings β†’ AI Content Spinner
  2. Enable the AI Spinner toggle
  3. Select your preferred AI provider and enter the API key
  4. Set the number of subject and body variations, then save
Only the key for the selected provider is used. Keys are stored encrypted on the server.

βœ‰οΈ Test Mails

Send periodic test emails during campaigns to monitor delivery and content quality.

OptionDescription
Test RecipientsUp to 25 email addresses (one per line). A random one receives each test.
Content TypeStats: Campaign progress report | Copy: Exact email as recipients see it
Trigger: Time-basedSend a test every X minutes/seconds
Trigger: Interval-basedSend a test after every X emails sent
Test emails are sent when a campaign starts/resumes and stop when paused/stopped/completed. View test logs in History by filtering for type "Test".

πŸ“‹ Application Logs

Real-time application log viewer with filtering, search, and auto-refresh. Admin only.

  • Time Range: Quick filters for 30min, 1hr, 2hr, 6hr
  • Log Level: Filter by DEBUG, INFO, WARNING, ERROR, CRITICAL
  • Module: Filter by application module
  • Search: Full-text search across log entries
  • Auto-refresh: Toggle real-time log streaming
  • Download: Export logs as a file

Log Retention

  • Hot log: Current log file (up to 1MB)
  • Daily rotation: Logs rotate daily with 7-day retention

{ } Template Variables

Use dynamic variables in your email templates for personalization. Variables are replaced with actual values when the email is sent.

VariableDescriptionExample Output
{{email}}Recipient's email addressuser@example.com
{{date}}Current date2026-03-05
{{time}}Current time14:30:00
{{unsubscribe_url}}Unique unsubscribe link for the recipienthttps://track.domain.com/api/unsubscribe/...

πŸ”§ Troubleshooting

Accounts getting permanently banned

This usually means the account credentials are invalid or the provider has blocked the account. Re-check the SMTP credentials and try re-importing. Check the Disabled Accounts tab for the specific error message.

Accounts getting soft banned quickly

Your daily limit per account may be too high. Microsoft typically allows ~100 emails/day for consumer accounts. Lower the daily limit in Settings and add more accounts.

Tracking not working

  • Ensure tracking is enabled in Settings
  • Verify your tracking domain is set up and activated
  • Ensure the tracking domain DNS is pointing to your server

Campaign stuck or not progressing

  • Check if all accounts are disabled (go to Disabled Accounts tab)
  • Verify the campaign status is "running" (not paused or stopped)
  • Check the Logs tab for error messages

SMTP connection errors

Verify the SMTP host, port, and encryption settings. For Gmail, you need an App Password (not your regular password). For other providers, check if SMTP access is enabled.

Slow sending speed

Increase the thread count in Settings. Reduce the delay between sends. Add more active accounts. Formula: accounts Γ— threads Γ· delay = emails/second

Choco Mailer Documentation

Professional Email Marketing Platform