/* * SPDX-FileCopyrightText: 2020 Stalwart Labs LLC * * SPDX-License-Identifier: AGPL-3.0-only OR LicenseRef-SEL */ use std::time::Instant; use crate::core::Session; use common::network::SessionStream; use imap_proto::{ Command, StatusResponse, protocol::{ ImapResponse, capability::{Capability, Response}, quoted_string, }, receiver::Request, }; use registry::schema::enums::Permission; impl Session { pub async fn handle_capability(&mut self, request: Request) -> trc::Result<()> { // Validate access self.assert_has_permission(Permission::ImapCapability)?; let op_start = Instant::now(); trc::event!( Imap(trc::ImapEvent::Capabilities), SpanId = self.session_id, Tls = self.is_tls, Strict = !self.server.core.imap.allow_plain_auth, Elapsed = op_start.elapsed() ); self.write_bytes( StatusResponse::completed(Command::Capability) .with_tag(request.tag) .serialize( Response { capabilities: Capability::all_capabilities( self.state.is_authenticated(), !self.is_tls && self.instance.acceptor.is_tls(), self.is_tls || self.server.core.imap.allow_plain_auth, self.server.core.imap.max_messages_per_command, self.server.core.imap.max_messages_per_save, ), } .serialize(), ), ) .await } pub async fn handle_id(&mut self, request: Request) -> trc::Result<()> { // Validate access self.assert_has_permission(Permission::ImapId)?; let op_start = Instant::now(); trc::event!( Imap(trc::ImapEvent::Id), SpanId = self.session_id, Elapsed = op_start.elapsed() ); self.write_bytes( StatusResponse::completed(Command::Id) .with_tag(request.tag) .serialize( concat!( "* ID (\"name\" \"", types::brand!(), "\" \"version\" \"1.0.0\" \"vendor\" \"", types::brand!(), "\" \"support-url\" \"", types::brand_url!(), "\")\r\n" ) .as_bytes() .to_vec(), ), ) .await } pub async fn handle_jmap_access(&mut self, request: Request) -> trc::Result<()> { // Validate access self.assert_has_permission(Permission::ImapCapability)?; let op_start = Instant::now(); trc::event!( Imap(trc::ImapEvent::Capabilities), SpanId = self.session_id, Elapsed = op_start.elapsed() ); let mut response = b"* JMAPACCESS ".to_vec(); quoted_string( &mut response, &format!( "{}/.well-known/jmap", self.server.core.network.http.url_https ), ); response.extend_from_slice(b"\r\n"); self.write_bytes( StatusResponse::completed(Command::GetJmapAccess) .with_tag(request.tag) .serialize(response), ) .await } }