5.5 KiB
5.5 KiB
Email Campaigns — Feature Plan
Existing Foundation (botserver/src/marketing/)
campaigns.rs— CrmCampaign model, CRUD handlersmetrics.rs— CampaignMetrics, ChannelBreakdown, open/click/conversion rateslists.rs— recipient liststemplates.rs— content templatestriggers.rs— event-based sendingemail/tracking.rs— open/click tracking pixels
Features to Build
1. Insights Dashboard
What: Time series views of delivery + engagement metrics per campaign.
Data points per time bucket (hourly/daily):
- Sent, delivered, bounced, failed
- Opens (unique + total), clicks, replies, unsubscribes
- Delivery rate, open rate, click-to-open rate (CTOR)
Filters/pivots:
- By mailbox provider (Gmail, Outlook, Yahoo, etc. — parsed from MX/SMTP response)
- By sender identity (from address / domain)
- By campaign or list
- Message search → show exact SMTP response from provider
Implementation:
- Add
email_delivery_eventstable:(id, campaign_id, recipient_id, event_type, provider, smtp_response, ts) - API:
GET /api/campaigns/:id/insights?from=&to=&group_by=provider|identity|day - UI: HTMX + chart.js time series (local vendor)
2. Advisor Recommendations
What: Analyze sending config + results and surface actionable fixes.
Checks to run:
| Check | Signal | Recommendation |
|---|---|---|
| SPF/DKIM/DMARC | DNS lookup | "Add missing record" |
| Bounce rate > 5% | delivery_events | "Clean list — remove hard bounces" |
| Open rate < 15% | metrics | "Improve subject line / send time" |
| Spam complaints > 0.1% | FBL data | "Remove complainers immediately" |
| Sending from new IP | warmup_schedule | "Follow warmup plan" |
| List age > 6 months | list.last_sent | "Re-engagement campaign before bulk send" |
Implementation:
marketing/advisor.rs—AdvisorEngine::analyze(campaign_id) -> Vec<Recommendation>- API:
GET /api/campaigns/:id/advisor - Runs automatically after each campaign completes
3. IP Warmup (like OneSignal / Mailchimp)
What: Gradually increase daily send volume over 4–6 weeks to build sender reputation.
Warmup schedule (standard):
| Day | Max emails/day |
|---|---|
| 1–2 | 50 |
| 3–4 | 100 |
| 5–7 | 500 |
| 8–10 | 1,000 |
| 11–14 | 5,000 |
| 15–21 | 10,000 |
| 22–28 | 50,000 |
| 29+ | unlimited |
Rules:
- Only send to most engaged subscribers first (opened in last 90 days)
- Stop warmup if bounce rate > 3% or complaint rate > 0.1%
- Resume next day at same volume if paused
Implementation:
marketing/warmup.rs—WarmupSchedule,WarmupEngine::get_daily_limit(ip, day) -> u32warmup_schedulestable:(id, ip, started_at, current_day, status, paused_reason)- Scheduler checks warmup limit before each send batch
- API:
GET /api/warmup/status,POST /api/warmup/start
4. Optimized Shared Delivery
What: Auto-select best sending IP based on real-time reputation signals.
Logic:
- Track per-IP: bounce rate, complaint rate, delivery rate (last 24h)
- Score each IP:
score = delivery_rate - (bounce_rate * 10) - (complaint_rate * 100) - Route each send to highest-scored IP for that destination provider
- Rotate IPs to spread load and preserve reputation
Implementation:
marketing/ip_router.rs—IpRouter::select(destination_domain) -> IpAddrip_reputationtable:(ip, provider, bounces, complaints, delivered, window_start)- Plugs into Stalwart send path via botserver API
5. Modern Email Marketing Features
| Feature | Description |
|---|---|
| Send time optimization | ML-based per-contact best send time (based on past open history) |
| A/B testing | Split subject/content, auto-pick winner after N hours |
| Suppression list | Global unsubscribe/bounce/complaint list, auto-applied to all sends |
| Re-engagement flows | Auto-trigger "we miss you" to contacts inactive > 90 days |
| Transactional + marketing separation | Separate IPs/domains for transactional vs bulk |
| One-click unsubscribe | RFC 8058 List-Unsubscribe-Post header on all bulk sends |
| Preview & spam score | Pre-send SpamAssassin score check |
| Link tracking | Redirect all links through tracker, record clicks per contact |
| Webhook events | Push delivery events to external URLs (Stalwart webhook → botserver) |
DB Tables to Add
email_delivery_events (id, campaign_id, recipient_id, event_type, provider, smtp_code, smtp_response, ts)
warmup_schedules (id, ip, started_at, current_day, daily_limit, status, paused_reason)
ip_reputation (id, ip, provider, delivered, bounced, complained, window_start)
advisor_recommendations (id, campaign_id, check_name, severity, message, created_at, dismissed)
ab_tests (id, campaign_id, variant_a, variant_b, split_pct, winner, decided_at)
suppression_list (id, org_id, email, reason, added_at)
Files to Create
botserver/src/marketing/
├── warmup.rs — IP warmup engine + schedule
├── advisor.rs — recommendation engine
├── ip_router.rs — optimized IP selection
├── ab_test.rs — A/B test logic
├── suppression.rs — global suppression list
└── send_time.rs — send time optimization
Existing Code to Extend
marketing/metrics.rs→ add time-series queries + provider breakdownmarketing/campaigns.rs→ add warmup_enabled, ab_test_id fieldsemail/tracking.rs→ already has open/click tracking, extend with provider parsingcore/shared/schema/→ add new tables above