/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ pub mod serialize; pub mod status; use self::serialize::serialize_hex; use crate::{ error::method::MethodErrorWrapper, method::{ availability::GetAvailabilityResponse, changes::ChangesResponse, copy::{CopyBlobResponse, CopyResponse}, get::GetResponse, import::ImportEmailResponse, lookup::BlobLookupResponse, parse::ParseResponse, query::QueryResponse, query_changes::QueryChangesResponse, search_snippet::GetSearchSnippetResponse, set::SetResponse, upload::BlobUploadResponse, validate::ValidateSieveScriptResponse, }, object::{ AnyId, addressbook::AddressBook, blob::Blob, calendar::Calendar, calendar_event::CalendarEvent, calendar_event_notification::{ CalendarEventNotification, CalendarEventNotificationGetResponse, }, contact::ContactCard, email::Email, email_submission::EmailSubmission, file_node::FileNode, identity::Identity, mailbox::Mailbox, participant_identity::ParticipantIdentity, principal::Principal, push_subscription::PushSubscription, quota::Quota, registry::Registry, share_notification::ShareNotification, sieve::Sieve, thread::Thread, vacation_response::VacationResponse, }, request::{Call, method::MethodName}, }; use jmap_tools::{Null, Value}; use std::collections::HashMap; #[derive(Debug, serde::Serialize)] #[serde(untagged)] pub enum ResponseMethod<'x> { Get(GetResponseMethod), Set(SetResponseMethod), Changes(ChangesResponseMethod), Copy(CopyResponseMethod), ImportEmail(ImportEmailResponse), Parse(ParseResponseMethod), QueryChanges(QueryChangesResponse), Query(QueryResponse), SearchSnippet(GetSearchSnippetResponse), ValidateScript(ValidateSieveScriptResponse), LookupBlob(BlobLookupResponse), UploadBlob(BlobUploadResponse), Echo(Value<'x, Null, Null>), Error(MethodErrorWrapper), } #[derive(Debug, serde::Serialize)] #[serde(untagged)] pub enum GetResponseMethod { Email(GetResponse), Mailbox(GetResponse), Thread(GetResponse), Identity(GetResponse), EmailSubmission(GetResponse), PushSubscription(GetResponse), Sieve(GetResponse), VacationResponse(GetResponse), Principal(GetResponse), PrincipalAvailability(GetAvailabilityResponse), Quota(GetResponse), Blob(GetResponse), AddressBook(GetResponse), ContactCard(GetResponse), FileNode(GetResponse), Calendar(GetResponse), CalendarEvent(GetResponse), CalendarEventNotification(CalendarEventNotificationGetResponse), ParticipantIdentity(GetResponse), ShareNotification(GetResponse), Registry(GetResponse), MaskedEmail(GetResponse), DeletedAccount(GetResponse), } #[derive(Debug, serde::Serialize)] #[serde(untagged)] pub enum SetResponseMethod { Email(Box>), Mailbox(Box>), Identity(Box>), EmailSubmission(Box>), PushSubscription(Box>), Sieve(Box>), VacationResponse(Box>), AddressBook(Box>), ContactCard(Box>), FileNode(Box>), ShareNotification(Box>), Calendar(Box>), CalendarEvent(Box>), CalendarEventNotification(Box>), ParticipantIdentity(Box>), Registry(Box>), MaskedEmail(Box>), DeletedAccount(Box>), } #[derive(Debug, serde::Serialize)] #[serde(untagged)] pub enum ChangesResponseMethod { Email(Box>), Mailbox(Box>), Thread(Box>), Identity(Box>), EmailSubmission(Box>), Quota(Box>), AddressBook(Box>), ContactCard(Box>), FileNode(Box>), Calendar(Box>), CalendarEvent(Box>), CalendarEventNotification(Box>), ShareNotification(Box>), // inbuxa: x:MaskedEmail/changes Registry(Box>), } #[derive(Debug, serde::Serialize)] #[serde(untagged)] pub enum CopyResponseMethod { Email(CopyResponse), ContactCard(CopyResponse), CalendarEvent(CopyResponse), FileNode(CopyResponse), Blob(CopyBlobResponse), } #[derive(Debug, serde::Serialize)] #[serde(untagged)] pub enum ParseResponseMethod { Email(ParseResponse), ContactCard(ParseResponse), CalendarEvent(ParseResponse), } #[derive(Debug, serde::Serialize)] pub struct Response<'x> { #[serde(rename = "methodResponses")] pub method_responses: Vec>>, #[serde(rename = "sessionState")] #[serde(serialize_with = "serialize_hex")] pub session_state: u32, #[serde(rename = "createdIds")] #[serde(skip_serializing_if = "HashMap::is_empty")] pub created_ids: HashMap, } impl<'x> Response<'x> { pub fn new(session_state: u32, created_ids: HashMap, capacity: usize) -> Self { Response { session_state, created_ids, method_responses: Vec::with_capacity(capacity), } } pub fn push_response( &mut self, id: String, name: MethodName, method: impl Into>, ) { self.method_responses.push(Call { id, method: method.into(), name, }); } pub fn push_error(&mut self, id: String, err: impl Into) { self.method_responses.push(Call { id, method: ResponseMethod::Error(err.into()), name: MethodName::error(), }); } pub fn push_created_id(&mut self, create_id: String, id: impl Into) { self.created_ids.insert(create_id, id.into()); } } impl From for ResponseMethod<'_> { fn from(error: trc::Error) -> Self { ResponseMethod::Error(error.into()) } } impl<'x, T: Into>> From> for ResponseMethod<'x> { fn from(result: trc::Result) -> Self { match result { Ok(value) => value.into(), Err(error) => error.into(), } } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::Email(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::Mailbox(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::Thread(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::Identity(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::EmailSubmission(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::PushSubscription(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::Sieve(value)) } } // inbuxa: Fastmail's MaskedEmail impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::MaskedEmail(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::MaskedEmail(Box::new(value))) } } // inbuxa: deleted accounts (UD-17) impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::DeletedAccount(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::DeletedAccount(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::VacationResponse(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::Principal(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::Quota(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::Blob(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::ContactCard(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::AddressBook(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::Registry(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::Email(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::Mailbox(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::Identity(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::EmailSubmission(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::PushSubscription(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::Sieve(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::VacationResponse(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::AddressBook(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::ContactCard(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::Registry(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: ChangesResponse) -> Self { ResponseMethod::Changes(ChangesResponseMethod::Email(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: ChangesResponse) -> Self { ResponseMethod::Changes(ChangesResponseMethod::Mailbox(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: ChangesResponse) -> Self { ResponseMethod::Changes(ChangesResponseMethod::Thread(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: ChangesResponse) -> Self { ResponseMethod::Changes(ChangesResponseMethod::Identity(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: ChangesResponse) -> Self { ResponseMethod::Changes(ChangesResponseMethod::EmailSubmission(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: ChangesResponse) -> Self { ResponseMethod::Changes(ChangesResponseMethod::Quota(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: ChangesResponse) -> Self { ResponseMethod::Changes(ChangesResponseMethod::AddressBook(Box::new(value))) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: CopyResponse) -> Self { ResponseMethod::Copy(CopyResponseMethod::Email(value)) } } impl<'x> From for ResponseMethod<'x> { fn from(value: CopyBlobResponse) -> Self { ResponseMethod::Copy(CopyResponseMethod::Blob(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: CopyResponse) -> Self { ResponseMethod::Copy(CopyResponseMethod::ContactCard(value)) } } impl<'x> From for ResponseMethod<'x> { fn from(value: ImportEmailResponse) -> Self { ResponseMethod::ImportEmail(value) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: ParseResponse) -> Self { ResponseMethod::Parse(ParseResponseMethod::Email(value)) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: ParseResponse) -> Self { ResponseMethod::Parse(ParseResponseMethod::ContactCard(value)) } } impl<'x> From for ResponseMethod<'x> { fn from(value: QueryChangesResponse) -> Self { ResponseMethod::QueryChanges(value) } } impl<'x> From for ResponseMethod<'x> { fn from(value: QueryResponse) -> Self { ResponseMethod::Query(value) } } impl<'x> From for ResponseMethod<'x> { fn from(value: GetSearchSnippetResponse) -> Self { ResponseMethod::SearchSnippet(value) } } impl<'x> From for ResponseMethod<'x> { fn from(value: ValidateSieveScriptResponse) -> Self { ResponseMethod::ValidateScript(value) } } impl<'x> From for ResponseMethod<'x> { fn from(value: BlobLookupResponse) -> Self { ResponseMethod::LookupBlob(value) } } impl<'x> From for ResponseMethod<'x> { fn from(value: BlobUploadResponse) -> Self { ResponseMethod::UploadBlob(value) } } impl<'x> From> for ResponseMethod<'x> { fn from(value: Value<'x, Null, Null>) -> Self { ResponseMethod::Echo(value) } } impl<'x> From for ResponseMethod<'x> { fn from(value: MethodErrorWrapper) -> Self { ResponseMethod::Error(value) } } impl From> for ResponseMethod<'_> { fn from(response: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::FileNode(response)) } } impl From> for ResponseMethod<'_> { fn from(response: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::FileNode(Box::new(response))) } } impl From> for ResponseMethod<'_> { fn from(response: ChangesResponse) -> Self { ResponseMethod::Changes(ChangesResponseMethod::FileNode(Box::new(response))) } } impl From for ResponseMethod<'_> { fn from(response: GetAvailabilityResponse) -> Self { ResponseMethod::Get(GetResponseMethod::PrincipalAvailability(response)) } } impl From> for ResponseMethod<'_> { fn from(response: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::Calendar(response)) } } impl From> for ResponseMethod<'_> { fn from(response: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::Calendar(Box::new(response))) } } impl From> for ResponseMethod<'_> { fn from(response: ChangesResponse) -> Self { ResponseMethod::Changes(ChangesResponseMethod::CalendarEvent(Box::new(response))) } } impl From> for ResponseMethod<'_> { fn from(response: ChangesResponse) -> Self { ResponseMethod::Changes(ChangesResponseMethod::CalendarEventNotification(Box::new( response, ))) } } impl From> for ResponseMethod<'_> { fn from(response: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::CalendarEvent(Box::new(response))) } } impl From> for ResponseMethod<'_> { fn from(response: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::ParticipantIdentity(Box::new(response))) } } impl From> for ResponseMethod<'_> { fn from(response: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::ParticipantIdentity(response)) } } impl From> for ResponseMethod<'_> { fn from(response: ChangesResponse) -> Self { ResponseMethod::Changes(ChangesResponseMethod::ShareNotification(Box::new(response))) } } impl From> for ResponseMethod<'_> { fn from(response: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::ShareNotification(Box::new(response))) } } impl From> for ResponseMethod<'_> { fn from(response: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::ShareNotification(response)) } } impl From> for ResponseMethod<'_> { fn from(response: GetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::CalendarEvent(response)) } } impl From> for ResponseMethod<'_> { fn from(value: ParseResponse) -> Self { ResponseMethod::Parse(ParseResponseMethod::CalendarEvent(value)) } } impl From> for ResponseMethod<'_> { fn from(value: CopyResponse) -> Self { ResponseMethod::Copy(CopyResponseMethod::CalendarEvent(value)) } } impl From> for ResponseMethod<'_> { fn from(value: CopyResponse) -> Self { ResponseMethod::Copy(CopyResponseMethod::FileNode(value)) } } impl From for ResponseMethod<'_> { fn from(value: CalendarEventNotificationGetResponse) -> Self { ResponseMethod::Get(GetResponseMethod::CalendarEventNotification(value)) } } impl From> for ResponseMethod<'_> { fn from(value: SetResponse) -> Self { ResponseMethod::Set(SetResponseMethod::CalendarEventNotification(Box::new( value, ))) } }