The mailbox-server
CLI starts an HTTP server that provides a REST API interface for interacting with a mailbox. It stores the messages in an SQLite database. The mailbox
CLI can interact with this API server as documented here. Another other application can use the same REST interface to read and update messages. For example, suppose you have a script that runs hourly in a Cloudflare Worker that scrapes a webpage for new data. That script can create messages based simply by making calls to the REST endpoint provided by this server.
$ mailbox-server
$ curl http://localhost:8080/messages
Sets the port that the HTTP server will listen on. The port can also be set with the $PORT
environment variable.
$ mailbox-server --port=9000
$ curl http://localhost:9000/messages
Instructs the HTTP server to bind to 0.0.0.0 instead of 127.0.0.1 and accept incoming connections from other machines on the network.
$ mailbox-server --expose
# On another machine using the server machine's IP address
$ curl http://10.0.0.10:9000/messages
Causes the HTTP server to expect an Authorization: Bearer {token}
header containing this token on all requests. Without this arg, no Authorization
header is required.
$ mailbox-server --token=0a1b2c3de4f5
$ curl http://localhost:8080/messages -H "Authorization: Bearer 0a1b2c3de4f5"
Path to the SQLite database file that the server uses to store the messages
$ mailbox-server --db-file=$HOME/messages.db
$ curl http://localhost:8080/messages
All responses are in JSON.
All API endpoints support filtering the messages that will be interacted with via query string parameters. The available filters are as follows:
ids
: comma-separated list of message ids?ids=3
matches the message with the id3
?ids=1,4,5
matches the messages with the ids1
,4
,5
mailbox
: name of the mailbox or parent mailbox?mailbox=my-script
matches all messages inmy-script
and all children mailboxes likemy-script/mailbox-1
andmy-script/mailbox-2
?mailbox=my-script/mailbox-1
matches all messages inmy-script/mailbox-1
and all children mailboxes likemy-script/mailbox-1/sub-mailbox
andmy-script/mailbox-2/sub-mailbox
states
: comma-separated list of message states (unread
,read
, orarchived
)?states=read
matches all read messages?states=unread,archived
matches all unread or archived messages
Filters can also be combined. For example, ?mailbox=other-script&states=read,archived
matches read or archived messages in the other-script
mailbox.
If no filter is provided, all messages will be interacted with.
If an authorization token was specified when starting the server, all requests must be sent with an Authorization
header of Bearer {token}
where {token}
is your configured API token.
All responses are JSON arrays of message objects. The format of message objects is as follows:
id
(integer): the message's idtimestamp
(string): the message's creation date in UTC ISO formatmailbox
(string): the message's mailboxcontent
(string): the message's contentstate
(string): the message's state, which will be one ofunread
,read
, orarchived
Example message:
{
"id": 123,
"timestamp": "2023-01-01T12:01:02.345678",
"mailbox": "foo",
"content": "bar",
"state": "unread"
}
Reads messages. Responds with a JSON array of messages matching the optional message filter ordered by timestamp descending.
Reads mailbox sizes. Responds with an array of JSON objects with a name
key that is the mailbox name and a message_count
key that is the number of messages that the mailbox contains. The array elements are ordered by the mailbox name ascending. If an optional message filter is provided, only messages that match the filter are counted towards mailbox sizes.
Example response:
[
{ "name": "mailbox-1", "message_count": 5 },
{ "name": "mailbox-2", "message_count": 2 },
{ "name": "mailbox-2/child", "message_count": 1 },
{ "name": "mailbox-3", "message_count": 4 }
]
Creates new messages. Responds with a JSON array of the created messages ordered by timestamp descending. This is the only endpoint that does not accept a message filter. New messages should be posted as JSON in the request body with a Content-Type
header of application/json
. The body can either be a single message object or an array of message objects. These are the accepted message object fields:
mailbox
(string): the message's mailboxcontent
(string): the message's contentstate
(string optional): the message's state, which will be one ofunread
,read
, orarchived
(defaults tounread
if omitted)
Example single-message payload:
{
"mailbox": "my-script",
"content": "Hello, world!",
"state": "read"
}
Example multi-message payload:
[
{
"mailbox": "my-script",
"content": "Hello, world!"
},
{
"mailbox": "my-script",
"content": "Hello, universe!",
"state": "archived"
}
]
Updates message states. Responds with a JSON array of the updated messages ordered by timestamp descending. Only updates messages matching the optional filter. If no filter is provided, all messages are updated. The new message state should be put as a JSON encoded object with a single field new_state
in the request body with a Content-Type
header of application/json
. new_state
can have the value unread
, read
, or archived
.
Example request payload to mark all messages as read:
{"new_state": "read"}
Permanently deletes messages. Responds with a JSON array of the deleted messages ordered by timestamp descending. Only updates messages matching the optional filter. Unlike the other endpoints, if no filter is provided, an error is returned instead of deleting all messages as a safety measure to prevent data loss.