#[non_exhaustive]pub struct Email {Show 29 fields
pub id: Id,
pub blob_id: Id,
pub thread_id: Id,
pub mailbox_ids: BTreeMap<Id, bool>,
pub keywords: BTreeMap<Keyword, bool>,
pub size: u64,
pub received_at: UTCDate,
pub message_id: Option<Vec<String>>,
pub in_reply_to: Option<Vec<String>>,
pub references: Option<Vec<String>>,
pub sender: Option<Vec<EmailAddress>>,
pub from: Option<Vec<EmailAddress>>,
pub to: Option<Vec<EmailAddress>>,
pub cc: Option<Vec<EmailAddress>>,
pub bcc: Option<Vec<EmailAddress>>,
pub reply_to: Option<Vec<EmailAddress>>,
pub subject: Option<String>,
pub sent_at: Option<Date>,
pub headers: Vec<EmailHeader>,
pub body_values: BTreeMap<String, EmailBodyValue>,
pub text_body: Vec<EmailBodyPart>,
pub html_body: Vec<EmailBodyPart>,
pub attachments: Vec<EmailBodyPart>,
pub body_structure: Option<EmailBodyPart>,
pub has_attachment: bool,
pub preview: Option<String>,
pub metadata: Option<Map<String, Value>>,
pub private_metadata: Option<Map<String, Value>>,
pub extra: Map<String, Value>,
}Expand description
An Email object (RFC 8621 §4.1).
Combines metadata (§4.1.1), parsed header convenience properties (§4.1.3), and body fields (§4.1.4).
§Full vs partial responses
This type is designed for full Email/get responses where all metadata
properties are present. The metadata fields blob_id, thread_id,
mailbox_ids, size, and received_at are required (non-Option);
deserialization fails if any of them is absent from the JSON.
RFC 8621 §4.5 allows clients to request only a subset of properties. If
a partial response omits any required metadata field, serde_json::from_str
will return a “missing field” error. For partial-property responses,
deserialize into serde_json::Value first or define a narrower type with
all fields Option.
Header convenience properties (§4.1.3) and body fields (§4.1.4) are all
Option; they deserialize as None when not included in the response.
§Serialization caveat for server implementors
Several collection fields (keywords, body_values, text_body,
html_body, attachments, headers) use
#[serde(skip_serializing_if = "…::is_empty")]. This is correct for
partial responses — a property not in the client’s properties list MUST be
absent from the response. However, RFC 8621 §4.1.1 defines keywords with
default: {}, meaning a server MUST include "keywords":{} in the response
when the property was requested and the email has no keywords.
Do not rely on serde_json::to_value(email) to produce RFC-compliant JSON
for full-object responses. Server code in jmap-mail-server must
explicitly populate any collection fields that are in the requested
properties set before serialization, or use a custom serializer that
includes them.
Fields (Non-exhaustive)§
This struct is marked as non-exhaustive
Struct { .. } syntax; cannot be matched against without a wildcard ..; and struct update syntax will not work.id: IdThe JMAP object id of this Email.
blob_id: IdBlob id of the raw RFC 5322 message octets.
thread_id: IdId of the Thread this Email belongs to.
mailbox_ids: BTreeMap<Id, bool>Set of Mailbox ids this Email belongs to.
Represented as BTreeMap<Id, bool> because the JMAP wire format uses a JSON object
with boolean values (RFC 8621 §4.1.1). Values are always true in full-object
responses; the map shape is also used in PatchObject updates (RFC 8620 §5.3) where
a null value removes an entry.
keywords: BTreeMap<Keyword, bool>Keywords applied to this Email.
Same JSON object shape as mailbox_ids (string keys, boolean values) — JMAP wire
format requirement. Keys are Keyword values (not JMAP Ids); system keywords
start with $ which is not valid inside a JMAP Id (RFC 8620 §1.2).
Values are always true in full-object responses (RFC 8621 §4.1.1).
size: u64Size in octets of the raw RFC 5322 message.
received_at: UTCDateDate the Email was received by the message store.
message_id: Option<Vec<String>>Value of the Message-ID header field as a list of message ids.
in_reply_to: Option<Vec<String>>Value of the In-Reply-To header field as a list of message ids.
references: Option<Vec<String>>Value of the References header field as a list of message ids.
sender: Option<Vec<EmailAddress>>Parsed addresses from the Sender header field.
from: Option<Vec<EmailAddress>>Parsed addresses from the From header field.
to: Option<Vec<EmailAddress>>Parsed addresses from the To header field.
cc: Option<Vec<EmailAddress>>Parsed addresses from the Cc header field.
bcc: Option<Vec<EmailAddress>>Parsed addresses from the Bcc header field.
reply_to: Option<Vec<EmailAddress>>Parsed addresses from the Reply-To header field.
subject: Option<String>Decoded text value of the Subject header field.
sent_at: Option<Date>Parsed value of the Date header field (RFC 8621 §4.1.3).
Type Date (any RFC 3339 timezone offset) per the RFC. Email Date
headers commonly carry non-UTC offsets such as "+10:00".
headers: Vec<EmailHeader>All header fields of the message in Raw form, in order.
body_values: BTreeMap<String, EmailBodyValue>Map from partId to decoded text content for text body parts.
text_body: Vec<EmailBodyPart>Text body parts to display, preferring text/plain.
html_body: Vec<EmailBodyPart>HTML body parts to display, preferring text/html.
attachments: Vec<EmailBodyPart>All attachment parts (depth-first, excluding subParts).
body_structure: Option<EmailBodyPart>Full MIME body structure of the message.
has_attachment: boolTrue if there is at least one downloadable attachment.
preview: Option<String>Short plaintext preview of the message body (≤256 characters).
metadata: Option<Map<String, Value>>Shared metadata, keyed by namespace identifier
(draft-ietf-jmap-metadata-04 §2). Each value is a JSON object (§2.1).
None when absent, which -04 §2 treats as {}; in an update a
null value “is equivalent to {}” (-04 §3.2) and also decodes as
None.
private_metadata: Option<Map<String, Value>>The authenticated user’s own metadata, keyed by namespace
identifier (draft-ietf-jmap-metadata-04 §2). Same shape and None
handling as metadata.
extra: Map<String, Value>Catch-all for vendor / site / private extension fields not covered by the typed fields above. Preserves unknown fields across deserialize/serialize round-trip per workspace extras-preservation policy (see workspace AGENTS.md).
Implementations§
Trait Implementations§
Source§impl<'de> Deserialize<'de> for Email
impl<'de> Deserialize<'de> for Email
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
impl Eq for Email
impl GetObject for Email
Source§impl JmapObject for Email
impl JmapObject for Email
Source§impl QueryObject for Email
impl QueryObject for Email
Source§type Comparator = EmailComparator
type Comparator = EmailComparator
Source§impl SetObject for Email
RFC 8621 §4.1 (rfc8621.txt:1316-2135): id, blobId, threadId,
size, hasAttachment and preview are “(immutable; server-set)”;
mailboxIds and keywords carry no attribute; every other property is
“(immutable)”. The header: forms (§4.1.3) are not struct fields.
draft-ietf-jmap-metadata-04 §3.2: clients write metadata and
privateMetadata through Foo/set.
impl SetObject for Email
RFC 8621 §4.1 (rfc8621.txt:1316-2135): id, blobId, threadId,
size, hasAttachment and preview are “(immutable; server-set)”;
mailboxIds and keywords carry no attribute; every other property is
“(immutable)”. The header: forms (§4.1.3) are not struct fields.
draft-ietf-jmap-metadata-04 §3.2: clients write metadata and
privateMetadata through Foo/set.
Source§const SERVER_SET: &'static [&'static str]
const SERVER_SET: &'static [&'static str]
/set method text never accepts from a
client, on create or update, is server-set too. Read moreSource§const CLIENT_SETTABLE: &'static [&'static str]
const CLIENT_SETTABLE: &'static [&'static str]
SERVER_SET: the ones a
client may set through /set. Read moreSource§const IMMUTABLE: &'static [&'static str]
const IMMUTABLE: &'static [&'static str]
CLIENT_SETTABLE properties the spec marks “immutable”: “The
value MUST NOT change after the object is created.” (RFC 8620 §1.1).
A property the /set method text accepts on create but not on update
is immutable too. Read more