use std::ops::{Deref, DerefMut};
use anyhow::{Result, anyhow};
use io_msgraph::v1::client::{MsgraphClientStd as Inner, MsgraphClientStdConnectOptions};
use pimalaya_config::secret::SecretResolver;
use secrecy::{ExposeSecret, SecretString};
use crate::{
account::context::Account,
config::{AccountConfig, Config, MsgraphAuthConfig, MsgraphConfig, ProxyConfig},
email::mailbox::{MailboxIndex, MailboxRole},
};
pub struct MsgraphClient {
inner: Inner,
folder_index: Option<MailboxIndex>,
}
impl MsgraphClient {
pub fn new(config: MsgraphConfig) -> Result<Self> {
let mut resolver = SecretResolver::new();
let token = msgraph_token(config.auth, &mut resolver)?;
let options = MsgraphClientStdConnectOptions {
tls: config.tls.into_tls(config.alpn),
proxy: ProxyConfig::resolve(config.proxy, &mut resolver)?,
user_id: config.user_id,
};
let inner = Inner::connect(token.expose_secret(), options)?;
Ok(Self {
inner,
folder_index: None,
})
}
pub fn resolve_mailbox_id(&mut self, mailbox: &str) -> Result<String> {
self.folder_index()?.resolve(mailbox)
}
pub fn role_mailbox_id(&mut self, role: &MailboxRole) -> Result<Option<String>> {
self.folder_index()?.with_role(role)
}
fn folder_index(&mut self) -> Result<&MailboxIndex> {
if self.folder_index.is_none() {
let folders = self.list_mailboxes(false)?;
self.folder_index = Some(MailboxIndex(folders));
}
Ok(self.folder_index.get_or_insert_default())
}
}
impl Deref for MsgraphClient {
type Target = Inner;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl DerefMut for MsgraphClient {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.inner
}
}
pub fn build_msgraph_client(
config: Config,
name: String,
mut account_config: AccountConfig,
) -> Result<(Account, MsgraphClient)> {
let msgraph_config = account_config
.msgraph
.take()
.ok_or_else(|| anyhow!("Microsoft Graph config is missing for account `{name}`"))?;
let account = Account::from(config).merge(Account::from(account_config));
let client = MsgraphClient::new(msgraph_config)?;
Ok((account, client))
}
pub fn msgraph_token(
config: MsgraphAuthConfig,
resolver: &mut SecretResolver,
) -> Result<SecretString> {
Ok(resolver.resolve(config.token)?)
}