Inbound Rules
Inbound Rules
Inbound rules let you automatically filter, route, and process incoming emails based on sender, subject, headers, and authentication results. Rules extend your existing alias routing — they evaluate before the alias default action and can override it.
How Rules Work
When an email arrives at one of your aliases, Postscale evaluates rules in priority order:
- Alias-specific rules run first (rules tied to the receiving alias)
- Domain-wide rules run next (rules with no alias specified)
- The first matching rule's action is applied
- If no rule matches, the alias default action runs (forward, webhook, etc.)
Rules extend aliases — they never replace your existing routing. If no rules match, everything works exactly as before.
Creating a Rule
curl -X POST "https://api.postscale.io/v1/domains/{domain_id}/rules" \
-H "Authorization: Bearer ps_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Block spam domain",
"conditions": [
{"field": "sender_domain", "comparator": "equals", "value": "spam.com"}
],
"action": "drop",
"priority": 10
}'
Or with the SDK:
await postscale.rules.create(domainId, {
name: 'Block spam domain',
conditions: [
{ field: 'sender_domain', comparator: 'equals', value: 'spam.com' }
],
action: 'drop',
priority: 10
});
Condition Fields
Each condition matches against a part of the incoming email:
| Field | What it matches | Example |
|---|---|---|
sender | Full sender address | spam@bad.com |
sender_domain | Domain part of sender | marketing.com |
subject | Subject line | URGENT, Invoice |
header | Any email header (specify header_name) | X-Mailer: BulkMailer |
spf | SPF authentication result | pass, fail, softfail, none |
dkim | DKIM authentication result | pass, fail, none |
Comparators
All comparators are case-insensitive except matches.
| Comparator | Description |
|---|---|
equals | Exact match |
not_equals | Not equal |
contains | Substring present |
not_contains | Substring absent |
starts_with | Begins with value |
ends_with | Ends with value |
matches | Regular expression |
Actions
| Action | What happens |
|---|---|
drop | Silently discard the email |
store | Store in DB without forwarding or webhooks |
mark_spam | Flag as spam, then continue to alias default action |
forward | Forward to specific addresses (overrides alias) |
webhook | Deliver to a specific webhook (overrides alias) |
Combining Conditions
Rules support AND/OR logic via the condition_match field:
"all"(default) — every condition must match (AND)"any"— at least one condition must match (OR)
You can add up to 10 conditions per rule.
Examples
Block a Spam Domain
Drop all emails from a known spam domain:
curl -X POST "https://api.postscale.io/v1/domains/{domain_id}/rules" \
-H "Authorization: Bearer ps_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Block spam.com",
"conditions": [
{"field": "sender_domain", "comparator": "equals", "value": "spam.com"}
],
"action": "drop",
"priority": 10
}'
Block Emails Failing SPF and DKIM
Drop emails that fail both SPF and DKIM authentication:
curl -X POST "https://api.postscale.io/v1/domains/{domain_id}/rules" \
-H "Authorization: Bearer ps_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Block unauthenticated senders",
"conditions": [
{"field": "spf", "comparator": "not_equals", "value": "pass"},
{"field": "dkim", "comparator": "not_equals", "value": "pass"}
],
"condition_match": "all",
"action": "drop",
"priority": 20
}'
Route Marketing Emails to a Webhook
Forward emails from a marketing domain to a specific webhook for processing:
curl -X POST "https://api.postscale.io/v1/domains/{domain_id}/rules" \
-H "Authorization: Bearer ps_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Marketing emails to webhook",
"conditions": [
{"field": "sender_domain", "comparator": "equals", "value": "marketing.example.com"}
],
"action": "webhook",
"action_config": {
"webhook_id": "your-webhook-uuid"
},
"priority": 30
}'
Forward Urgent Emails to Multiple Addresses
Catch any email with "urgent" or "critical" in the subject and forward to the on-call team:
curl -X POST "https://api.postscale.io/v1/domains/{domain_id}/rules" \
-H "Authorization: Bearer ps_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Urgent to on-call",
"conditions": [
{"field": "subject", "comparator": "contains", "value": "urgent"},
{"field": "subject", "comparator": "contains", "value": "critical"}
],
"condition_match": "any",
"action": "forward",
"action_config": {
"forward_to": ["oncall@company.com", "alerts@company.com"]
},
"priority": 5
}'
Block Bulk Mailers by Header
Drop emails sent by known bulk mailing software:
curl -X POST "https://api.postscale.io/v1/domains/{domain_id}/rules" \
-H "Authorization: Bearer ps_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Block bulk mailer",
"conditions": [
{
"field": "header",
"comparator": "contains",
"value": "BulkMailer",
"header_name": "X-Mailer"
}
],
"action": "drop",
"priority": 15
}'
Block Senders with Regex
Use a regex pattern to block multiple spam domains at once:
curl -X POST "https://api.postscale.io/v1/domains/{domain_id}/rules" \
-H "Authorization: Bearer ps_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Regex block spam domains",
"conditions": [
{
"field": "sender",
"comparator": "matches",
"value": ".*@(spam|junk|promo)\\.comquot;
}
],
"action": "drop",
"priority": 10
}'
Store Newsletters Without Forwarding
Keep newsletter emails in your Postscale inbox without forwarding them:
curl -X POST "https://api.postscale.io/v1/domains/{domain_id}/rules" \
-H "Authorization: Bearer ps_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "Store newsletters",
"conditions": [
{"field": "subject", "comparator": "contains", "value": "newsletter"},
{"field": "header", "comparator": "contains", "value": "list-unsubscribe", "header_name": "List-Unsubscribe"}
],
"condition_match": "any",
"action": "store",
"priority": 50
}'
Alias-Specific Rule
Attach a rule to a specific alias instead of the whole domain:
curl -X POST "https://api.postscale.io/v1/domains/{domain_id}/rules" \
-H "Authorization: Bearer ps_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"name": "VIP senders only for support@",
"alias_id": "your-alias-uuid",
"conditions": [
{"field": "sender_domain", "comparator": "not_equals", "value": "bigclient.com"}
],
"action": "drop",
"priority": 1
}'
Testing Rules
Before emails start flowing, test your rules against sample data to verify they work as expected. The test endpoint evaluates all rules and shows per-condition match details:
curl -X POST "https://api.postscale.io/v1/domains/{domain_id}/rules/test" \
-H "Authorization: Bearer ps_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"from": "user@spam.com",
"subject": "Buy cheap stuff now!!!",
"spf": "fail",
"dkim": "fail"
}'
Response:
{
"matched_rules": [
{
"rule_id": "...",
"rule_name": "Block spam.com",
"priority": 10,
"action": "drop",
"stop_processing": true,
"matched": true,
"conditions": [
{
"field": "sender_domain",
"comparator": "equals",
"value": "spam.com",
"matched": true,
"actual": "spam.com"
}
]
}
],
"effective_action": "drop",
"effective_rule_id": "...",
"would_fall_through": false
}
The would_fall_through field tells you whether the email would reach the alias default action (no rule matched or no rule stopped processing).
The test endpoint never affects real emails. Use it to debug complex rule sets before they go live.
Managing Rules
List Rules
curl "https://api.postscale.io/v1/domains/{domain_id}/rules" \
-H "Authorization: Bearer ps_live_your_api_key"
Update a Rule
Partial updates are supported — only include the fields you want to change:
curl -X PUT "https://api.postscale.io/v1/rules/{rule_id}" \
-H "Authorization: Bearer ps_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"active": false
}'
Delete a Rule
curl -X DELETE "https://api.postscale.io/v1/rules/{rule_id}" \
-H "Authorization: Bearer ps_live_your_api_key"
Reorder Rules
Change the evaluation order by setting new priorities:
curl -X PUT "https://api.postscale.io/v1/domains/{domain_id}/rules/reorder" \
-H "Authorization: Bearer ps_live_your_api_key" \
-H "Content-Type: application/json" \
-d '{
"rules": [
{"id": "rule-1-uuid", "priority": 10},
{"id": "rule-2-uuid", "priority": 20},
{"id": "rule-3-uuid", "priority": 30}
]
}'
Priority and Stop Processing
- Priority controls evaluation order. Lower numbers run first (0-1000, default 100).
- Stop processing (default
true) determines whether to stop evaluating further rules after a match. Set tofalseto allow multiple rules to match — the last matching rule's action wins.
Put your most specific rules at low priorities (e.g., 1-10) and catch-all rules at higher priorities (e.g., 100+). This ensures specific rules always take precedence.
Plan Limits
| Plan | Max rules per domain |
|---|---|
| Free | 5 |
| Starter | 25 |
| Plus | 50 |
| Pro | 100 |
| Scale | 500 |
Match Statistics
Every rule tracks how many emails it has matched and when it last matched. Use this to identify rules that are no longer effective or to monitor rule activity via the list endpoint.