Skip to Content
SimulatorsGmailMessages and threads

Simulators

Messages and threads

Messages and threads are the mailbox itself: the simulator keeps each message as its RFC 5322 text and renders every read from it. Read a thread, move a message through its labels, then trash and delete it and check the counts the profile reports:

curl -s -X POST "$RYSTIC_URL/_rystic/scenario" -d '{"name":"gmail_busy_inbox"}' -o /dev/null
G=(-H 'Authorization: Bearer ya29.placeholder')
curl -s "$RYSTIC_URL/gmail/v1/users/me/threads?maxResults=2" "${G[@]}" | jq -c '[.threads[] | {id, snippet}]'
# -> [{"id":"19a4c0d1e2f30004","snippet":"Standup notes - Monday: three in flight, one blocked"},{"id":"19a4c0d1e2f30003","snippet":"Your flight ZX4821 is confirmed, seat 14C"}]
curl -s "$RYSTIC_URL/gmail/v1/users/me/threads/19a4c0d1e2f30004" "${G[@]}" | jq -c '{id, messages: [.messages[] | {id, labelIds}]}'
# -> {"id":"19a4c0d1e2f30004","messages":[{"id":"19a4c0d1e2f31005","labelIds":["INBOX","UNREAD","Label_13"]},{"id":"19a4c0d1e2f31006","labelIds":["SENT","Label_13"]},{"id":"19a4c0d1e2f31007","labelIds":["INBOX","UNREAD","Label_13"]}]}
curl -s "$RYSTIC_URL/gmail/v1/users/me/messages/19a4c0d1e2f31007/modify" "${G[@]}" -H 'Content-Type: application/json' -d '{"removeLabelIds":["UNREAD"],"addLabelIds":["STARRED"]}' | jq -c '{id, labelIds}'
# -> {"id":"19a4c0d1e2f31007","labelIds":["INBOX","Label_13","STARRED"]}
curl -s -X POST "$RYSTIC_URL/gmail/v1/users/me/messages/19a4c0d1e2f31007/trash" "${G[@]}" | jq -c '{id, labelIds}'
# -> {"id":"19a4c0d1e2f31007","labelIds":["TRASH","Label_13","STARRED"]}
curl -s -X DELETE "$RYSTIC_URL/gmail/v1/users/me/messages/19a4c0d1e2f31007" "${G[@]}" -o /dev/null -w '%{http_code}\n'
# -> 204
curl -s "$RYSTIC_URL/gmail/v1/users/me/messages/19a4c0d1e2f31007" "${G[@]}" | jq -c '.error | {code, status, message}'
# -> {"code":404,"status":"NOT_FOUND","message":"Requested entity was not found."}
curl -s "$RYSTIC_URL/gmail/v1/users/me/profile" "${G[@]}" | jq -c '{emailAddress, messagesTotal, threadsTotal}'
# -> {"emailAddress":"ada.lovelace@example.com","messagesTotal":8,"threadsTotal":6}

Inserting, importing and sending

POST /gmail/v1/users/me/messages inserts a message: the whole RFC 5322 message as base64url raw, with the labelIds you give. It adds SENT when the From header is the mailbox’s own address. POST …/messages/import imports one, and POST …/messages/send sends one, labeled SENT. Each also takes an upload (Uploads), and a send records an event in the sent-mail log.

Inserted and sent messages join a thread only by the threadId you send, never by their Subject or References header. Without a threadId they start a thread of their own.

Differs from Gmail: an imported message joins no thread you can read (Limitations).

Reading a message

GET …/messages/{id} takes a format:

  • full returns the MIME part tree, each part’s headers and body, with an attachment as an attachmentId.
  • metadata returns only the headers metadataHeaders names.
  • minimal returns the ids, labels and snippet.
  • raw returns the base64url message as raw.

Every format carries snippet and sizeEstimate. GET …/messages/{id}/attachments/{attachmentId} returns an attachment’s data and size by the id its part names. In the busy inbox, the invoice message carries a PDF and a CSV:

G=(-H 'Authorization: Bearer ya29.placeholder')
curl -s "$RYSTIC_URL/gmail/v1/users/me/messages/19a4c0d1e2f31003?format=full" "${G[@]}" | jq -c '[.payload.parts[] | {mimeType, filename}]'
# -> [{"mimeType":"text/plain","filename":""},{"mimeType":"application/pdf","filename":"invoice-4471.pdf"},{"mimeType":"text/csv","filename":"line-items.csv"}]
curl -s "$RYSTIC_URL/gmail/v1/users/me/messages/19a4c0d1e2f31003/attachments/MTlhNGMwZDFlMmYzMTAwMzoy" "${G[@]}" | jq -c '{size}'
# -> {"size":58}

Labels, trash and delete

RequestWhat it does
modifyadds and removes labels
trashadds TRASH and removes INBOX
untrashremoves TRASH
deleteremoves the message for good; reading it then returns 404 notFound
batchModify, batchDeletetake a list of ids and return 204

Threads

GET …/threads lists threads newest first, each with its snippet. GET …/threads/{id} returns every message in the thread. A thread’s modify, trash, untrash and delete act on all of its messages. A thread modify that names one label in both addLabelIds and removeLabelIds returns 400 invalidArgument, “Cannot both add and remove the same label”.

Profile

GET …/profile returns the mailbox’s emailAddress and its current historyId, with messagesTotal and threadsTotal as they stand after the last write.

Errors

Every JSON error is Gmail’s envelope: {"error": {"code", "message", "status", "errors": [{"domain", "reason", "message"}]}}.

RequestReturns
an unknown id404 notFound, “Requested entity was not found.”
a userId the simulator does not take403 forbidden (Auth)
Last updated on