ForgeSendDocs

Bulk import via CSV

Bulk import connects multiple SMTP inboxes in one pass from a CSV file, instead of using the SMTP / Manual form one inbox at a time. Each row can also auto-start warmup on the inbox it connects, with its own warmup mode, volume, reply rate, and sending schedule.

CSV column format

The CSV needs a header row. Columns are matched by header name, not position — so the columns can appear in any order — but header matching is case-sensitive, so Email will not satisfy the email requirement.

ColumnRequiredNotes
emailAlwaysMust pass email-format validation
smtpHostAlwaysUp to 255 characters
smtpPortAlwaysWhole number, 1–65535
smtpSecureModeAlwaysExactly STARTTLS, SSL_TLS, or NONE (case-insensitive)
smtpUsernameAlwaysUp to 255 characters
smtpPasswordAlwaysUp to 500 characters — never trimmed
autoStartWarmupAlwaysExactly Y or N (case-insensitive)
displayNameOptionalUp to 120 characters
imapHostOnly if autoStartWarmup = Y
imapPortOnly if autoStartWarmup = Y
imapSecureModeOnly if autoStartWarmup = YExactly STARTTLS, SSL_TLS, or NONE
imapUsernameOnly if autoStartWarmup = Y
imapPasswordOnly if autoStartWarmup = Y
warmupModeOptionalBlank, RAMPING, MAINTENANCE, or CUSTOM — blank defaults to RAMPING
customVolumeOnly if warmupMode = CUSTOMWhole number
replyRateOptionalWhole number if given — blank uses warmup's own default
sendingScheduleOptionalMust match an existing workspace schedule name

If autoStartWarmup is N, the imapHost/imapPort/imapSecureMode/imapUsername/imapPassword columns can still be filled in, but they're stored without being validated — and warmupMode, customVolume, replyRate, and sendingSchedule are ignored entirely, not even format-checked.

Rows where every column is blank are dropped automatically before anything else runs. A CSV with no usable rows left after that is rejected with "No usable rows were found in this CSV." A sample CSV matching this exact column set is available from the import dialog.

Validation order

Each row is validated and processed through the same sequence, in this order:

  1. Format checks — the column rules above, checked locally with no network calls. A row that fails here never reaches the network.
  2. Sending schedule lookup — if a sendingSchedule name was given, it's resolved against the workspace before anything else. An unmatched name fails the row here: "Sending schedule "{name}" was not found in this workspace."
  3. Live SMTP and IMAP pre-checks — only run when autoStartWarmup = Y. SMTP is checked first with a real connection and authentication attempt; IMAP is only checked if SMTP passes. A row with autoStartWarmup = N skips both pre-checks — the inbox connection step below does its own SMTP verification regardless.
  4. Connect the inbox — always attempted (this is the same connect call the manual SMTP / Manual form uses), including its own internal SMTP re-verification even on a warmup row that already passed the pre-check.
  5. Start warmup — only if autoStartWarmup = Y and the inbox connected. Applies the same defaults as starting warmup manually: RAMPING mode, roughly 15% reply rate, and the workspace's default sending schedule.
  6. Apply overrides — any row-requested warmupMode/customVolume, replyRate, or sendingSchedule are applied on top of step 5's defaults. Each of the three overrides is applied independently, so one failing doesn't block the other two.

Pre-import warnings

Two warnings can appear on individual rows before you confirm the import. Both are informational only — neither one blocks the row from being imported.

Port / secure-mode mismatch. Shown when a row's port is exactly one of the conventional values below but its secure mode doesn't match:

PortExpected secure mode
587 (SMTP)STARTTLS
465 (SMTP)SSL_TLS
143 (IMAP)STARTTLS
993 (IMAP)SSL_TLS

The message reads: "Port {port} is usually paired with {SSL/TLS or STARTTLS}, not {whatever the row's secure mode is}." The IMAP half of this check only runs on rows with autoStartWarmup = Y.

customVolume ignored. Shown when a row sets customVolume but warmupMode isn't CUSTOM — since customVolume only ever takes effect in CUSTOM mode; RAMPING and MAINTENANCE both use their own fixed volume. The message reads: "customVolume ({value}) will be ignored — warmupMode is {blank (defaults to RAMPING) or whatever was given}, not CUSTOM. {RAMPING or MAINTENANCE}'s own fixed volume will be used instead."

Row cap

20 rows per upload. A CSV with more rows than that is rejected before any row is sent, with: "This file has {n} rows — imports are capped at 20 rows per upload. Split this file and import it in batches." At least 1 row is required.

Rows are processed strictly one at a time (see Known limitations), so a batch where every row needs both SMTP and IMAP pre-checks can take several minutes worst case. The 20-row cap exists specifically to keep a full batch inside that window.

Per-row results

Each row gets three independent results, not one pass/fail — because connecting the inbox, starting warmup, and configuring warmup overrides can each succeed or fail on their own. Every result is one of Done, Failed, or Not requested.

Import results — read only
RowConnectedWarmup startedWarmup configured
sales1@acme.comDoneDoneDone
sales2@acme.comDoneNot requestedNot requested
sales3@acme.comFailedNot requestedNot requested
  • Connected — never Not requested, since connecting is always attempted. Failed covers everything upstream of a successful connect: a format-validation failure, a sending-schedule lookup miss, a failed SMTP/IMAP pre-check, or the connect call itself failing.
  • Warmup startedNot requested if the row's autoStartWarmup was N. Otherwise Failed if starting warmup errors (for example, no active warmup subscription, or the workspace's shared monthly warmup volume was already used up by an earlier row in the same batch) — note that Connected stays Done in that case, since the inbox itself connected fine. Done once warmup starts.
  • Warmup configuredNot requested whenever warmup wasn't started or failed to start, since overrides are only applied after a successful start. Failed if any of the up-to-three overrides (warmupMode/customVolume, replyRate, sendingSchedule) errors, with the specific failing override(s) named in the message. A row that requested no overrides at all (blank warmupMode, blank replyRate, blank sendingSchedule) still gets Done here, since there was nothing to fail — it's running on step 5's RAMPING defaults.

Known limitations

  • Rows are processed strictly one at a time, synchronously, inside a single request — there's no background queue. This is deliberate, partly to stay well under the warmup provider's own request-rate limit, not just to avoid hammering target mail servers.
  • No duplicate-email detection. Nothing in the import checks for the same email appearing twice in one CSV, or against an inbox that's already connected in the workspace — each row is processed independently. Results are matched back to rows by position (row 1, row 2, ...), not by email, specifically because an email can legitimately repeat across rows.
  • Passwords are never trimmed. smtpPassword and imapPassword are used exactly as given, including any leading or trailing whitespace — every other column is trimmed.

Where to go next

Next: Warmup overview