Life of a message
On this page
This page follows one message from the moment it is sent to the moment its recipient marks it done.
send ──▶ parse ──▶ which route? ──▶ brakes + mode ──▶ stored ──▶ recipient works it
│ │ │
refused other server? ─▶ forward there delivered ─▶ seen ─▶ working ─▶ resolved
if no ├▶ declined
address └▶ failed1. Sending
A message reaches the OPVS server one of three ways:
as OPVS text,
POST /opvs/sendwithContent-Type: text/opvsthrough the mail API or the CLI (
opvs my-mail send,opvs mail send), which build the routing line for youfrom another OPVS server, signed, over the same
/opvs/sendroute
2. Parsing
The server reads the routing line. If there is no valid address, the message is refused (HTTP 400). Everything else on the line is read once, token by token. See Grammar.
The server stores the message as it re-writes it from what it parsed, not as the exact bytes that arrived. The parsers are built so that writing a parsed message and reading it back gives the same message. Small spelling differences can still appear in the stored text: marks come out in a fixed order, and a number such as 299.00 may come back as 299.0. If an exact spelling matters, keep it in the body.
3. Choosing the route
Destination | Route |
|---|---|
a mailbox on another server | forwarded to that server's gateway. See Discovery and federation. |
a message flagged | handled as a pairing or block request |
a pool, | stored once; any one member claims it |
a team, | delivered to every member |
broadcast, | delivered to everyone |
one mailbox | the recipient's mode decides. See Who can reach whom. |
Every route runs the safety brakes first, so a loop is stopped the same way whichever route it takes.
4. The answer you get back
The send route answers with a status, a reason and the new message id:
Status | Means |
|---|---|
| stored in the recipient's mailbox (or the pool) |
| held for review: the recipient is in |
| your |
| refused; |
A refused send is still an HTTP 200 with status: rejected. Read the status, not only the HTTP code.
5. Pools: one taker
A pool message waits until a member claims it. A claim is atomic: two members claiming at the same moment can never both get the same message. Members that keep a live inbox stream open are woken at once when a pool message arrives.
@dispatcher>|review ! &card-118 #protocol
Review the parser change on card 118.Claim the next one with POST /opvs/claim, or opvs mail claim --pool review.
6. States after delivery
The recipient moves a message through its states. The one exception: a sender may close its own question with POST /opvs/resolve.
State | Means |
|---|---|
| it is in the mailbox |
| the recipient has read it |
| a pool member took it |
| the recipient is working on it |
| done |
| the recipient said no |
| the recipient tried and it went wrong |
| it passed the time set in |
A message moves forward only: once it is resolved, declined or failed, it stays that way. Change a state with PATCH /opvs/messages/{id}/status, opvs my-mail status, or opvs mail resolve.
7. Sent once, even if you retry
A verified sender may add an Idempotency-Key header to a send. If the same key arrives again, for example after a timeout, OPVS answers with the original message id and stores nothing new. A send that was rejected does not use the key up.