1 This file describes the schemata used for notmuch's structured output
2 format (currently JSON and S-Expressions).
4 []'s indicate lists. List items can be marked with a '?', meaning
5 they are optional; or a '*', meaning there can be zero or more of that
6 item. {}'s indicate an object that maps from field identifiers to
7 values. An object field marked '?' is optional; one marked with '*'
8 can repeat (with a different name). |'s indicate alternates (e.g.,
9 int|string means something can be an int or a string).
11 For S-Expression output, lists are printed delimited by () instead of
12 []. Objects are printed as p-lists, i.e. lists where the keys and values
13 are interleaved. Keys are printed as keywords (symbols preceded by a
14 colon), e.g. (:id "123" :time 54321 :from "foobar"). Null is printed as
15 nil, true as t and false as nil.
17 This is version 5 of the structured output format.
23 - First versioned schema release.
24 - Added part.content-length and part.content-transfer-encoding fields.
27 - Added the thread_summary.query field.
30 - Replaced message.filename string with a list of filenames.
31 - Added part.content-disposition field.
34 - replace signature error integer bitmask with a set of flags for
36 - (notmuch 0.29) added message.crypto to identify overall message
40 - sorting support for notmuch show (no change to actual schema,
41 just new command line argument)
46 # Number of seconds since the Epoch
49 # Thread ID, sans "thread:"
52 # Message ID, sans "id:"
55 # E-mail header name, sans trailing colon, like "Subject" or "In-Reply-To"
61 # A top-level set of threads (do_show)
62 # Returned by notmuch show without a --part argument
63 thread_set = [thread*]
65 # Top-level messages in a thread (show_messages)
66 thread = [thread_node*]
68 # A message and its replies (show_messages)
70 message|null, # null if not matched and not --entire-thread
71 [thread_node*] # children of message
74 # A message (format_part_sprinter)
76 # (format_message_sprinter)
80 timestamp: unix_time, # date header as unix time
81 date_relative: string, # user-friendly timestamp
87 body?: [part] # omitted if --body=false
90 # when showing the message, was any or all of it decrypted?
91 msgdecstatus: "full"|"partial"
93 # The overall cryptographic state of the message as a whole:
97 # was the set of signatures described under encrypted cover?
99 # which of the headers is covered by sigstatus?
100 headers: [header_name*]
103 status: msgdecstatus,
104 # map encrypted headers that differed from the outside headers.
105 # the value of each item in the map is what that field showed externally
106 # (maybe null if it was not present in the external headers).
107 header-mask: { header_name*: string|null }
111 # A MIME part (format_part_sprinter)
113 id: int|string, # part id (currently DFS part number)
115 encstatus?: encstatus,
116 sigstatus?: sigstatus,
118 content-type: string,
119 content-disposition?: string,
121 # if content-type starts with "multipart/":
123 # if content-type is "message/rfc822":
124 content: [{headers: headers, body: [part]}],
125 # otherwise (leaf parts):
127 content-charset?: string,
128 # A leaf part's body content is optional, but may be included if
129 # it can be correctly encoded as a string. Consumers should use
130 # this in preference to fetching the part content separately.
132 # If a leaf part's body content is not included, the length of
133 # the encoded content (in bytes) may be given instead.
134 content-length?: int,
135 # If a leaf part's body content is not included, its transfer encoding
136 # may be given. Using this and the encoded content length, it is
137 # possible for the consumer to estimate the decoded content length.
138 content-transfer-encoding?: string
141 # The headers of a message or part (format_headers_sprinter with reply = FALSE)
153 extra_header_pair= (header_name: string)
154 # Encryption status (format_part_sprinter)
155 encstatus = [{status: "good"|"bad"}]
157 # Signature status (format_part_sigstatus_sprinter)
158 sigstatus = [signature*]
161 # (signature_status_to_string)
162 status: "good"|"bad"|"error"|"unknown",
163 # if status is "good":
164 fingerprint?: string,
169 # if status is not "good":
179 alg-unsupported?: bool,
187 notmuch search schema
188 ---------------------
191 search_summary = [thread_summary*]
194 search_threads = [threadid*]
197 search_messages = [messageid*]
200 search_files = [string*]
203 search_tags = [string*]
207 timestamp: unix_time,
208 date_relative: string, # user-friendly timestamp
209 matched: int, # number of matched messages
210 total: int, # total messages in thread
211 authors: string, # comma-separated names with | between
212 # matched and unmatched
216 # Two stable query strings identifying exactly the matched and
217 # unmatched messages currently in this thread. The messages
218 # matched by these queries will not change even if more messages
219 # arrive in the thread. If there are no matched or unmatched
220 # messages, the corresponding query will be null (there is no
221 # query that matches nothing). (Added in schema version 2.)
222 query: [string|null, string|null],
229 # The headers of the constructed reply
230 reply-headers: reply_headers,
232 # As in the show format (format_part_sprinter)
236 # Reply headers (format_headers_sprinter with reply = TRUE)