Mail Rules
Complete guide to configuring Mail Rules for automated email processing.
Mail rules define how inbound email is processed after a Mailbox fetches it. Rules are processed in priority order (lower number = higher priority). Each mailbox can have multiple rules; rules can be enabled or disabled without deleting them.
What are Mail Rules?
When an email matches a rule's conditions, the system executes actions such as:
- Extracting images from attachments and adding them to your picture database
- Parsing spreadsheet files (CSV/XLSX) and triggering EDI destinations
- Searching for pictures by container code and sending them via EDI
- Sending processing reports via email
Rule structure
Every rule has three main parts:
- When — Conditions that must be met for the rule to trigger
- Extract (optional) — Variables to extract from the email (e.g. container codes from subject)
- Then — Actions to execute when conditions match
{
"when": {
"type": "sender_email",
"value": "operations@example.com"
},
"extract": {
"variables": {
"container_code": {
"from": "subject",
"regex": "([A-Z]{4}[0-9]{7})",
"group": 1
}
}
},
"then": [
{
"action": "ingest_images",
"config": {
"target": {
"container_code": "{container_code}",
"terminal": "MAIN"
}
}
}
]
}
Conditions (When)
Basic conditions
Sender email — Match a specific sender:
{ "type": "sender_email", "value": "operations@example.com" }
Sender domain — Match any address in a domain:
{ "type": "sender_domain", "value": "@example.com" }
Subject contains — Case-insensitive substring:
{ "type": "subject_contains", "value": "Container Report" }
Subject regex — Regular expression on subject:
{ "type": "subject_regex", "regex": "^(BEANR0F|NLRTM08|NLRTM10)$" }
Body contains:
{ "type": "body_contains", "value": "urgent" }
Has attachment type:
{ "type": "has_attachment_type", "value": ["image/jpeg", "image/png"] }
Field comparison — Operators: eq, ne, contains, matches, in, gt, gte, lt, lte:
{ "field": "subject", "op": "contains", "value": "CAIU" }
Combining conditions
All (AND):
{
"all": [
{ "type": "sender_domain", "value": "@example.com" },
{ "type": "subject_contains", "value": "Container" }
]
}
Any (OR):
{
"any": [
{ "type": "subject_contains", "value": "BEANR0F" },
{ "type": "subject_contains", "value": "NLRTM08" }
]
}
Not (negation):
{
"not": { "type": "sender_domain", "value": "@spam.com" }
}
Variable extraction
Extract values from email fields to use in actions:
{
"extract": {
"variables": {
"container_code": {
"from": "subject",
"regex": "([A-Z]{4}[0-9]{7})",
"group": 1,
"required": true
},
"terminal": {
"from": "subject",
"regex": "Terminal: ([A-Z]+)",
"group": 1,
"default": "MAIN"
}
}
}
}
| Field | Description |
|---|---|
| from | Field to extract from (subject, body, sender, etc.) |
| regex | Pattern with capture groups |
| group | Capture group index (1 = first group) |
| required | Rule fails if variable cannot be extracted |
| default | Value if extraction fails |
Actions (Then)
1. Ingest images
Extract image attachments and add them to the picture database:
{
"action": "ingest_images",
"config": {
"target": {
"container_code": "{container_code}",
"terminal": "MAIN",
"case_date": "{case_date}",
"picture_source": "Mailbox",
"picture_creator": "Mailbox: Operations"
},
"attachment_filter": {
"content_types": ["image/jpeg", "image/png"],
"max_size_bytes": 10485760
},
"processing": {
"max_resolution": 1280,
"jpeg_quality": 90
}
}
}
2. Parse spreadsheet
Parse CSV or XLSX attachments and process each row via Code mappings:
{
"action": "parse_spreadsheet",
"config": {
"attachment_filter": {
"content_types": ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"],
"filename_pattern": "*.xlsx"
},
"parser": {
"type": "xlsx",
"sheet": 0,
"skip_rows": 0,
"max_rows": 0
},
"column_map": {
"customer": "client_name",
"containerno": "container_code"
}
}
}
Key configuration notes:
- parser.type —
csvorxlsx - column_map — Maps spreadsheet columns to internal fields
- use_code_mappings: true (default) — EDI destination and days_back come from each code mapping
- fallback_enabled — Use tenant fallback destination when no mapping matches
- use_code_mappings: false — Each row must include days_back (1–365)
- reporting — Optional summary email with CSV/JSONL attachments after all chunks finish
- Legacy rule fields days_back and send_when_no_pictures on
parse_spreadsheetare ignored — use code mappings instead
3. Search pictures and send EDI
Search by container code and send via EDI (useful when email has no attachments):
{
"action": "search_pictures_and_send_edi",
"config": {
"container_code": "{container_code}",
"days_back": 30,
"terminals": ["MAIN", "GATE"],
"destination": "EOS"
}
}
4. Send report
Email a processing report:
{
"action": "send_report",
"config": {
"to": "operations@example.com",
"subject": "Processed: {container_code}",
"include_logs": true
}
}
Complete examples
Example 1: Extract images from specific sender
{
"when": {
"all": [
{ "type": "sender_email", "value": "operations@example.com" },
{ "type": "subject_contains", "value": "Container" }
]
},
"extract": {
"variables": {
"container_code": {
"from": "subject",
"regex": "([A-Z]{4}[0-9]{7})",
"group": 1,
"required": true
}
}
},
"then": [
{
"action": "ingest_images",
"config": {
"target": {
"container_code": "{container_code}",
"terminal": "MAIN",
"case_date": "2026-01-20",
"picture_source": "Mailbox",
"picture_creator": "Mailbox: Operations"
},
"attachment_filter": {
"content_types": ["image/jpeg", "image/png"]
}
}
}
]
}
Example 2: Process spreadsheet from company domain
{
"when": {
"all": [
{ "type": "sender_domain", "value": "@example.com" },
{
"type": "has_attachment_type",
"value": ["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"]
}
]
},
"then": [
{
"action": "parse_spreadsheet",
"config": {
"parser": { "type": "xlsx", "sheet": 0 },
"column_map": {
"customer": "client_name",
"containerno": "container_code"
}
}
}
]
}
Example 3: EDI for specific subject patterns
{
"when": {
"all": [
{
"any": [
{ "type": "sender_email", "value": "operations@depot1.example.com" },
{ "type": "sender_email", "value": "notifications@depot2.example.com" }
]
},
{ "type": "subject_regex", "regex": "^(BEANR0F|NLRTM08|NLRTM10)$" },
{ "type": "subject_contains", "value": "CAIU" }
]
},
"extract": {
"variables": {
"container_code": {
"from": "subject",
"regex": "([A-Z]{4}[0-9]{7})",
"group": 1,
"required": true
}
}
},
"then": [
{
"action": "search_pictures_and_send_edi",
"config": {
"container_code": "{container_code}",
"days_back": 30,
"terminals": ["*"],
"destination": "EOS"
}
}
]
}
Best practices
- Use specific conditions — Combine sender and subject checks when possible
- Validate before saving — Use the Validate button in the Admin UI
- Set priorities — Specific rules: lower numbers; general rules: higher numbers
- Use variable extraction — Reuse rules across senders
- Start simple — Add complexity incrementally
- Monitor Processing state
- Use descriptive rule names
Troubleshooting
Rule not triggering?
- Check the rule is active (
is_active: true) - Verify conditions match the test email exactly
- Check rule priority — a higher-priority rule may match first
- Review Processing state for other rules on the same message
Variable extraction failing?
- Test regex with an online regex tester
- Ensure capture group numbering is correct (
group: 1= first parentheses) - Set
"required": falseand provide a"default"for optional variables
Actions not executing?
- Check Processing state for error messages
- Verify required fields (container_code, terminal, etc.)
- Ensure Code mappings exist for
parse_spreadsheet - Verify EDI destinations are configured for
search_pictures_and_send_edi
See also: Mailboxes, Processing state, Code mappings