1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#![allow(clippy::field_reassign_with_default)]
use anyhow::{anyhow, Result};

#[async_trait::async_trait]
pub trait MailOps {
    /// Send a plain text email.
    ///
    /// This is a nicer experience than using `post`.
    async fn send_plain_text(
        &self,
        subject: &str,
        message: &str,
        to: &[String],
        cc: &[String],
        bcc: &[String],
        from: &str,
    ) -> Result<()>;
}

#[async_trait::async_trait]
impl MailOps for crate::mail_send::MailSend {
    /// Send a plain text email.
    ///
    /// This is a nicer experience than using `post`.
    async fn send_plain_text(
        &self,
        subject: &str,
        message: &str,
        tos: &[String],
        ccs: &[String],
        bccs: &[String],
        from: &str,
    ) -> Result<()> {
        let mut mail = crate::types::PostMailSendRequest {
            subject: subject.to_string(),
            from: crate::types::FromEmailObject {
                email: from.to_string(),
                name: String::new(),
            },
            content: vec![crate::types::Content {
                value: message.to_string(),
                type_: "text/plain".to_string(),
            }],
            ..Default::default()
        };
        let mut p = crate::types::Personalizations {
            from: Some(mail.from.clone()),
            ..Default::default()
        };
        for to in tos {
            p.to.push(crate::types::ReplyTo {
                email: to.to_string(),
                name: String::new(),
            });
        }
        for cc in ccs {
            p.cc.push(crate::types::CcBccEmailObject {
                email: cc.to_string(),
                name: String::new(),
            });
        }
        for bcc in bccs {
            p.bcc.push(crate::types::CcBccEmailObject {
                email: bcc.to_string(),
                name: String::new(),
            });
        }
        mail.personalizations = vec![p];

        let url = self.client.url("/mail/send", None);
        let resp = self
            .client
            .request_raw(
                reqwest::Method::POST,
                &url,
                crate::Message {
                    body: Some(reqwest::Body::from(serde_json::to_vec(&mail).unwrap())),
                    content_type: None,
                },
            )
            .await?;

        match resp.status() {
            http::StatusCode::ACCEPTED => Ok(()),
            s => Err(anyhow!("received response status: {:?}", s)),
        }
    }
}