use serde::{Deserialize, Serialize};
use std::collections::HashMap;
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Session {
pub capabilities: HashMap<String, Capability>,
pub accounts: HashMap<String, Account>,
pub primary_accounts: HashMap<String, String>,
pub username: String,
pub api_url: String,
pub download_url: String,
pub upload_url: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub event_source_url: Option<String>,
pub state: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Capability {
#[serde(skip_serializing_if = "Option::is_none")]
pub max_concurrent_requests: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_calls_in_request: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_size_request: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_size_upload: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_objects_in_get: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_objects_in_set: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub collation_algorithms: Option<Vec<String>>,
}
impl Default for Capability {
fn default() -> Self {
Self {
max_concurrent_requests: Some(4),
max_calls_in_request: Some(16),
max_size_request: Some(10 * 1024 * 1024), max_size_upload: Some(50 * 1024 * 1024), max_objects_in_get: Some(500),
max_objects_in_set: Some(500),
collation_algorithms: Some(vec![
"i;ascii-numeric".to_string(),
"i;ascii-casemap".to_string(),
]),
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct Account {
pub name: String,
pub is_personal: bool,
pub is_read_only: bool,
pub account_capabilities: HashMap<String, AccountCapability>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct AccountCapability {
#[serde(skip_serializing_if = "Option::is_none")]
pub max_mailboxes_per_email: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_mailbox_depth: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_size_mailbox_name: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub max_size_attachments_per_email: Option<u64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub email_query_sort_options: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub may_upload_script: Option<bool>,
}
impl Default for AccountCapability {
fn default() -> Self {
Self {
max_mailboxes_per_email: Some(10),
max_mailbox_depth: Some(10),
max_size_mailbox_name: Some(255),
max_size_attachments_per_email: Some(50 * 1024 * 1024), email_query_sort_options: Some(vec![
"receivedAt".to_string(),
"from".to_string(),
"subject".to_string(),
"size".to_string(),
]),
may_upload_script: Some(false),
}
}
}
impl Session {
pub fn new(username: String, account_id: String, base_url: String) -> Self {
let mut capabilities = HashMap::new();
let mut accounts = HashMap::new();
let mut primary_accounts = HashMap::new();
let core_cap_uri = "urn:ietf:params:jmap:core".to_string();
capabilities.insert(core_cap_uri.clone(), Capability::default());
let mail_cap_uri = "urn:ietf:params:jmap:mail".to_string();
capabilities.insert(mail_cap_uri.clone(), Capability::default());
let submission_cap_uri = "urn:ietf:params:jmap:submission".to_string();
capabilities.insert(submission_cap_uri.clone(), Capability::default());
let mut account_caps = HashMap::new();
account_caps.insert(mail_cap_uri.clone(), AccountCapability::default());
account_caps.insert(submission_cap_uri.clone(), AccountCapability::default());
let account = Account {
name: username.clone(),
is_personal: true,
is_read_only: false,
account_capabilities: account_caps,
};
accounts.insert(account_id.clone(), account);
primary_accounts.insert(core_cap_uri, account_id.clone());
primary_accounts.insert(mail_cap_uri, account_id.clone());
primary_accounts.insert(submission_cap_uri, account_id);
Self {
capabilities,
accounts,
primary_accounts,
username,
api_url: format!("{}/jmap", base_url),
download_url: format!("{}/download/{{accountId}}/{{blobId}}/{{name}}", base_url),
upload_url: format!("{}/upload/{{accountId}}", base_url),
event_source_url: Some(format!("{}/eventsource", base_url)),
state: "session-state-1".to_string(),
}
}
}