126 lines
3.3 KiB
Markdown
126 lines
3.3 KiB
Markdown
# Warmup Recipes
|
|
|
|
Four recipes control **how many emails the primary receives/sends per day** over the campaign duration.
|
|
|
|
## Global constraints (all recipes)
|
|
|
|
| Parameter | Default | Min | Max |
|
|
|-----------|---------|-----|-----|
|
|
| Duration | 30 days | 14 | 45 |
|
|
| Min emails/day | 1 | 1 | — |
|
|
| Max emails/day | 40 | — | 50 |
|
|
| Reply rate | 30% | 10% | 45% |
|
|
| Volume change cap | +20% / 48h | — | Industry best practice |
|
|
|
|
## 1. Grow — Progressive (recommended)
|
|
|
|
**Use when:** New domain or cold mailbox. Safest default.
|
|
|
|
### Behavior
|
|
|
|
- Start at `minEmailsPerDay` (default 1) on day 1
|
|
- Increase daily toward `maxEmailsPerDay` over `durationDays`
|
|
- Never increase more than 20% vs prior 48h average
|
|
- After reaching max, hold flat until campaign end
|
|
- Optionally continue background warmup post-campaign at 20% of max
|
|
|
|
### Algorithm (pseudocode)
|
|
|
|
```
|
|
totalGrowthDays = durationDays * 0.7 // reach max by ~70% of campaign
|
|
dailyIncrement = (maxEmails - minEmails) / totalGrowthDays
|
|
|
|
for day in 1..durationDays:
|
|
target = minEmails + floor(dailyIncrement * min(day, totalGrowthDays))
|
|
target = min(target, maxEmails)
|
|
target = cap48hIncrease(previousTargets, target, 0.20)
|
|
schedule[day] = target
|
|
```
|
|
|
|
### Example (30 days, min=1, max=40)
|
|
|
|
| Day | Planned sends |
|
|
|-----|---------------|
|
|
| 1 | 1 |
|
|
| 7 | ~8 |
|
|
| 14 | ~18 |
|
|
| 21 | ~30 |
|
|
| 24+ | 40 |
|
|
|
|
## 2. Flat
|
|
|
|
**Use when:** Mailbox already warm; maintain reputation during live outreach.
|
|
|
|
### Behavior
|
|
|
|
- Constant `maxEmailsPerDay` every day
|
|
- No ramp
|
|
- Same reply rate and rescue rules
|
|
|
|
```
|
|
schedule[day] = maxEmailsPerDay // for all days
|
|
```
|
|
|
|
## 3. Randomized
|
|
|
|
**Use when:** Experimentation; avoid perfectly predictable patterns.
|
|
|
|
### Behavior
|
|
|
|
- Daily volume random within `[minEmailsPerDay, maxEmailsPerDay]`
|
|
- Weighted toward middle of range (normal distribution)
|
|
- 48h spike cap still applies
|
|
- Seed per campaign for reproducibility (debugging)
|
|
|
|
```
|
|
schedule[day] = randomInt(min, max, seed=campaignId+day)
|
|
schedule[day] = cap48hIncrease(...)
|
|
```
|
|
|
|
## 4. Custom
|
|
|
|
**Use when:** Expert operators want per-day control.
|
|
|
|
### Behavior
|
|
|
|
- User defines array: `[{ day: 1, sends: 2 }, { day: 2, sends: 5 }, ...]`
|
|
- Validate: each value within [min, max], length ≤ durationDays
|
|
- Missing days: hold last defined value or interpolate (configurable)
|
|
- UI: spreadsheet-style editor + import CSV
|
|
|
|
## Recipe selection API (future)
|
|
|
|
```json
|
|
{
|
|
"recipe": "grow",
|
|
"durationDays": 30,
|
|
"minEmailsPerDay": 1,
|
|
"maxEmailsPerDay": 40,
|
|
"replyRatePercent": 30
|
|
}
|
|
```
|
|
|
|
## Dispatcher integration
|
|
|
|
1. Load active campaigns
|
|
2. For each campaign, read `DailySchedule` for today
|
|
3. If `actualSends < plannedSends`, schedule next send slot with jitter
|
|
4. Pick satellite from `CampaignSatellite` (weighted random)
|
|
5. Primary is always receiver for satellite→primary sends; primary may send replies back
|
|
|
|
## Post-campaign
|
|
|
|
| Mode | Behavior |
|
|
|------|----------|
|
|
| Complete | Stop sends; mark campaign `completed` |
|
|
| Maintenance | Switch to Flat at 20% of max (recommended) |
|
|
| Pause | Operator pause; resume later |
|
|
|
|
## UI copy (recommended labels)
|
|
|
|
| Recipe | Label | Subtitle |
|
|
|--------|-------|----------|
|
|
| grow | Grow | Progressive ramp — recommended for new mailboxes |
|
|
| flat | Flat | Steady volume — for already-warm inboxes |
|
|
| randomized | Randomized | Variable daily volume — for testing |
|
|
| custom | Custom | Define your own day-by-day schedule |
|