ffrelay_api/
types.rs

1//! Data types for Firefox Relay API requests and responses.
2
3use bon::Builder;
4use serde::{Deserialize, Serialize};
5use tabled::Tabled;
6
7/// Represents an email relay (alias) with its statistics and metadata.
8///
9/// This structure contains information about a single email relay,
10/// including its unique identifier, email address, and usage statistics.
11#[derive(Deserialize, Tabled)]
12pub struct FirefoxEmailRelay {
13    /// Unique identifier for this relay.
14    pub id: u64,
15
16    /// The full email address of the relay (e.g., "abc123@mozmail.com").
17    pub full_address: String,
18
19    /// Whether the relay is enabled or not
20    pub enabled: bool,
21
22    /// User-provided description for this relay.
23    pub description: String,
24
25    /// Number of emails that have been blocked by this relay.
26    pub num_blocked: u64,
27
28    /// Number of emails that have been forwarded to your real email address.
29    pub num_forwarded: u64,
30
31    /// Number of emails you've replied to through this relay.
32    pub num_replied: u64,
33
34    /// Number of spam emails detected for this relay.
35    pub num_spam: u64,
36}
37
38impl FirefoxEmailRelay {
39    /// Checks if this relay is a custom domain relay.
40    ///
41    /// Returns `true` if this is a custom domain relay (requires premium subscription),
42    /// or `false` if it's a standard @mozmail.com relay.
43    ///
44    /// # Example
45    ///
46    /// ```
47    /// # use ffrelay_api::types::FirefoxEmailRelay;
48    /// # use serde_json::json;
49    /// # let relay: FirefoxEmailRelay = serde_json::from_value(json!({
50    /// #     "id": 123,
51    /// #     "full_address": "test@mozmail.com",
52    /// #     "description": "test",
53    /// #     "num_blocked": 0,
54    /// #     "num_forwarded": 0,
55    /// #     "num_replied": 0,
56    /// #     "num_spam": 0
57    /// # })).unwrap();
58    /// assert_eq!(relay.is_domain(), false); // Standard relay
59    /// ```
60    pub fn is_domain(&self) -> bool {
61        if let Some((_, dom)) = self.full_address.split_once('@') {
62            !dom.eq("mozmail.com")
63        } else {
64            false
65        }
66    }
67}
68
69/// Request parameters for creating a new email relay.
70///
71/// Use the builder pattern to construct this request. The `description` field
72/// is required, while `enabled` defaults to `true` and `address` is optional.
73///
74/// # Example
75///
76/// ```
77/// use ffrelay_api::types::FirefoxEmailRelayRequest;
78///
79/// // Create a simple relay
80/// let request = FirefoxEmailRelayRequest::builder()
81///     .description("For newsletters".to_string())
82///     .build();
83///
84/// // Create a custom domain relay (requires premium)
85/// let request = FirefoxEmailRelayRequest::builder()
86///     .description("Shopping sites".to_string())
87///     .address("shopping".to_string())
88///     .build();
89/// ```
90#[derive(Debug, Serialize, Builder)]
91pub struct FirefoxEmailRelayRequest {
92    /// Description for the relay to help you remember its purpose.
93    #[serde(skip_serializing_if = "Option::is_none")]
94    description: Option<String>,
95
96    /// Whether the relay should be enabled immediately (defaults to `true`).
97    #[builder(default = true)]
98    enabled: bool,
99
100    /// Optional custom address for domain relays (requires premium subscription).
101    /// If `None`, a random address will be generated.
102    #[serde(skip_serializing_if = "Option::is_none")]
103    pub address: Option<String>,
104}
105
106/// Detailed information about a Firefox Relay profile.
107///
108/// Contains account-level information including subscription status,
109/// usage statistics, privacy settings, and configuration options.
110#[derive(Debug, Deserialize, Tabled)]
111pub struct FirefoxRelayProfile {
112    /// Unique identifier for this profile.
113    pub id: u64,
114
115    /// The API token for this profile (may be redacted in some responses).
116    pub api_token: String,
117
118    /// Whether the account has reached the maximum number of masks allowed.
119    pub at_mask_limit: bool,
120
121    /// URL to the user's avatar image.
122    pub avatar: String,
123
124    /// Date when the user subscribed to premium features (ISO 8601 format).
125    pub date_subscribed: String,
126
127    /// Total number of emails blocked across all relays.
128    pub emails_blocked: u64,
129
130    /// Total number of emails forwarded across all relays.
131    pub emails_forwarded: u64,
132
133    /// Total number of emails replied to across all relays.
134    pub emails_replied: u64,
135
136    /// Whether the account has the megabundle subscription.
137    pub has_megabundle: bool,
138
139    /// Whether the account has phone masking features.
140    pub has_phone: bool,
141
142    /// Whether the account has a premium subscription.
143    pub has_premium: bool,
144
145    /// Whether the account has Mozilla VPN.
146    pub has_vpn: bool,
147
148    /// Number of level one email trackers blocked.
149    pub level_one_trackers_blocked: u64,
150
151    /// Whether metrics collection is enabled for this profile.
152    pub metrics_enabled: bool,
153
154    /// Timestamp for the next allowed email creation attempt.
155    pub next_email_try: String,
156
157    /// Onboarding state for free tier users.
158    pub onboarding_free_state: u32,
159
160    /// General onboarding state.
161    pub onboarding_state: u32,
162
163    /// Whether level one email tracker removal is enabled.
164    pub remove_level_one_email_trackers: bool,
165
166    /// Whether server-side storage is enabled.
167    pub server_storage: bool,
168
169    /// Whether phone call logs are stored.
170    pub store_phone_log: bool,
171
172    /// Custom subdomain for premium users (e.g., "username" in username@mozilla.email).
173    pub subdomain: String,
174
175    /// Total number of email masks (relays) created.
176    pub total_masks: u64,
177}