Chaos and faults
Real mail servers fail. Fault rules make simmail’s SMTP server fail on purpose, so you can test that your app retries, backs off and reports bounces properly.
Faults apply to mail your app sends over SMTP. Mail sent with POST /api/send is not affected. Changing them needs the admin role.
A rule says when to misbehave and how.
| Field | Meaning |
|---|---|
name | Your label. |
kind | error (the default), greylist, rate or drop. |
stage | When in the SMTP conversation: mail, rcpt or data. |
match | Which addresses: an exact address, @domain, or empty (or *) for all. |
rate | Chance, 0 to 1, that an error or drop rule fires. |
code | The SMTP reply code, such as 421, 450, 451, 452, 550, 552 or 554. 0 means delay only. |
enhanced | The enhanced status code, such as 5.7.26. Defaults to the code’s class (5.0.0). |
message | The reply text your app sees. |
delay_ms | Wait this long before answering. |
retry_after | Greylisting: seconds before a retry is accepted. |
per_minute | Rate limiting: messages a minute before deferring. |
window | Only at certain times (below). |
enabled | Whether the rule is on. |
What each stage matches
Section titled “What each stage matches”| Stage | match is compared with |
|---|---|
mail | The sender (MAIL FROM). |
rcpt | Each recipient (RCPT TO). |
data | Each recipient, then the sender, once the message has been sent. |
What each kind does
Section titled “What each kind does”| Kind | Behaviour |
|---|---|
error | With chance rate: waits delay_ms, then answers code. With code 0 it only delays. |
greylist | The first attempt for each sender and recipient pair is deferred with 451 4.7.1; a retry after retry_after seconds is accepted. |
rate | More than per_minute messages in a minute are deferred with 421 4.7.0. |
drop | With chance rate: waits delay_ms, then closes the connection without answering. |
code, enhanced and message override the defaults for greylist and rate too.
The first enabled rule that matches, is in its window, and fires decides. Greylisting and rate rules that let a message through hand over to the next rule. Order your rules from most to least specific.
Setting rules
Section titled “Setting rules”PUT /api/faults replaces the whole list:
curl -s -X PUT https://c1.simmail.dev/api/faults \ -H "Authorization: Bearer smk_your_admin_key" \ -H "Content-Type: application/json" \ -d '[ { "name": "Harbor mailbox is full", "stage": "rcpt", "match": "dana@harbor.test", "rate": 1, "code": 552, "enhanced": "5.2.2", "message": "Mailbox full", "enabled": true }, { "name": "Flaky server", "stage": "data", "rate": 0.2, "code": 451, "message": "Temporary local problem, try again", "enabled": true } ]'GET /api/faults reads them. PUT /api/faults with [] clears them.
Scenarios
Section titled “Scenarios”Scenarios are ready-made rules with the codes and wording big providers really send. GET /api/faults/scenarios lists them. POST /api/faults/scenarios/{id} adds one as an enabled rule:
curl -s -X POST https://c1.simmail.dev/api/faults/scenarios/gmail-rate \ -H "Authorization: Bearer smk_your_admin_key" \ -H "Content-Type: application/json" \ -d '{"match": "@gmail.com"}'The body is optional: a non-empty match replaces the scenario’s match, and window limits it in time. The answer is the full list of rules.
| Id | Provider | What happens |
|---|---|---|
gmail-unauthenticated | Gmail | 550 5.7.26 at data for @gmail.com: unauthenticated sender. |
gmail-rate | Gmail | Rate limit of 10 a minute for @gmail.com, 421 4.7.28. |
gmail-no-user | Gmail | 10% of @gmail.com recipients do not exist, 550 5.1.1. |
gmail-over-quota | Gmail | 10% of @gmail.com recipients are over quota, 452 4.2.2. |
microsoft-busy | Microsoft | 30% of @outlook.com recipients deferred, 451 4.7.500 “Server busy”. |
microsoft-blocked | Microsoft | 550 5.7.1 blocklisted client host, at the mail stage for @outlook.com. |
microsoft-access-denied | Microsoft | @outlook.com recipients refused, 550 5.4.1. |
yahoo-deferred | Yahoo / AOL | Half of sessions deferred, 421 4.7.0 [TSS04], at the mail stage for @yahoo.com. |
yahoo-policy | Yahoo / AOL | 554 5.7.9 at data for @yahoo.com: not accepted for policy reasons. |
greylisting | Any server | Greylisting, retry accepted after 60 seconds. |
rate-limit | Any server | More than 20 messages a minute deferred with 421. |
drop | Any server | 20% of messages: the server hangs up during data. |
slow | Any server | Every message takes 20 seconds to be accepted. |
mailbox-full | Any server | 10% of recipients have a full mailbox, 552 5.2.2. |
Windows
Section titled “Windows”A window limits a rule to certain times on the universe’s simulated clock, such as “Thursdays from 14:00 to 15:00”:
{ "days": "thu", "from": "14:00", "to": "15:00", "tz": "Europe/London" }| Field | Values |
|---|---|
days | mon, mon-fri, sat,sun, all (also * or empty) |
from, to | HH:MM. A window may run past midnight, such as 22:00 to 02:00. |
tz | A time zone name. Defaults to the server’s. |
Simple refusals and delays are in every plan. Greylisting, rate limits, dropped connections, windows and scenarios need the chaos profiles feature of your plan; without it, the API answers 402.
Bounces without fault rules
Section titled “Bounces without fault rules”Faults change the SMTP conversation. To have an address accept mail and then bounce it later, as many real providers do, use the recipient rules instead: mark an address full, unknown, disabled, blocked or domain, or make a share of never-seen addresses dead.