Skip to the documentation
MCP server

Rules

What happens to mail as it arrives.

Rules tools

ToolWhat it does
listRulesEvery rule on the active connection, in the order they are evaluated, a page at a time, with what each one does and how often it has fired.
getRuleOne rule in full: its conditions, its actions and whether it is on.
createRuleWrite a rule: conditions over an arriving message, and what should happen to anything matching them. The rule is created DISABLED.
testRuleWhich of the last thirty days’ messages a rule would have caught, and what it would have done to them. Changes nothing.
setRuleEnabledTurn one rule on or off, once a person has read it back.
updateRuleChange a rule: its name, conditions, actions, whether it stops the rules below, whether it is on, or its position.
deleteRuleDelete a rule for good. Nothing it already did is undone. A chat always asks first.
reorderRulesSet the order the rules run in, naming every rule you can see once.
listRuleRunsWhat the rules did, newest first: which rule matched which message, what it did and what failed. Returned a page at a time.

createRule writes the rule DISABLED, which is the one place this server deliberately differs from the REST API. POST /rules defaults to enabled. A rule that archives, trashes or forwards mail should not start doing it on the strength of a chat message: write it, call testRule to show the person you are working for which of their own messages it would have caught, and only then ask for setRuleEnabled.

updateRule, deleteRule and reorderRules change the rules that exist, exactly as PATCH /rules/{id}, DELETE /rules/{id} and POST /rules/reorder do. A deleted rule cannot be restored and a reorder changes what every later message does, so updateRule and deleteRule always show the person a card to approve in the assistant, and a client should ask first as well. listRuleRuns reads what the rules did.

Rules belong to the CONNECTION, so these act on whichever mailbox setActiveConnection last named, and a rule a colleague wrote is one of them. A mailbox holds 100 rules, each with at most 20 conditions and 10 actions.

Nothing here is retroactive. A rule decides what happens to mail arriving after it is enabled; it does not sweep a mailbox that already exists, and testRule reports rather than files.

Some tools on this server make a change the REST API guards with a verification code, and ask for the same code. Until the client has verified a code in the last 60 minutes, or the person has chosen Allow changes for 60 minutes on it in Account → Connected apps, such a tool answers with a result that starts Refused (step_up_required): and changes nothing. emptyAudience never asks for a code. The API Authentication page lists every tool that asks, and shows how to ask for a code and verify it.

Reference

listRules

Scopesrules:readThe app's assistant runs it without askingToolkitrules

Mail rules on the active connection, in the order they run. A rule is a set of conditions over an inbound message and a list of things to do to anything matching them: label it, archive it, forward it. Order matters: rules run top to bottom and one marked "stops here" prevents every rule below it from running. Reports whether each is enabled, which is the fact worth reading. A disabled rule is doing nothing at all. Use getRule for one in full, including its conditions and its actions. One page at a time: when more follow, the last line gives a cursor to pass back, with the same filter, for the next page.

Inputs

enabledboolean
limitinteger
At least 1At most 100Default50
cursorstring

Also available in

API
GET /rules
TypeScript
nextmail.rules.list()nextmail.rules.listAll()nextmail.rules.iterate()
Python
rules.list()rules.list_all()rules.iterate()
Ruby
rules.listrules.list_allrules.iterate
PHP
rules->listrules->listAllrules->iterate
Go
Rules.ListRules.ListAllRules.Iterate
Java
rules().listrules().listAllrules().iterate
C#
Rules.ListAsyncRules.ListAllAsyncRules.IterateAsync

getRule

Scopesrules:readThe app's assistant runs it without askingToolkitrules

One rule in full, by id (rul_…): every condition it tests, every action it takes, whether it stops the rules below it, and how many messages it has matched. Read this back to the person before asking for a rule to be enabled. The conditions are the part that decides what happens to their mail, and a rule reads very differently from the sentence that asked for it.

Inputs

idstringRequired

Also available in

API
GET /rules/{id}
TypeScript
nextmail.rules.get()
Python
rules.get()
Ruby
rules.get
PHP
rules->get
Go
Rules.Get
Java
rules().get
C#
Rules.GetAsync

createRule

Scopesrules:writeThe app's assistant always asks firstToolkitrules

Create a mail rule on the active connection: conditions over an inbound message, and what should happen to anything matching them. THE RULE IS CREATED DISABLED. It does nothing to any mail until a person turns it on, because a rule that archives or forwards should not start doing that on the strength of a chat message. Call testRule next to show which of the last thirty days’ messages it would have caught, read the rule back, and only then ask whether to enable it with setRuleEnabled. Rules run in order and a new one goes last: reorderRules changes the order, updateRule edits a rule and deleteRule removes it.

Inputs

namestringRequired
1 to 100 characters
descriptionstring

A note on what the rule is for, shown under its name in the app.

Up to 500 characters
matchstring
One of"all""any"Default"all"
conditionsobject[]Required
fieldstringRequired
One of"from""from_domain""envelope_from""to""cc""bcc""recipient""reply_to""delivered_to""subject""body""header""list_id""attachment_name""attachment_type""has_attachment""attachment_size""message_size""spam""bounced""hour""weekday"
opstringRequired
One of"matches""contains""equals""starts_with""ends_with""gt""lt"
valuestringRequired
headerstring
negateboolean
Defaultfalse
actionsobject[]Required
typestringRequired
One of"label""remove_label""archive""mark_read""star""spam""trash""forward""reply""block_sender""reject"
valuestring
stopProcessingboolean
Defaultfalse

Also available in

API
POST /rules
TypeScript
nextmail.rules.create()
Python
rules.create()
Ruby
rules.create
PHP
rules->create
Go
Rules.Create
Java
rules().create
C#
Rules.CreateAsync

testRule

Scopesrules:readThe app's assistant runs it without askingToolkitrules

A dry run: which of the recent messages in the inbox this rule WOULD have matched, and what it would have done to them. Changes nothing: no message is labelled, archived, forwarded or replied to, and the rule is not enabled. This is what to show a person before asking whether to turn a rule on. It scores the newest message each thread RECEIVED and never the mailbox’s own sends or replies, because a rule only ever runs on arriving mail. It reads STORED messages rather than deliveries, which costs the answer two different ways and both belong in whatever you report. Conditions on a raw header, on a mailing-list id, on the SMTP envelope, on message size or on the delivered-to address cannot be answered at all and are reported as untestable rather than counted as misses. Attachment, hour and weekday conditions ARE answered, but from stored mail rather than from the delivery. Stored mail drops images inlined into the body, which delivery counts as attachments, and keeps only the sender’s own Date: header, where delivery uses our receipt clock. Those are therefore reported as approximate, and the dates printed beside each match are the sender’s. A message that arrived encrypted has no readable body at all, so a body condition is neither matched nor missed on it. The result says how many were skipped that way, and that number belongs in whatever you report. Pass those caveats on rather than relaying the count as an exact answer.

Inputs

idstringRequired
daysinteger
At least 1At most 365Default30
limitinteger
At least 1At most 200Default50

Also available in

API
POST /rules/{id}/test
TypeScript
nextmail.rules.test()
Python
rules.test()
Ruby
rules.test
PHP
rules->test
Go
Rules.Test
Java
rules().test
C#
Rules.TestAsync

setRuleEnabled

Scopesrules:writeThe app's assistant always asks firstToolkitrules

Turn a rule on or off. ENABLING A RULE STARTS IT ACTING ON REAL MAIL IMMEDIATELY: the next message that matches it is labelled, archived, forwarded or replied to without anybody being asked, and some of those cannot be undone. Only enable a rule a person has actually been shown. Call getRule to read it back and testRule to show what it would have caught, and ask. It applies to mail that arrives from now on and does not go back over messages already in the mailbox. Disabling is the reverse and is always safe: the rule stops matching and nothing it already did is undone.

Inputs

idstringRequired
enabledbooleanRequired

Also available in

API
PATCH /rules/{id}
TypeScript
nextmail.rules.update()
Python
rules.update()
Ruby
rules.update
PHP
rules->update
Go
Rules.Update
Java
rules().update
C#
Rules.UpdateAsync

updateRule

Scopesrules:writeThe app's assistant always asks firstToolkitrules

Change a rule: its name, description, conditions, actions, whether it stops the rules below it, whether it is on, or its position. What you pass replaces that part of the rule, so conditions and actions are whole lists. A rule that is on acts on the next message that matches it, so read it back with getRule and show testRule first. reorderRules sets the whole order at once.

Inputs

idstringRequired

The rule, by its id (rul_…). listRules names every one.

1 to 128 characters
namestring
1 to 100 characters
descriptionstring
Can be nullUp to 500 characters
matchstring
One of"all""any"
conditionsobject[]
fieldstringRequired
One of"from""from_domain""envelope_from""to""cc""bcc""recipient""reply_to""delivered_to""subject""body""header""list_id""attachment_name""attachment_type""has_attachment""attachment_size""message_size""spam""bounced""hour""weekday"
opstringRequired
One of"matches""contains""equals""starts_with""ends_with""gt""lt"
valuestringRequired
headerstring
negateboolean
Defaultfalse
actionsobject[]
typestringRequired
One of"label""remove_label""archive""mark_read""star""spam""trash""forward""reply""block_sender""reject"
valuestring
stopProcessingboolean
enabledboolean
positioninteger
At least 0At most 1000000

Also available in

API
PATCH /rules/{id}
TypeScript
nextmail.rules.update()
Python
rules.update()
Ruby
rules.update
PHP
rules->update
Go
Rules.Update
Java
rules().update
C#
Rules.UpdateAsync

deleteRule

Scopesrules:writeThe app's assistant always asks firstToolkitrules

Delete a rule for good. It stops acting on mail at once, and nothing it already did is undone. There is no bin for rules. setRuleEnabled with enabled false is the reversible way to stop one.

Inputs

idstringRequired

The rule, by its id (rul_…). listRules names every one.

1 to 128 characters

Also available in

API
DELETE /rules/{id}
TypeScript
nextmail.rules.delete()
Python
rules.delete()
Ruby
rules.delete
PHP
rules->delete
Go
Rules.Delete
Java
rules().delete
C#
Rules.DeleteAsync

reorderRules

Scopesrules:writeThe app's assistant asks first unless you asked for itToolkitrules

Set the order rules run in, first to last. ruleIds has to name every rule listRules shows you, each once. Order is part of what rules do: one that stops the rules below it hides them from every message it matches.

Inputs

ruleIdsstring[]Required
1 to 1000 items

Also available in

API
POST /rules/reorder
TypeScript
nextmail.rules.reorder()
Python
rules.reorder()
Ruby
rules.reorder
PHP
rules->reorder
Go
Rules.Reorder
Java
rules().reorder
C#
Rules.ReorderAsync

listRuleRuns

Scopesrules:readThe app's assistant runs it without askingToolkitrules

What the rules did, newest first: each time a rule matched a message, which actions it took and which of them failed. Narrow it to one rule with ruleId or to one conversation with threadId. One page at a time: when more follow, the last line gives a cursor to pass back, with the same filters, for the next page.

Inputs

ruleIdstring
1 to 128 characters
threadIdstring
1 to 128 characters
limitinteger
At least 1At most 100
cursorstring
1 to 128 characters

Also available in

API
GET /rules/runs
TypeScript
nextmail.rules.listRuns()nextmail.rules.listAllRuns()nextmail.rules.iterateRuns()
Python
rules.list_runs()rules.list_all_runs()rules.iterate_runs()
Ruby
rules.list_runsrules.list_all_runsrules.iterate_runs
PHP
rules->listRunsrules->listAllRunsrules->iterateRuns
Go
Rules.ListRunsRules.ListAllRunsRules.IterateRuns
Java
rules().listRunsrules().listAllRunsrules().iterateRuns
C#
Rules.ListRunsAsyncRules.ListAllRunsAsyncRules.IterateRunsAsync