FlashRev AI Mailer
Use the flashrev-mailer CLI to run personalized email campaigns with FlashRev mailbox pools, recipient validation, throttled scheduling, and detailed send logs.
Security posture
This skill handles outbound email and authentication material. The following constraints are non-negotiable and apply to every workflow below:
- API key lives only in the operator's shell environment (
FLASHREV_API_KEYor the name set viaflashrev.apiKeyEnv). It is never written to.flashrev/config.json, campaign exports, send logs, or chat output. - SMTP credentials returned by FlashRev are held in process memory only — keyed by
mailboxId, used by anodemailertransporter, and released when the send pool closes. They are never persisted to disk, never echoed to logs, and never included inexportoutput. - Live sending requires explicit human approval per batch. The agent must run
--dry-run --yesfirst, show rendered drafts to the user, and only proceed with--live --yesafter the user approves drafts, sender pool, schedule, and recipient set. The agent never auto-escalates batch size. - Throttling is enforced: minimum 10 minutes between sends per mailbox (hard lower bound), working-hour window, and a per-batch
--limit.--send-future(which would bypass scheduling) is forbidden. - Recipient gating: never send to syntax-invalid, opted-out, suppressed, or validation-failed addresses.
risky/catch-all/accept-all/unknownare treated as undeliverable unless the user explicitly overrides. - Failure mode is stop-and-ask, not retry-with-different-input. If a prerequisite or confirmation is missing, halt the workflow and surface the gap to the user.
Prerequisites
These items must be set up by the human operator. The agent's role is to verify each one and guide the user to fix anything missing — never attempt to install software, generate API keys, or modify the user's shell environment unattended.
- Node.js ≥ 20 is installed and on
PATH. - CLI is installed globally by the user:
npm install -g flashrev-ai-mailer. Verify withflashrev-mailer --help. - FlashRev API key is generated by the user at https://info.flashlabs.ai/settings/privateApps and exported as a shell environment variable (
export FLASHREV_API_KEY="...", optionally appended to~/.zshrcor~/.bashrcfor persistence). To use a different variable name, setflashrev.apiKeyEnvin.flashrev/config.json— but the key value itself must always stay in the environment, never inside any config file (see Safety rules). - Base URL is initialized once per workspace. The agent may run
flashrev-mailer init --base-url "<url>"after the user confirms the URL; this writes.flashrev/config.json. To overwrite an existing config, append--force. - Outbound network access to the FlashRev API host and to the SMTP servers returned per mailbox (e.g.
smtp.gmail.com:465). Sending dials SMTP directly vianodemailer. - Workspace is writable — campaign state, queue, and send logs are persisted under the current working directory.
Run flashrev-mailer doctor (or flashrev-mailer doctor --check-api for a live probe) before any campaign step. If a check fails, stop the workflow, tell the user exactly which prerequisite is missing with the command or link to fix it, and wait — do not proceed to import / queue / send until the user reports it resolved.
Required confirmations
Each item below is a business decision the agent must explicitly align with the user before proceeding — do not assume defaults.
- Contact source is approved: CSV, TSV, public CSV URL, Google Sheets CSV/export URL, or Clay CSV export.
- The email column and personalization fields are understood (list them back to the user for confirmation).
- The campaign goal, offer, tone, sender identity, and call to action are approved.
- Sending timezone, weekday/window, and frequency are approved.
- The user has reviewed drafts and explicitly approved live sending.
Workflow
Prerequisites must be satisfied first (see above). All commands assume CAMPAIGN_ID is lowercase-kebab-case (e.g. launch-001); the CLI will slugify other forms internally, but mixing styles between commands causes lookups to fail. Pick one ID per campaign and reuse it verbatim.
- Confirm sender pool —
flashrev-mailer mailboxeslists FlashRev-provisioned sender mailboxes. Confirm at least one usable mailbox exists and align with the user on which sender identity will run this campaign. If the list is empty, stop and ask the user to provision mailboxes in FlashRev before continuing. - Import contacts:
flashrev-mailer import --campaign CAMPAIGN_ID --source contacts.csvReport the "Email syntax invalid" count back to the user. If non-zero, ask whether to clean the source CSV before continuing. - Validate recipients:
flashrev-mailer validate --campaign CAMPAIGN_ID --limit 200For lists over 200 contacts, run validate in batches and report progress between batches; this also avoids exhausting the FlashRev verification quota in a single call. - Draft personalized content. For template drafting:
flashrev-mailer draft --campaign CAMPAIGN_ID --subject-template "..." --body-template "..." - Queue only eligible contacts:
flashrev-mailer queue --campaign CAMPAIGN_ID --require-validation --timezone Etc/GMT+5 --window 09:00-17:00 --min-interval 10 - Dry-run a small batch first:
flashrev-mailer send --campaign CAMPAIGN_ID --limit 5 --dry-run --yesAlways set--limitexplicitly (the CLI default is 25). Show a few rendered drafts to the user; have them confirm subject and body wording before any live send. - Send live in small batches, only after explicit user approval:
flashrev-mailer send --campaign CAMPAIGN_ID --limit 10 --live --yesRe-confirm with the user between batches before raising--limit. Never send the entire queue in one call. - Review and export results:
flashrev-mailer status --campaign CAMPAIGN_IDflashrev-mailer export --campaign CAMPAIGN_ID --format csv --out results.csv
Personalization guidance
- Use contact fields as template variables, for example
{{first_name}},{{company}}, and{{focus}}. - Use
{{field|fallback}}when a field may be blank. - Keep every generated email grounded in available contact fields or user-approved research.
- Ask for approval when the campaign goal, offer, or tone is ambiguous.
- Do not invent private facts about a recipient.
Safety rules
- Never print or store API keys in campaign exports, logs, or chat output.
- Keep API keys in environment variables only. Do not write the key into
.flashrev/config.json(or any other on-disk config) even when the user asks for "convenience" — config files persist on disk, sync to cloud drives, and can leak into git history. If a different variable name is needed, setflashrev.apiKeyEnv(the variable name, not the value). - Do not send to syntax-invalid, opted-out, suppressed, or validation-failed recipients.
- Treat risky, catch-all, accept-all, or unknown validation results as not deliverable unless the user explicitly approves otherwise.
- Always queue with
--require-validationunless the user explicitly opts out. - Minimum interval must stay at or above 10 minutes per sender mailbox — this is a hard lower bound, not negotiable.
- Always pass
--limittosend; never let the implicit default (25) decide batch size. Live sends should start small (≤ 10) and scale up only with re-confirmation. - Never pass
--send-futuretosend. It bypasses the scheduled time and the working-hour window, which defeats throttling and could trigger spam-trap responses from upstream SMTP providers. - Use
--dry-run --yesbefore live sending. - Use
--live --yesonly after the user approves final drafts, schedule, sender pool, and recipient set.
API adapter notes
The default endpoints in src/config.js reflect FlashRev's confirmed contract: mailbox listing, recipient verification, and SMTP credential retrieval. Sending uses the SMTP credentials returned by FlashRev to dial the upstream SMTP server (e.g. smtp.gmail.com:465) directly via nodemailer; FlashRev does not expose a generic send endpoint. For request/response shapes, see references/api_contract.md.