Skip to main content

io_msgraph/v1/rest/users/messages/
get_raw.rs

1//! Get the raw MIME content of a Microsoft Graph message
2//! (`GET /me/messages/{id}/$value`).
3//!
4//! Unlike the other coroutines, the `$value` endpoint returns the raw
5//! RFC 5322 message rather than JSON, so this runs the HTTP send
6//! directly and yields the body bytes.
7//!
8//! <https://learn.microsoft.com/en-us/graph/outlook-get-mime-message>
9
10use alloc::{format, vec::Vec};
11
12use io_http::{
13    coroutine::{HttpCoroutine, HttpCoroutineState},
14    rfc6750::bearer::HttpAuthBearer,
15    rfc9110::{
16        request::HttpRequest,
17        send::{HttpSendOutput, HttpSendYield},
18    },
19    rfc9112::send::Http11Send,
20};
21use log::{debug, trace};
22use url::Url;
23
24use crate::{
25    coroutine::*,
26    v1::send::{MSGRAPH_API_BASE, MsgraphSendError, MsgraphSendOutput, parse_api_error, user_path},
27};
28
29/// Gets the raw RFC 5322 MIME content of a Microsoft Graph message.
30pub struct MsgraphMessageGetRaw {
31    send: Http11Send,
32}
33
34impl MsgraphMessageGetRaw {
35    /// Gets the raw MIME content of the message `id`.
36    pub fn new(auth: &HttpAuthBearer, user_id: &str, id: &str) -> Result<Self, MsgraphSendError> {
37        debug!("prepare microsoft graph message raw retrieval");
38        trace!("id: {id:?}");
39
40        let user = user_path(user_id);
41        let url = Url::parse(MSGRAPH_API_BASE)?.join(&format!("{user}/messages/{id}/$value"))?;
42
43        let request = HttpRequest::get(url.clone())
44            .header("Authorization", auth.to_authorization())
45            .body(Vec::new());
46
47        Ok(Self {
48            send: Http11Send::new(request),
49        })
50    }
51}
52
53impl MsgraphCoroutine for MsgraphMessageGetRaw {
54    type Yield = MsgraphYield;
55    type Return = Result<MsgraphSendOutput<Vec<u8>>, MsgraphSendError>;
56
57    fn resume(&mut self, arg: Option<&[u8]>) -> MsgraphCoroutineState<Self::Yield, Self::Return> {
58        match self.send.resume(arg) {
59            HttpCoroutineState::Yielded(HttpSendYield::WantsRead) => {
60                MsgraphCoroutineState::Yielded(MsgraphYield::WantsRead)
61            }
62            HttpCoroutineState::Yielded(HttpSendYield::WantsWrite(bytes)) => {
63                MsgraphCoroutineState::Yielded(MsgraphYield::WantsWrite(bytes))
64            }
65            HttpCoroutineState::Yielded(HttpSendYield::WantsRedirect { .. }) => {
66                MsgraphCoroutineState::Complete(Err(MsgraphSendError::UnexpectedRedirect))
67            }
68            HttpCoroutineState::Complete(Err(err)) => {
69                MsgraphCoroutineState::Complete(Err(err.into()))
70            }
71            HttpCoroutineState::Complete(Ok(HttpSendOutput {
72                response,
73                keep_alive,
74                ..
75            })) => {
76                if response.status.is_success() {
77                    debug!("message raw retrieved");
78                    MsgraphCoroutineState::Complete(Ok(MsgraphSendOutput {
79                        response: response.body,
80                        keep_alive,
81                    }))
82                } else {
83                    let (status, code, message) = parse_api_error(*response.status, &response.body);
84                    MsgraphCoroutineState::Complete(Err(MsgraphSendError::Api {
85                        status,
86                        code,
87                        message,
88                    }))
89                }
90            }
91        }
92    }
93}