#[cfg(any(
feature = "rustls-aws",
feature = "rustls-ring",
feature = "native-tls"
))]
use core::time::Duration;
use core::{any::Any, fmt};
use alloc::{
boxed::Box,
string::{String, ToString},
vec::Vec,
};
use std::io::{self, Read, Write};
use io_http::rfc6750::bearer::HttpAuthBearer;
#[cfg(any(
feature = "rustls-aws",
feature = "rustls-ring",
feature = "native-tls"
))]
use pimalaya_stream::std::stream::StreamStd;
#[cfg(any(
feature = "rustls-aws",
feature = "rustls-ring",
feature = "native-tls"
))]
pub use pimalaya_stream::tls::*;
use thiserror::Error;
#[cfg(any(
feature = "rustls-aws",
feature = "rustls-ring",
feature = "native-tls"
))]
use url::Url;
#[cfg(any(
feature = "rustls-aws",
feature = "rustls-ring",
feature = "native-tls"
))]
use crate::v1::send::MSGRAPH_API_BASE;
use crate::{
coroutine::*,
v1::rest::users::{
MsgraphUser,
contact_folders::{
MsgraphContactFolder,
child_folders::MsgraphContactChildFoldersList,
create::MsgraphContactFolderCreate,
delete::MsgraphContactFolderDelete,
get::MsgraphContactFolderGet,
list::{
MsgraphContactFoldersList, MsgraphContactFoldersListParams,
MsgraphContactFoldersListResponse,
},
update::MsgraphContactFolderUpdate,
},
contacts::{
MsgraphContact,
create::MsgraphContactCreate,
delete::MsgraphContactDelete,
delta::{MsgraphContactsDelta, MsgraphContactsDeltaResponse},
get::MsgraphContactGet,
list::{MsgraphContactsList, MsgraphContactsListParams, MsgraphContactsListResponse},
update::MsgraphContactUpdate,
},
get::MsgraphUserGet,
mail_folders::{
MsgraphMailFolder,
child_folders::MsgraphMailChildFoldersList,
copy::MsgraphMailFolderCopy,
create::MsgraphMailFolderCreate,
delete::MsgraphMailFolderDelete,
get::MsgraphMailFolderGet,
list::{
MsgraphMailFoldersList, MsgraphMailFoldersListParams,
MsgraphMailFoldersListResponse,
},
r#move::MsgraphMailFolderMove,
update::MsgraphMailFolderUpdate,
},
messages::{
MsgraphMessage,
attachments::{
MsgraphAttachment,
create::MsgraphAttachmentCreate,
delete::MsgraphAttachmentDelete,
get_raw::MsgraphAttachmentGetRaw,
list::{MsgraphAttachmentsList, MsgraphAttachmentsListResponse},
},
copy::MsgraphMessageCopy,
create::MsgraphMessageCreate,
create_mime::MsgraphMessageCreateMime,
delete::MsgraphMessageDelete,
delta::{MsgraphMessagesDelta, MsgraphMessagesDeltaResponse},
get::MsgraphMessageGet,
get_raw::MsgraphMessageGetRaw,
list::{MsgraphMessagesList, MsgraphMessagesListParams, MsgraphMessagesListResponse},
r#move::MsgraphMessageMove,
send::MsgraphMessageSend,
update::MsgraphMessageUpdate,
},
send_mail::{MsgraphMailSend, MsgraphMailSendMime},
},
v1::send::{MsgraphNoResponse, MsgraphSendError, MsgraphSendOutput},
};
#[derive(Debug, Error)]
pub enum MsgraphClientStdError {
#[error(transparent)]
Send(#[from] MsgraphSendError),
#[error(transparent)]
Io(#[from] io::Error),
#[cfg(any(
feature = "rustls-aws",
feature = "rustls-ring",
feature = "native-tls"
))]
#[error(transparent)]
Tls(#[from] anyhow::Error),
#[cfg(any(
feature = "rustls-aws",
feature = "rustls-ring",
feature = "native-tls"
))]
#[error("Microsoft Graph URL `{0}` has no host")]
UrlMissingHost(String),
#[cfg(any(
feature = "rustls-aws",
feature = "rustls-ring",
feature = "native-tls"
))]
#[error(
"Microsoft Graph URL `{url}` has unsupported scheme `{scheme}` (expected `http` or `https`)"
)]
UrlUnsupportedScheme {
url: String,
scheme: String,
},
}
pub struct MsgraphClientStdConnectOptions {
#[cfg(any(
feature = "rustls-aws",
feature = "rustls-ring",
feature = "native-tls"
))]
pub tls: Tls,
pub user_id: String,
}
impl Default for MsgraphClientStdConnectOptions {
fn default() -> Self {
Self {
#[cfg(any(
feature = "rustls-aws",
feature = "rustls-ring",
feature = "native-tls"
))]
tls: Tls::default(),
user_id: String::from("me"),
}
}
}
const READ_BUFFER_SIZE: usize = 16 * 1024;
pub struct MsgraphClientStd {
pub stream: Box<dyn MsgraphStream>,
pub auth: HttpAuthBearer,
pub user_id: String,
}
impl MsgraphClientStd {
pub fn new<S: Read + Write + Send + 'static>(
stream: S,
token: impl ToString,
options: MsgraphClientStdConnectOptions,
) -> Self {
Self {
stream: Box::new(stream),
auth: HttpAuthBearer::new(token.to_string()),
user_id: options.user_id,
}
}
#[cfg(any(
feature = "rustls-aws",
feature = "rustls-ring",
feature = "native-tls"
))]
pub fn connect(
token: impl ToString,
options: MsgraphClientStdConnectOptions,
) -> Result<Self, MsgraphClientStdError> {
let MsgraphClientStdConnectOptions { tls, user_id } = options;
let url = Url::parse(MSGRAPH_API_BASE).expect("Microsoft Graph API base URL is valid");
let host = url
.host_str()
.ok_or_else(|| MsgraphClientStdError::UrlMissingHost(url.to_string()))?;
let stream = match url.scheme() {
"http" => StreamStd::connect_tcp(host, url.port().unwrap_or(80))?,
"https" => StreamStd::connect_tls(host, url.port().unwrap_or(443), &tls)?,
scheme => {
return Err(MsgraphClientStdError::UrlUnsupportedScheme {
url: url.to_string(),
scheme: scheme.to_string(),
});
}
};
stream.set_read_timeout(Some(Duration::from_secs(30)))?;
Ok(Self {
stream: Box::new(stream),
auth: HttpAuthBearer::new(token.to_string()),
user_id,
})
}
pub fn set_stream<S: Read + Write + Send + 'static>(&mut self, stream: S) {
self.stream = Box::new(stream);
}
pub fn run<C, T>(
&mut self,
mut coroutine: C,
) -> Result<MsgraphSendOutput<T>, MsgraphClientStdError>
where
C: MsgraphCoroutine<
Yield = MsgraphYield,
Return = Result<MsgraphSendOutput<T>, MsgraphSendError>,
>,
{
let mut buf = [0u8; READ_BUFFER_SIZE];
let mut arg: Option<&[u8]> = None;
loop {
match coroutine.resume(arg.take()) {
MsgraphCoroutineState::Complete(Ok(out)) => return Ok(out),
MsgraphCoroutineState::Complete(Err(err)) => return Err(err.into()),
MsgraphCoroutineState::Yielded(MsgraphYield::WantsRead) => {
let n = self.stream.read(&mut buf)?;
arg = Some(&buf[..n]);
}
MsgraphCoroutineState::Yielded(MsgraphYield::WantsWrite(bytes)) => {
self.stream.write_all(&bytes)?;
arg = None;
}
}
}
}
pub fn me(&mut self) -> Result<MsgraphSendOutput<MsgraphUser>, MsgraphClientStdError> {
let coroutine = MsgraphUserGet::new(&self.auth, &self.user_id)?;
self.run(coroutine)
}
pub fn mail_folders_list(
&mut self,
params: &MsgraphMailFoldersListParams,
) -> Result<MsgraphSendOutput<MsgraphMailFoldersListResponse>, MsgraphClientStdError> {
let coroutine = MsgraphMailFoldersList::new(&self.auth, &self.user_id, params)?;
self.run(coroutine)
}
pub fn mail_folder_get(
&mut self,
id: &str,
) -> Result<MsgraphSendOutput<MsgraphMailFolder>, MsgraphClientStdError> {
let coroutine = MsgraphMailFolderGet::new(&self.auth, &self.user_id, id)?;
self.run(coroutine)
}
pub fn mail_folder_create(
&mut self,
folder: &MsgraphMailFolder,
) -> Result<MsgraphSendOutput<MsgraphMailFolder>, MsgraphClientStdError> {
let coroutine = MsgraphMailFolderCreate::new(&self.auth, &self.user_id, folder)?;
self.run(coroutine)
}
pub fn mail_folder_update(
&mut self,
id: &str,
folder: &MsgraphMailFolder,
) -> Result<MsgraphSendOutput<MsgraphMailFolder>, MsgraphClientStdError> {
let coroutine = MsgraphMailFolderUpdate::new(&self.auth, &self.user_id, id, folder)?;
self.run(coroutine)
}
pub fn mail_folder_delete(
&mut self,
id: &str,
) -> Result<MsgraphSendOutput<MsgraphNoResponse>, MsgraphClientStdError> {
let coroutine = MsgraphMailFolderDelete::new(&self.auth, &self.user_id, id)?;
self.run(coroutine)
}
pub fn mail_folder_copy(
&mut self,
id: &str,
destination: &str,
) -> Result<MsgraphSendOutput<MsgraphMailFolder>, MsgraphClientStdError> {
let coroutine = MsgraphMailFolderCopy::new(&self.auth, &self.user_id, id, destination)?;
self.run(coroutine)
}
pub fn mail_folder_move(
&mut self,
id: &str,
destination: &str,
) -> Result<MsgraphSendOutput<MsgraphMailFolder>, MsgraphClientStdError> {
let coroutine = MsgraphMailFolderMove::new(&self.auth, &self.user_id, id, destination)?;
self.run(coroutine)
}
pub fn mail_child_folders_list(
&mut self,
id: &str,
params: &MsgraphMailFoldersListParams,
) -> Result<MsgraphSendOutput<MsgraphMailFoldersListResponse>, MsgraphClientStdError> {
let coroutine = MsgraphMailChildFoldersList::new(&self.auth, &self.user_id, id, params)?;
self.run(coroutine)
}
pub fn contact_folders_list(
&mut self,
params: &MsgraphContactFoldersListParams,
) -> Result<MsgraphSendOutput<MsgraphContactFoldersListResponse>, MsgraphClientStdError> {
let coroutine = MsgraphContactFoldersList::new(&self.auth, &self.user_id, params)?;
self.run(coroutine)
}
pub fn contact_folder_get(
&mut self,
id: &str,
) -> Result<MsgraphSendOutput<MsgraphContactFolder>, MsgraphClientStdError> {
let coroutine = MsgraphContactFolderGet::new(&self.auth, &self.user_id, id)?;
self.run(coroutine)
}
pub fn contact_folder_create(
&mut self,
folder: &MsgraphContactFolder,
) -> Result<MsgraphSendOutput<MsgraphContactFolder>, MsgraphClientStdError> {
let coroutine = MsgraphContactFolderCreate::new(&self.auth, &self.user_id, folder)?;
self.run(coroutine)
}
pub fn contact_folder_update(
&mut self,
id: &str,
folder: &MsgraphContactFolder,
) -> Result<MsgraphSendOutput<MsgraphContactFolder>, MsgraphClientStdError> {
let coroutine = MsgraphContactFolderUpdate::new(&self.auth, &self.user_id, id, folder)?;
self.run(coroutine)
}
pub fn contact_folder_delete(
&mut self,
id: &str,
) -> Result<MsgraphSendOutput<MsgraphNoResponse>, MsgraphClientStdError> {
let coroutine = MsgraphContactFolderDelete::new(&self.auth, &self.user_id, id)?;
self.run(coroutine)
}
pub fn contact_child_folders_list(
&mut self,
id: &str,
params: &MsgraphContactFoldersListParams,
) -> Result<MsgraphSendOutput<MsgraphContactFoldersListResponse>, MsgraphClientStdError> {
let coroutine = MsgraphContactChildFoldersList::new(&self.auth, &self.user_id, id, params)?;
self.run(coroutine)
}
pub fn contacts_list(
&mut self,
folder: Option<&str>,
params: &MsgraphContactsListParams,
) -> Result<MsgraphSendOutput<MsgraphContactsListResponse>, MsgraphClientStdError> {
let coroutine = MsgraphContactsList::new(&self.auth, &self.user_id, folder, params)?;
self.run(coroutine)
}
pub fn contact_get(
&mut self,
id: &str,
expand: Option<&str>,
) -> Result<MsgraphSendOutput<MsgraphContact>, MsgraphClientStdError> {
let coroutine = MsgraphContactGet::new(&self.auth, &self.user_id, id, expand)?;
self.run(coroutine)
}
pub fn contact_create(
&mut self,
folder: Option<&str>,
contact: &MsgraphContact,
) -> Result<MsgraphSendOutput<MsgraphContact>, MsgraphClientStdError> {
let coroutine = MsgraphContactCreate::new(&self.auth, &self.user_id, folder, contact)?;
self.run(coroutine)
}
pub fn contact_update(
&mut self,
id: &str,
contact: &MsgraphContact,
) -> Result<MsgraphSendOutput<MsgraphContact>, MsgraphClientStdError> {
let coroutine = MsgraphContactUpdate::new(&self.auth, &self.user_id, id, contact)?;
self.run(coroutine)
}
pub fn contact_delete(
&mut self,
id: &str,
) -> Result<MsgraphSendOutput<MsgraphNoResponse>, MsgraphClientStdError> {
let coroutine = MsgraphContactDelete::new(&self.auth, &self.user_id, id)?;
self.run(coroutine)
}
pub fn contacts_delta(
&mut self,
folder: Option<&str>,
select: Option<&str>,
) -> Result<MsgraphSendOutput<MsgraphContactsDeltaResponse>, MsgraphClientStdError> {
let coroutine = MsgraphContactsDelta::new(&self.auth, &self.user_id, folder, select)?;
self.run(coroutine)
}
pub fn messages_list(
&mut self,
folder: Option<&str>,
params: &MsgraphMessagesListParams,
) -> Result<MsgraphSendOutput<MsgraphMessagesListResponse>, MsgraphClientStdError> {
let coroutine = MsgraphMessagesList::new(&self.auth, &self.user_id, folder, params)?;
self.run(coroutine)
}
pub fn message_get(
&mut self,
id: &str,
) -> Result<MsgraphSendOutput<MsgraphMessage>, MsgraphClientStdError> {
let coroutine = MsgraphMessageGet::new(&self.auth, &self.user_id, id)?;
self.run(coroutine)
}
pub fn message_get_raw(
&mut self,
id: &str,
) -> Result<MsgraphSendOutput<Vec<u8>>, MsgraphClientStdError> {
let coroutine = MsgraphMessageGetRaw::new(&self.auth, &self.user_id, id)?;
self.run(coroutine)
}
pub fn message_create(
&mut self,
folder: Option<&str>,
message: &MsgraphMessage,
) -> Result<MsgraphSendOutput<MsgraphMessage>, MsgraphClientStdError> {
let coroutine = MsgraphMessageCreate::new(&self.auth, &self.user_id, folder, message)?;
self.run(coroutine)
}
pub fn message_create_mime(
&mut self,
folder: Option<&str>,
raw: &[u8],
) -> Result<MsgraphSendOutput<MsgraphMessage>, MsgraphClientStdError> {
let coroutine = MsgraphMessageCreateMime::new(&self.auth, &self.user_id, folder, raw)?;
self.run(coroutine)
}
pub fn message_update(
&mut self,
id: &str,
message: &MsgraphMessage,
) -> Result<MsgraphSendOutput<MsgraphMessage>, MsgraphClientStdError> {
let coroutine = MsgraphMessageUpdate::new(&self.auth, &self.user_id, id, message)?;
self.run(coroutine)
}
pub fn message_delete(
&mut self,
id: &str,
) -> Result<MsgraphSendOutput<MsgraphNoResponse>, MsgraphClientStdError> {
let coroutine = MsgraphMessageDelete::new(&self.auth, &self.user_id, id)?;
self.run(coroutine)
}
pub fn message_move(
&mut self,
id: &str,
destination: &str,
) -> Result<MsgraphSendOutput<MsgraphMessage>, MsgraphClientStdError> {
let coroutine = MsgraphMessageMove::new(&self.auth, &self.user_id, id, destination)?;
self.run(coroutine)
}
pub fn message_copy(
&mut self,
id: &str,
destination: &str,
) -> Result<MsgraphSendOutput<MsgraphMessage>, MsgraphClientStdError> {
let coroutine = MsgraphMessageCopy::new(&self.auth, &self.user_id, id, destination)?;
self.run(coroutine)
}
pub fn messages_delta(
&mut self,
folder: Option<&str>,
select: Option<&str>,
) -> Result<MsgraphSendOutput<MsgraphMessagesDeltaResponse>, MsgraphClientStdError> {
let coroutine = MsgraphMessagesDelta::new(&self.auth, &self.user_id, folder, select)?;
self.run(coroutine)
}
pub fn messages_delta_from_link(
&mut self,
link: &str,
) -> Result<MsgraphSendOutput<MsgraphMessagesDeltaResponse>, MsgraphClientStdError> {
let coroutine = MsgraphMessagesDelta::from_link(&self.auth, link)?;
self.run(coroutine)
}
pub fn attachment_create(
&mut self,
message_id: &str,
name: &str,
content: &[u8],
content_type: Option<&str>,
) -> Result<MsgraphSendOutput<MsgraphAttachment>, MsgraphClientStdError> {
let coroutine = MsgraphAttachmentCreate::new(
&self.auth,
&self.user_id,
message_id,
name,
content,
content_type,
)?;
self.run(coroutine)
}
pub fn attachments_list(
&mut self,
message_id: &str,
) -> Result<MsgraphSendOutput<MsgraphAttachmentsListResponse>, MsgraphClientStdError> {
let coroutine = MsgraphAttachmentsList::new(&self.auth, &self.user_id, message_id)?;
self.run(coroutine)
}
pub fn attachment_get_raw(
&mut self,
message_id: &str,
attachment_id: &str,
) -> Result<MsgraphSendOutput<Vec<u8>>, MsgraphClientStdError> {
let coroutine =
MsgraphAttachmentGetRaw::new(&self.auth, &self.user_id, message_id, attachment_id)?;
self.run(coroutine)
}
pub fn attachment_delete(
&mut self,
message_id: &str,
attachment_id: &str,
) -> Result<MsgraphSendOutput<MsgraphNoResponse>, MsgraphClientStdError> {
let coroutine =
MsgraphAttachmentDelete::new(&self.auth, &self.user_id, message_id, attachment_id)?;
self.run(coroutine)
}
pub fn message_send(
&mut self,
id: &str,
) -> Result<MsgraphSendOutput<MsgraphNoResponse>, MsgraphClientStdError> {
let coroutine = MsgraphMessageSend::new(&self.auth, &self.user_id, id)?;
self.run(coroutine)
}
pub fn mail_send(
&mut self,
message: &MsgraphMessage,
save_to_sent_items: bool,
) -> Result<MsgraphSendOutput<MsgraphNoResponse>, MsgraphClientStdError> {
let coroutine =
MsgraphMailSend::new(&self.auth, &self.user_id, message, save_to_sent_items)?;
self.run(coroutine)
}
pub fn mail_send_mime(
&mut self,
raw: &[u8],
) -> Result<MsgraphSendOutput<MsgraphNoResponse>, MsgraphClientStdError> {
let coroutine = MsgraphMailSendMime::new(&self.auth, &self.user_id, raw)?;
self.run(coroutine)
}
}
impl fmt::Debug for MsgraphClientStd {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("MsgraphClientStd")
.field("auth", &self.auth)
.field("user_id", &self.user_id)
.finish_non_exhaustive()
}
}
pub trait MsgraphStream: Read + Write + Send + Any {
fn as_any_mut(&mut self) -> &mut dyn Any;
}
impl<T: Read + Write + Send + Any> MsgraphStream for T {
fn as_any_mut(&mut self) -> &mut dyn Any {
self
}
}