Skip to main content

braze_sync/resource/
email_template.rs

1//! Email Template domain type. See IMPLEMENTATION.md §6.4.
2//!
3//! `body_plaintext` is always present (`String`, not `Option<String>`); the
4//! empty string is the legitimate value for HTML-only templates. This is a
5//! deliberate decision recorded in §17.
6
7use serde::{Deserialize, Serialize};
8
9#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
10pub struct EmailTemplate {
11    pub name: String,
12    pub subject: String,
13    /// HTML body (may contain Liquid; treated as opaque text in v1.0).
14    pub body_html: String,
15    /// Plaintext fallback. Empty string allowed; field always present.
16    #[serde(default)]
17    pub body_plaintext: String,
18    #[serde(default, skip_serializing_if = "Option::is_none")]
19    pub from_address: Option<String>,
20    #[serde(default, skip_serializing_if = "Option::is_none")]
21    pub from_display_name: Option<String>,
22    #[serde(default, skip_serializing_if = "Option::is_none")]
23    pub reply_to: Option<String>,
24    #[serde(default, skip_serializing_if = "Option::is_none")]
25    pub preheader: Option<String>,
26    #[serde(default)]
27    pub tags: Vec<String>,
28}
29
30#[cfg(test)]
31mod tests {
32    use super::*;
33
34    #[test]
35    fn email_template_yaml_roundtrip() {
36        let t = EmailTemplate {
37            name: "welcome".into(),
38            subject: "Welcome".into(),
39            body_html: "<p>hi</p>".into(),
40            body_plaintext: "hi".into(),
41            from_address: Some("noreply@example.com".into()),
42            from_display_name: Some("Example".into()),
43            reply_to: None,
44            preheader: Some("Get started".into()),
45            tags: vec!["onboarding".into()],
46        };
47        let yaml = serde_yml::to_string(&t).unwrap();
48        let parsed: EmailTemplate = serde_yml::from_str(&yaml).unwrap();
49        assert_eq!(t, parsed);
50    }
51
52    #[test]
53    fn empty_plaintext_is_valid() {
54        let t = EmailTemplate {
55            name: "html_only".into(),
56            subject: "x".into(),
57            body_html: "<p>x</p>".into(),
58            body_plaintext: String::new(),
59            from_address: None,
60            from_display_name: None,
61            reply_to: None,
62            preheader: None,
63            tags: vec![],
64        };
65        let yaml = serde_yml::to_string(&t).unwrap();
66        let parsed: EmailTemplate = serde_yml::from_str(&yaml).unwrap();
67        assert_eq!(parsed.body_plaintext, "");
68    }
69}