# MassMailer test plan (draft) ## Test environments - Run unit and scheduling tests against a fake mail adapter that records requests and injects errors; use a controllable clock. - Use a provider sandbox or dedicated internal mailbox for integration tests. No real business contacts in automated tests. - Perform a small live pilot only after contact eligibility, sender domain, opt-out process, and provider limits are checked. ## Test matrix | ID | Level | Scenario | Expected result | | --- | --- | --- | --- | | T01 | Unit | CSV with BOM, quoted commas, blank rows, duplicate case variants, malformed addresses | Preview explains each rejection; committed contacts are unique and source is retained. | | T02 | Unit | Import a previously suppressed address | Suppression remains active and campaign preflight excludes it. | | T03 | Unit | Empty subject, missing sender/postal address/opt-out route, unknown merge field | Approval blocked with actionable errors. | | T04 | Unit | Imported HTML template or contact field includes script, event handler, active object, `javascript:` URL, or HTML metacharacters | Active content is blocked; merged values are escaped; preview cannot execute script in the HTA. | | T05 | Unit | Three queued recipients across two campaigns with five-minute minimum interval | Attempt timestamps are at least five minutes apart across both campaigns, including after a failure or retry. | | T06 | Unit | Due send occurs overnight, on a weekend, or across a daylight-saving change while the HTA remains open | Dispatch remains eligible at any hour; UTC pacing gap holds; displayed local time is correct. | | T07 | Integration | Attempt to launch two HTA instances | Only one instance may dispatch; one provider request is made. | | T08 | Integration | HTA closes or crashes before, during, and after provider call | No new send begins after close; durable state survives; uncertain outcomes are flagged and not retried automatically. | | T09 | Integration | SMTP timeout, transient 4xx, permanent 5xx, TLS failure, or authentication rejection | Transient cases back off; permanent cases stop; connection or credential issue pauses and surfaces an action. | | T10 | Integration | Pause/cancel while a send is in flight | Current outcome is saved; no next attempt starts. | | T11 | Integration | Sleep/offline period covering several slots | No catch-up burst on wake; next send follows the persisted pacing clock. | | T12 | Integration | Opt-out arrives between queue selection and dispatch | Last-moment suppression check skips recipient. | | T13 | Integration | Test-send action | Only configured internal test address receives a message; live delivery counts do not advance. | | T14 | End to end | 10 internal test addresses across restart | Each recipient is attempted at most once in ordinary paths; report matches provider requests. | | T15 | Operations | Backup and restore queue, campaigns, and suppressions | Restored system resumes without lost opt-outs or accidental duplicate sends. | | T16 | Security | Inspect files/logs and run as least-privileged account | No secrets in app files or logs; unauthorized local account cannot read contact store. | | T17 | Unit | Load example INI; change `QUEUE_INTERVAL` from 300 to another allowed value; try missing/invalid port, TLS flags, send mode, image limits, or postal address | Valid values take effect according to their documented lifecycle; invalid transport values block sending; missing postal address blocks new campaign approval with a clear error. | | T18 | Integration | Fake SMTP server refuses STARTTLS or presents an invalid certificate | Sender fails closed; it does not send credentials or message content in plaintext. | | T19 | Integration | Launch with x86 and x64 hosts, a missing provider, a missing MDB, and an unsupported schema version | Only a matching host/provider with an openable configured MDB and supported schema starts the HTA; other cases show actionable errors before UI launch. | | T20 | Operations | Send an unsubscribe reply to the monitored mailbox and process it during daily review | Owner records suppression; no later queued send goes to that address. | | T21 | Integration | Import two HTML templates, approve a campaign with one, then edit its source `.html` and image files | The campaign sends its approved HTML and image snapshots; source edits do not change queued content. | | T22 | Integration | Send an internal test message with a local PNG/JPEG image | Raw MIME contains `multipart/related`, matching `cid:` references and inline image parts; no local paths appear in the received message. | | T23 | Unit | Import a template with path traversal, an absolute path, unsupported image type, or oversized image | Import blocks the asset with a clear reason and never reads outside the selected template folder. | | T24 | Manual integration | Open the internal test message in the intended desktop and web mail clients | HTML and inline images render as expected; reply address, postal address, and opt-out wording are visible. | | T25 | Integration | Change sender/reply/postal INI values and source template after approving a campaign | Existing campaign keeps its approved identity, footer, HTML, and images; a new campaign can use the new values. | | T26 | Unit | Shorten or lengthen `QUEUE_INTERVAL` while a prior attempt's gap is still pending | The next send occurs no earlier than both the old reserved time and the new interval measured from the last attempt. | | T27 | Operations | Restore the database under another Windows identity | Campaign and suppression data restore; SMTP password cannot be decrypted and must be entered again before sending. | | T28 | Integration | Close the HTA with a due campaign, wait past several intervals, then reopen | No sends occur while closed; reopening requires explicit resume and causes no catch-up burst. | | T29 | Integration | Invoke provider probe from both 32-bit and 64-bit script hosts on target PC | Diagnostic reports actual MDB create/write/read capability per provider and architecture; startup uses the verified architecture. | ## Release gates 1. All P1 stories and T01-T29 applicable to the chosen provider pass. 2. Sender domain and provider limits verified; the system can display provider rejection and halt safely. 3. Unsubscribe route is tested end to end; a recorded opt-out takes effect before the next dispatch. Any manual mailbox procedure has an owner and a tested processing schedule. 4. Operator receives deployment, backup/restore, pause, reconciliation, and incident instructions. 5. Pilot results reviewed for acceptance, bounces, complaints, and reporting accuracy before expanding recipients.