Skip to main content

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}