• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

divviup / divviup-api / 8666760397

12 Apr 2024 07:02PM UTC coverage: 56.289% (+0.2%) from 56.083%
8666760397

Pull #968

github

web-flow
Merge 8c0857084 into a6cdbab81
Pull Request #968: Support for time bucketed fixed size

58 of 86 new or added lines in 8 files covered. (67.44%)

6 existing lines in 5 files now uncovered.

3692 of 6559 relevant lines covered (56.29%)

102.51 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

74.6
/src/clients/postmark_client.rs
1
use crate::{
2
    clients::{ClientConnExt, ClientError},
3
    Config,
4
};
5
use email_address::EmailAddress;
6
use serde::{de::DeserializeOwned, Deserialize, Serialize};
7
use serde_json::{json, Value};
8
use trillium::{async_trait, Conn, KnownHeaderName};
9
use trillium_api::FromConn;
10
use trillium_client::Client;
11

12
#[derive(Debug, Clone)]
13
pub struct PostmarkClient {
14
    client: Client,
15
    email: EmailAddress,
16
}
17

18
#[async_trait]
19
impl FromConn for PostmarkClient {
20
    async fn from_conn(conn: &mut Conn) -> Option<Self> {
×
21
        conn.state().cloned()
×
22
    }
×
23
}
24

25
impl PostmarkClient {
26
    pub fn new(config: &Config) -> Self {
278✔
27
        let client = config
278✔
28
            .client
278✔
29
            .clone()
278✔
30
            .with_base(config.postmark_url.clone())
278✔
31
            .with_default_header("X-Postmark-Server-Token", config.postmark_token.clone())
278✔
32
            .with_default_header(KnownHeaderName::Accept, "application/json");
278✔
33

278✔
34
        Self {
278✔
35
            client,
278✔
36
            email: config.email_address.clone(),
278✔
37
        }
278✔
38
    }
278✔
39

40
    pub async fn send_email(&self, email: Email) -> Result<Value, ClientError> {
×
41
        let mut email = serde_json::to_value(&email)?;
×
42
        email
×
43
            .as_object_mut()
×
44
            .unwrap()
×
45
            .insert("From".into(), self.email.to_string().into());
×
46
        self.post("/email", &email).await
×
47
    }
×
48

49
    pub async fn send_email_template(
2✔
50
        &self,
2✔
51
        to: &str,
2✔
52
        template_name: &str,
2✔
53
        model: &impl Serialize,
2✔
54
        message_id: Option<String>,
2✔
55
    ) -> Result<Value, ClientError> {
2✔
56
        let headers = match message_id {
2✔
57
            Some(m) => json!([{
2✔
58
                "Name": "Message-ID",
2✔
59
                "Value": format!("<{m}@{}>", self.email.domain())
2✔
60
            }]),
2✔
61
            None => json!([]),
×
62
        };
63

64
        self.post(
2✔
65
            "/email/withTemplate",
2✔
66
            &json!({
2✔
67
                "To": to,
2✔
68
                "From": self.email,
2✔
69
                "TemplateAlias": template_name,
2✔
70
                "TemplateModel": model,
2✔
71
                "Headers": headers
2✔
72
            }),
2✔
73
        )
2✔
UNCOV
74
        .await
×
75
    }
2✔
76

77
    // private below here
78

79
    async fn post<T>(&self, path: &str, json: &impl Serialize) -> Result<T, ClientError>
2✔
80
    where
2✔
81
        T: DeserializeOwned,
2✔
82
    {
2✔
83
        self.client
2✔
84
            .post(path)
2✔
85
            .with_json_body(json)?
2✔
86
            .success_or_client_error()
2✔
UNCOV
87
            .await?
×
88
            .response_json()
2✔
89
            .await
×
90
            .map_err(ClientError::from)
2✔
91
    }
2✔
92
}
93

94
#[derive(Serialize, Deserialize, Clone, Debug)]
×
95
#[serde(rename_all = "PascalCase")]
96
pub struct Email {
97
    pub to: String,
98
    pub subject: String,
99
    pub text_body: String,
100
    pub html_body: String,
101
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc