flashrev-ai-mailer
v2.0.1
Published
FlashRev-powered CLI for AI-assisted personalized email campaigns with multi-step follow-up sequences and AI auto reply.
Maintainers
Readme
FlashRev AI Mailer
An npm-installable CLI for AI-assisted personalized email campaigns backed by FlashRev's sequence engine. v2.0 adds multi-step follow-up, AI auto reply, event tracking (open/click/reply), and unified inbox/outbox visibility.
Install
npm install -g flashrev-ai-mailer
flashrev-mailer --helpFor local testing from this folder:
npm install
npm link
flashrev-mailer --helpQuick Start
Generate a private app API key at https://info.flashlabs.ai/settings/privateApps before running the commands below.
export FLASHREV_API_KEY="your_flashrev_api_key"
flashrev-mailer init --base-url "https://open-ai-api.flashlabs.ai"
flashrev-mailer doctor --check-api
# Single-step campaign (v1 style still works)
flashrev-mailer import --campaign launch-001 --source examples/contacts.csv
flashrev-mailer draft --campaign launch-001 \
--subject "Quick idea for {{ Company }}" \
--body "Hi {{ FirstName }}, I noticed {{ Company }} is working on..."
flashrev-mailer send --campaign launch-001 --dry-run --yes --mailbox <addressId> # preview
flashrev-mailer send --campaign launch-001 --live --yes --mailbox <addressId> # commit
flashrev-mailer status --campaign launch-001
flashrev-mailer outbox --campaign launch-001 # view sent emails
flashrev-mailer inbox --campaign launch-001 # view prospect repliesCommands (17 total)
Setup
| Command | Purpose |
|---|---|
| init | Create .flashrev/config.json |
| doctor [--check-api] | Verify config + endpoints; --check-api triggers new-user schedule lazy init |
| mailboxes [--json] | List FlashRev sender mailboxes |
Campaign build
| Command | Purpose |
|---|---|
| import --campaign X --source <csv\|url> [--overwrite] | Default append (preserves sequenceId/setting/steps); --overwrite clears all metadata |
| validate --campaign X [--limit N] | Optional pre-flight deliverability check (backend auto-runs on send --live) |
| draft --campaign X [--step N] [--delay-days N] [--reply-to N] --subject T --body B | Stage email template(s). Multi-step → see Follow-up workflow |
| steps list --campaign X / steps remove --campaign X --step N | List or delete steps locally; deletions apply at next send --live |
| send --campaign X --dry-run --yes [--mailbox <id>] | Local preview, no backend writes |
| send --campaign X --live --yes [--mailbox <id>] [--send-start 09:00 --send-end 17:00 --weekdays mon-fri --timezone TZ\|<id>] [--ai-auto-reply --ai-auto-reply-prompt "..."] [--send-now] | Commit to backend sequence engine (one-time, idempotent for re-edit). All send-time params live here. |
View
| Command | Purpose |
|---|---|
| status --campaign X [--json] | Sequence overview (state / steps / delivery / engagement) |
| list [--remote] [--state ...] | List local campaigns; --remote joins backend sources="ai_mailer" filter |
| outbox [--campaign X] [--status delivered\|bounced\|opened\|replied] [--to ...] [--view <MAIL_ID>] | Sent emails with labels, open/click/reply counts |
| inbox [--campaign X] [--unread] [--sentiment positive] [--intent Interested] [--view <MAIL_ID>] [--mark-read <MAIL_ID>] | Prospect replies with AI-detected sentiment & intent |
| export --campaign X [--format json\|csv] [--out file] | Export campaign data |
Run-state control
| Command | Purpose |
|---|---|
| pause --campaign X | Pause sequence (stop further steps) |
| resume --campaign X | Resume from paused |
| reply --mail-id <MAIL_ID> --body "..." | Reply to a specific inbox email (preserves thread) |
| reschedule --campaign X [--schedule <tmplId>\|--send-start ... --send-end ... --weekdays ...] | Change schedule for committed campaign |
| ai-auto-reply enable\|disable\|show --campaign X [--prompt "..."] | Per-sequence AI auto reply config |
| delete --campaign X --yes [--keep-local\|--keep-remote] | Delete campaign (local dir + backend sequence). Irreversible — already-sent emails are not recalled |
Workflow: multi-step follow-up
flashrev-mailer import --campaign outreach --source contacts.csv
# Stage step 1 (new thread)
flashrev-mailer draft --campaign outreach \
--subject "Hi {{ FirstName }}" \
--body "I noticed {{ Company }} is..."
# Stage step 2 (3-day follow-up, replies in same thread → backend uses 'Re: ...')
flashrev-mailer draft --campaign outreach --step 2 --delay-days 3 --reply-to 1 \
--body "Just following up on my previous note..."
flashrev-mailer send --campaign outreach --live --yes --mailbox <id>
flashrev-mailer status --campaign outreachWorkflow: AI auto reply
The backend can use an LLM + your prompt to auto-reply when prospects respond.
This complements (does not replace) prospectRepliesEnabled (which stops the
sequence on reply).
# Configure when committing the campaign (all params on send)
flashrev-mailer send --campaign outreach --live --yes --mailbox <id> \
--ai-auto-reply --ai-auto-reply-prompt "You are an SDR. Be brief."
# Or configure / update after the fact
flashrev-mailer ai-auto-reply enable --campaign outreach \
--prompt "$(cat prompts/sales.md)" # max 2000 chars
flashrev-mailer ai-auto-reply show --campaign outreach
flashrev-mailer ai-auto-reply disable --campaign outreach # prompt preserved
flashrev-mailer ai-auto-reply enable --campaign outreach # reuses preserved promptWorkflow: triage replies → reply directly
flashrev-mailer inbox --campaign outreach
# MAIL_ID CONTACT_ID TIME FROM INTENT SENTIMENT SNIPPET
# 150479 2049119 ● 18:44 5/21 Jane <[email protected]> Interested positive thanks, can you...
# Reply directly from CLI (same thread)
flashrev-mailer reply --mail-id 150479 --body "Glad to hear! Here's the link..."
# Mark read without replying
flashrev-mailer inbox --mark-read 150479
# See sent email's full timeline
flashrev-mailer outbox --view 150478Important defaults
- Default send window: weekdays, 09:00-17:00, timezone from your FlashRev profile (fallback
America/New_Yorkif profile unreachable). Override per campaign withsend --send-start --send-end --weekdays --timezone <id|zoneId>. - Sending is dry-run by default; real sending requires
--live --yes. send --livecommits the entire campaign (steps + setting + contacts) to the backend in one shot; subsequentsend --livecalls go through thesequence/editFull-Replace path (the CLI fetchessequence/detailfirst to preserve fields).send --liveonly re-uploads contacts whose localsend.status !== "submitted", and the backend dedupes by(email, companyId)(importLimit=true) — adding new contacts to an existing campaign does not re-send step 1 to old contacts.- Contacts that fail email syntax validation are never submitted; backend also re-checks deliverability on receive.
- All list commands cap
--limitat 100 per page. - Every CLI-created sequence is tagged
sources="ai_mailer"server-side →list --remoteonly shows your CLI-originated sequences.
Migrating from 1.x
v1 used nodemailer directly to talk to SMTP; v2 delegates to the backend sequence engine. Behavior differences worth knowing:
| Aspect | v1 | v2 |
|---|---|---|
| send --live channel | CLI → SMTP via nodemailer | sequence/add + contact/upload-contact → backend dispatch-svc → mail-svc |
| Per-mailbox throttle | CLI enforced (10 min hard bound) | Backend enforced |
| Send time precision | scheduledAt honored exactly | Aligned to sequence working-time-window (may shift) |
| Open / click / reply tracking | Not available | Built-in (outbox shows labels + counts) |
| Reply handling | Manual | inbox + reply + optional ai-auto-reply |
| Web UI visibility | Hidden (mail bypassed FlashRev backend) | Visible (filterable by sources="ai_mailer") |
Removed in v2.1:
| v1 / v2.0 | v2.1 replacement |
|---|---|
| queue --campaign X --mailbox ... --send-start ... --ai-auto-reply ... | All params merged into send: send --campaign X --live --yes --mailbox ... --send-start ... --ai-auto-reply ... |
| queue --send-now | send --live --send-now --yes |
| queue --window 09:00-17:00 | send --send-start 09:00 --send-end 17:00 ... |
| queue --min-interval | controlled by backend; no CLI override |
| --require-validation | backend auto-validates on send --live |
Default behavior changes:
| Before | After |
|---|---|
| import defaults to overwrite | import defaults to append (preserves sequenceId/setting/steps); pass --overwrite to force replace |
| Schedule timezone hardcoded Asia/Shanghai (id=106) | Reads from your FlashRev profile, fallback America/New_York (id=22) |
Output format changes: status and export extended with new columns
(opened/clicked/replied). If you parse output, switch to --json for a stable
schema.
campaign.json schema: v2 auto-extends sequenceId / steps / setting /
timeTemplateId / committedAt / localDirty / sources. v1 files load fine — no
manual migration needed.
Commands the agent runs vs. commands requiring user confirmation
Following the embedded skills/flashrev-mailer skill, the agent may freely
run read-only commands (doctor / mailboxes / validate / status / list /
outbox / inbox / ai-auto-reply show / export).
The agent must obtain explicit user confirmation before:
send --live(sends emails)pause / resume(changes production state)ai-auto-reply enable(the prompt becomes how the LLM replies on your behalf — show the user the prompt verbatim)reply(sends a reply to a specific email)reschedule(changes when sequence delivers)send --live --send-now(bypasses the working-time window)inbox --mark-read(modifies state, but low risk)steps remove(changes campaign structure)delete --yes(irreversible — list contents in chat first; already-sent emails are not recalled)
