agentmail/types/lists.rs
1use serde::{Deserialize, Serialize};
2
3/// Which traffic direction a list governs. A path input only (there is no
4/// wire value to decode), so it has no unknown variant.
5#[derive(Clone, Copy, Debug, PartialEq, Eq)]
6pub enum ListDirection {
7 /// Applied to outbound (sent) mail.
8 Send,
9 /// Applied to inbound (received) mail.
10 Receive,
11 /// Applied to replies.
12 Reply,
13}
14
15impl ListDirection {
16 /// The path segment for this direction.
17 pub(crate) fn as_path(self) -> &'static str {
18 match self {
19 ListDirection::Send => "send",
20 ListDirection::Receive => "receive",
21 ListDirection::Reply => "reply",
22 }
23 }
24}
25
26/// Whether a list allows or blocks its entries. A path input only, so it has
27/// no unknown variant.
28#[derive(Clone, Copy, Debug, PartialEq, Eq)]
29pub enum ListKind {
30 /// An allow list.
31 Allow,
32 /// A block list.
33 Block,
34}
35
36impl ListKind {
37 /// The path segment for this kind.
38 pub(crate) fn as_path(self) -> &'static str {
39 match self {
40 ListKind::Allow => "allow",
41 ListKind::Block => "block",
42 }
43 }
44}
45
46/// Whether a list entry is an address or a whole domain.
47#[derive(Clone, Copy, Debug, PartialEq, Eq, Deserialize)]
48#[serde(rename_all = "lowercase")]
49pub enum EntryType {
50 /// A single email address.
51 Email,
52 /// A whole domain.
53 Domain,
54 /// An entry type this client version does not recognize.
55 #[serde(other)]
56 Unknown,
57}
58
59/// A single allow/block list entry.
60#[derive(Clone, Debug, Deserialize)]
61pub struct ListEntry {
62 /// The address or domain.
63 pub entry: String,
64 /// Free-text reason recorded with the entry.
65 #[serde(default)]
66 pub reason: Option<String>,
67 /// Whether the entry is an address or a domain.
68 #[serde(default = "unknown_entry_type")]
69 pub entry_type: EntryType,
70 /// The organization the entry belongs to.
71 #[serde(default)]
72 pub organization_id: Option<String>,
73 /// Traffic direction this entry governs: `send`, `receive`, or `reply`.
74 #[serde(default)]
75 pub direction: Option<String>,
76 /// Whether this is an `allow` or `block` entry.
77 #[serde(default)]
78 pub list_type: Option<String>,
79 /// Owning pod, when the account uses pods.
80 #[serde(default)]
81 pub pod_id: Option<String>,
82 /// Constrained inbox, when the entry is inbox-scoped.
83 #[serde(default)]
84 pub inbox_id: Option<String>,
85 /// Whether the entry is read-only (system-managed).
86 #[serde(default)]
87 pub read_only: bool,
88 /// Timestamp the entry was created (RFC 3339).
89 #[serde(default)]
90 pub created_at: Option<String>,
91}
92
93fn unknown_entry_type() -> EntryType {
94 EntryType::Unknown
95}
96
97/// Request body for `create_list_entry`.
98#[derive(Clone, Debug, Default, Serialize)]
99pub struct CreateListEntry {
100 /// The address or domain to add.
101 pub entry: String,
102 /// An optional reason to record with the entry.
103 #[serde(skip_serializing_if = "Option::is_none")]
104 pub reason: Option<String>,
105}
106
107/// One page of list entries from `list_list_entries_page`.
108#[derive(Clone, Debug, Deserialize)]
109pub struct ListEntries {
110 /// Total entries in the list (not just this page).
111 pub count: u64,
112 /// This page of entries.
113 #[serde(default)]
114 pub entries: Vec<ListEntry>,
115 /// Cursor for the next page; `None` on the last page.
116 #[serde(default)]
117 pub next_page_token: Option<String>,
118}