use crate::error::Error;
use crate::mailbox::{Mailbox, MailboxData};
use crate::message::{MessageData, MessagePreviewData};
use bytes::Bytes;
use futures::{Stream, TryStreamExt};
use jiff::Timestamp;
use reqwest::header::{HeaderMap, HeaderValue};
use reqwest::{ClientBuilder, header};
use serde::Deserialize;
use std::time::Duration;
#[derive(Clone, Debug)]
pub struct Client {
client: reqwest::Client,
}
impl Client {
pub fn new() -> Self {
Self::default()
}
pub async fn create_mailbox(&self) -> Result<Mailbox<'_>, Error> {
let response = self
.client
.post("https://mob2.temp-mail.org/mailbox")
.send()
.await?
.error_for_status()?;
let data = response.json::<MailboxData>().await?;
Ok(Mailbox::new(self, data))
}
pub(crate) async fn list_mailbox_messages(
&self,
token: &str,
after: Option<Timestamp>,
) -> Result<Vec<MessagePreviewData>, Error> {
let mut builder = self
.client
.get("https://mob2.temp-mail.org/messages")
.header(header::AUTHORIZATION, self.authorization_header(token)?);
if let Some(after) = after {
builder = builder.query(&[("after", after.as_second())]);
}
let response = builder
.send()
.await?
.error_for_status()?
.json::<ListMessagesResponse>()
.await?;
Ok(response.messages)
}
pub(crate) async fn get_message(
&self,
token: &str,
message_id: &str,
) -> Result<MessageData, Error> {
let response = self
.client
.get(format!("https://mob2.temp-mail.org/messages/{message_id}"))
.header(header::AUTHORIZATION, self.authorization_header(token)?)
.send()
.await?
.error_for_status()?;
Ok(response.json().await?)
}
pub(crate) async fn get_attachment(
&self,
token: &str,
message_id: &str,
attachment_id: u32,
) -> Result<impl Stream<Item = Result<Bytes, Error>>, Error> {
let response = self
.client
.get(format!(
"https://mob2.temp-mail.org/messages/{message_id}/attachment/{attachment_id}"
))
.header(header::AUTHORIZATION, self.authorization_header(token)?)
.send()
.await?
.error_for_status()?;
let bytes_stream = response.bytes_stream();
Ok(bytes_stream.map_err(Error::from).into_stream())
}
fn authorization_header(&self, token: &str) -> Result<HeaderValue, Error> {
HeaderValue::from_str(token).map_err(|_| Error::NonAsciiMailboxToken(String::from(token)))
}
}
impl Default for Client {
fn default() -> Self {
let mut headers = HeaderMap::new();
headers.insert(header::ACCEPT, HeaderValue::from_static("application/json"));
Self {
client: ClientBuilder::new()
.user_agent("4.09")
.default_headers(headers)
.referer(false)
.read_timeout(Duration::new(5, 0))
.build()
.expect("failed to create reqwest client"),
}
}
}
impl From<reqwest::Client> for Client {
fn from(client: reqwest::Client) -> Self {
Self { client }
}
}
#[derive(Clone, Eq, PartialEq, Hash, Debug, Deserialize)]
struct ListMessagesResponse {
mailbox: String,
messages: Vec<MessagePreviewData>,
}