QMail Overview (Group 6)

The RAIDA messaging surface. Six active commands cover the full lifecycle: upload encrypted file fragments, upload large file pages, notify the recipient’s beacon RAIDA, poll or peek the beacon for new mail, and download the stored fragments.

Overview

QMail is RAIDA’s store-and-forward messaging service. A message is split into stripes (typically 7 data + 1 parity) and one stripe is uploaded to each of 8 RAIDA servers. Small files use one-shot upload command 70; large attachments use additive page upload command 75. The sender then notifies the recipient’s “beacon” RAIDA — a single RAIDA agreed in advance with the recipient — that mail is waiting. The recipient long-polls (ping) or non-blocking-checks (peek) the beacon, downloads the private file_type=0 meta object first, and then reassembles the body and attachments locally.

Public Tell, private meta

The Tell is public to the beacon operator and carries routing, server locations, object sizes/checksums, and the inbox-fee locker needed for fee validation. Human-readable fields such as subject, filenames, labels, and preview text are private CBDF metadata and must be stored in file_type=0, not in the Tell.

Current QMail commands are wrapped in the standard 32-byte RAIDA AES-128 packet header. The 48-byte QMail preamble documented below is not that packet header; it is the first 48 bytes of the decrypted request body after the RAIDA header has been parsed.

All six active commands are encrypted at the wire level using AES-128 keyed by the caller’s selected coin AN. For upload, upload large page, tell, ping, and peek, the handler also compares the preamble AN against the stored coin record identified by the preamble. Download currently relies on wire decryption and file/ACL checks.

Object Transfer v1

The stable QMail Object Transfer v1 contract preserves commands 70–75 for compatibility and assigns commands 76–84 to resumable byte-range transfer, object information, live capability discovery, and owner-authorized deletion.

Per-command wire formats live on the dedicated pages linked from the sidebar: upload, upload large page, tell, ping, peek, and download. The stable resumable-transfer contract is documented separately in Object Transfer v1.

End-to-end flow

Sender                Storage RAIDAs (x8)              Beacon RAIDA              Recipient
  |                         |                              |                         |
  |-- upload 70 or 75 ----->|  one/page per RAIDA, parallel|                         |
  |<-- 250 OK --------------|                              |                         |
  |                         |                              |                         |
  |-------------------- tell (cmd 71) --------------------->|                         |
  |<------------------- 250 OK -----------------------------|                         |
  |                                                        |                         |
  |                                                        |<-- ping (cmd 72) -------|
  |                                                        |    long-poll, parks fd  |
  |                                                        |                         |
  |                                                        |-- 250 + tell blob ----->|
  |                                                        |                         |
  |                         |<------------------------- download (cmd 74) -----------|
  |                         |    one per RAIDA, parallel                             |
  |                         |-- 250 + 256KB page ------------------------------------>|
  |                                                        (reassemble locally)

Universal preamble (48 bytes)

Every QMail request body begins with a 48-byte preamble that authenticates the caller/mailbox identity. The preamble is the same for all six active commands and is separate from the RAIDA packet header. Its layout matches qmail_preamble_t in the raidax source:

Offset convention note: raidax counts the encrypted challenge(16) plus the QMail identity block as this 48-byte preamble; rest_core often names only the identity block QMAIL_PREAMBLE_SIZE = 32 because the protocol layer prepends the challenge separately. These are the same bytes with different offset origins.

OffsetSizeFieldDescription
0–1516Challenge12 random bytes followed by a 4-byte big-endian CRC32 of the random bytes. Required for replay protection.
16–238Session IDSet to all zeros for the standard QMail encryption mode.
24–252Coin TypeFixed 00 06 — the QMail/CloudCoin network ID.
261DenominationCaller/mailbox coin denomination (signed; valid range −8 to +6).
27–304Serial NumberCaller/mailbox coin serial number (big-endian). Identifies the AN-bearer being authenticated.
311ReservedWas Device ID. Server reads and ignores — available for future use. Set to 0.
32–4716Authenticity (AN)Caller/mailbox 16-byte AN for this RAIDA. Upload, tell, ping, and peek compare this to the stored AN for the (denom, SN) and reject with ERROR_INVALID_AN on mismatch.

Status codes

QMail uses the standard RAIDA status enum from protocol.h. The codes any QMail handler can return:

DecimalHexSymbolMeaning
80x08ERROR_COIN_NOT_FOUNDThe (denom, SN) in the preamble is not loaded on this RAIDA.
160x10ERROR_INVALID_PACKET_LENGTHBody too short for the command, missing terminator, or declared payload size doesn’t match the body length.
180x12ERROR_WRONG_RAIDAFor tell: no recipient inbox could be written (zero deliveries).
340x22ERROR_INVALID_ENCRYPTIONWire-level decryption failed before the command body was reached. Most often caused by sending a zero-AN preamble or selecting an encryption coin the RAIDA doesn’t hold.
400x28ERROR_INVALID_SN_OR_DENOMINATIONDenomination outside the allowed −8…+6 range.
1670xA7ERROR_PAYMENT_PROCESSINGTemporary payment or inbox-fee validation dependency failure; retry the operation.
1690xA9ERROR_PAYMENT_REQUIREDStorage locker payment could not be consumed (empty key or insufficient balance).
1940xC2ERROR_FILESYSTEMServer failed to create a directory, write a file, or arm an inotify watch.
1980xC6ERROR_INVALID_PARAMETERField validation failed (bad coin type, timestamp out of range, stripe count out of range, page beyond end of file, etc.).
2000xC8ERROR_INVALID_ANPreamble AN does not match the server’s stored AN for the (denom, SN).
2020xCAERROR_FILE_NOT_EXISTFor download: the requested (GUID, file_type) is not stored.
2500xFASTATUS_SUCCESSCommand completed successfully.
2540xFEERROR_MEMORY_ALLOCServer allocation failure.

Reserved bytes available for protocol extension

The current QMail wire structures contain the following reserved fields. Each is currently zero-filled by the sender and ignored by the server. They are catalogued here so future protocol extensions know which slots are available without breaking the existing layouts.

StructureFieldBytesNotes
Universal preamblebyte 31 (was Device ID)1Per-request, all six active commands. Server reads but ignores.
tell routing header (qmail_tell_req_t)reserved_1[4] at offset 20–234Sits between total_file_size and client_timestamp.
tell routing headerreserved_2[1] at offset 471Tail of the 48-byte routing header.
tell recipient entry (qmail_address_entry_t)reserved[8] at offset 24–318 per recipientOne entry per recipient (To/CC/BCC). Multiplies with recipient count.
tell file header (qmail_file_header_t)reserved[5] at offset 59–635 per emailTail of the manifest header. Bytes 57 (edit_sequence) and 58 (parity_algo) of the same region used to be reserved and now carry defined meanings. Pass-through — the recipient reads these bytes verbatim through tell → ping → download.
tell file manifest entryreserved[2] at entry offset 2–32 per fileOne per manifest entry (private meta + body + N attachments). Pass-through, sits between file_flags and original_size.
tell file header (qmail_file_header_t)manifest_flags bits 2–7 at offset 566 bits per emailBits 0 (footer_removed) and 1 (crc32_present) are defined. Bits 2–7 are available for future flags.
download request (qmail_download_req_t)bytes_per_page at offset 321Server hard-codes 256 KB pages and ignores this byte.
ping/peek response array header (qmail_response_array_header_t)reserved[5] at offset 3–75Sits between total_tells and the first 64-byte file-header that follows.

Largest contiguous pass-through region today: the 8 bytes per recipient in qmail_address_entry_t.reserved[8], plus the per-email 5-byte tail of the manifest header (file_header.reserved[59..63]). The address-entry reserved bytes are beacon-local (the beacon validates the address record); the manifest-header tail is pass-through and reaches the recipient verbatim.

Defined fields formerly listed as reserved. File-header bytes 57 (edit_sequence) and 58 (parity_algo) used to be part of the manifest-header reserved tail. They now carry sender-controlled meanings — see the tell page for details.

Legacy footer migration note. Pre-manifest .tell files on disk include an 18-byte recipient footer (tag 0x50, length 16, recipient locker). Current manifest v1 records have no footer. Implementations may strip the legacy footer when migrating pre-manifest .tell files; new code should not emit, parse, or expect a footer on the wire.