Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add support for mail_settings message field #118

Merged
merged 2 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
329 changes: 329 additions & 0 deletions src/v3/message.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,329 @@
//! Provides types related to [`crate::v3::Message`].
gsquire marked this conversation as resolved.
Show resolved Hide resolved

use serde::Serialize;

/// The settings to use when sending the [`crate::v3::Message`].
/// See the [api docs](https://www.twilio.com/docs/sendgrid/api-reference/mail-send/mail-send#request-body)
/// for details.
#[derive(Default, Serialize)]
pub struct MailSettings {
#[serde(flatten, skip_serializing_if = "Option::is_none")]
bypass_filter_settings: Option<BypassFilterSettings>,

#[serde(skip_serializing_if = "Option::is_none")]
footer: Option<Footer>,

#[serde(skip_serializing_if = "Option::is_none")]
sandbox_mode: Option<SandboxMode>,
}

/// Settings to bypass list suppressions.
///
/// This is structured as an enum because when the `bypass_list_management` field is provided,
/// the other bypass filters (`bypass_spam_management`, `bypass_bounce_management`, and
/// `bypass_unsubscribe_management`) are ignored.
///
/// See: <https://www.twilio.com/docs/sendgrid/ui/sending-email/index-suppressions#bypass-filters-and-v3-mail-send>
#[derive(Serialize)]
#[serde(untagged)]
pub enum BypassFilterSettings {
/// Variant to configure bypassing all list suppressions with the `bypass_list_management` field.
TopLevel(TopLevelBypassFilterSettings),
/// Variant to configure bypassing specific list suppressions with the `bypass_spam_management`,
/// `bypass_bounce_management`, and `bypass_unsubscribe_management` fields.
Granular(GranularBypassFilterSettings),
}

/// Used to configure bypassing all list suppressions with the `bypass_list_management` field.
#[derive(Default, Serialize)]
pub struct TopLevelBypassFilterSettings {
#[serde(default)]
bypass_list_management: BypassListManagement,
}

/// Used for the bypass list management setting.
#[derive(Default, Serialize)]
pub struct BypassListManagement {
enable: bool,
}

/// Used to configure bypassing specific list suppressions with the `bypass_spam_management`,
/// `bypass_bounce_management`, and `bypass_unsubscribe_management` fields.
#[derive(Default, Serialize)]
pub struct GranularBypassFilterSettings {
#[serde(skip_serializing_if = "Option::is_none")]
bypass_spam_management: Option<BypassSpamManagement>,

#[serde(skip_serializing_if = "Option::is_none")]
bypass_bounce_management: Option<BypassBounceManagement>,

#[serde(skip_serializing_if = "Option::is_none")]
bypass_unsubscribe_management: Option<BypassUnsubscribeManagement>,
}

/// Used for the bypass spam management setting.
#[derive(Default, Serialize)]
pub struct BypassSpamManagement {
enable: bool,
}

/// Used for the bypass bounce management setting.
#[derive(Default, Serialize)]
pub struct BypassBounceManagement {
enable: bool,
}

/// Used for the bypass unsubscribe management setting.
#[derive(Default, Serialize)]
pub struct BypassUnsubscribeManagement {
enable: bool,
}

/// Used to provide a footer for the [`crate::v3::Message`].
#[derive(Default, Serialize)]
pub struct Footer {
enable: bool,

#[serde(skip_serializing_if = "Option::is_none")]
text: Option<String>,

#[serde(skip_serializing_if = "Option::is_none")]
html: Option<String>,
}

/// Used for the sandbox mode setting.
#[derive(Default, Serialize)]
pub struct SandboxMode {
enable: bool,
}

impl MailSettings {
/// Create a new default [`MailSettings`] instance.
pub fn new() -> Self {
Default::default()
}

/// Set the bypass filter settings.
pub fn set_bypass_filter_settings(mut self, settings: BypassFilterSettings) -> Self {
self.bypass_filter_settings = Some(settings);
self
}

/// Set the footer setting.
pub fn set_footer(mut self, footer: Footer) -> Self {
self.footer = Some(footer);
self
}

/// Set the sandbox mode setting.
pub fn set_sandbox_mode(mut self, sandbox_mode: SandboxMode) -> Self {
self.sandbox_mode = Some(sandbox_mode);
self
}
}

impl TopLevelBypassFilterSettings {
/// Create a new default [`TopLevelBypassFilterSettings`] instance.
pub fn new() -> Self {
Default::default()
}

/// Set the bypass list management setting.
pub fn set_bypass_list_management(
mut self,
bypass_list_management: BypassListManagement,
) -> Self {
self.bypass_list_management = bypass_list_management;
self
}
}

impl BypassListManagement {
/// Create a new default [`BypassListManagement`] instance.
pub fn new() -> Self {
Default::default()
}

/// Enable or disable the setting
pub fn set_enable(mut self, enable: bool) -> Self {
self.enable = enable;
self
}
}

impl GranularBypassFilterSettings {
/// Create a new default [`GranularBypassFilterSettings`] instance.
pub fn new() -> Self {
Default::default()
}

/// Set the bypass spam management setting.
pub fn set_bypass_spam_management(
gsquire marked this conversation as resolved.
Show resolved Hide resolved
mut self,
bypass_spam_management: BypassSpamManagement,
) -> Self {
self.bypass_spam_management = Some(bypass_spam_management);
self
}

/// Set the bypass bounce management setting.
pub fn set_bypass_bounce_management(
mut self,
bypass_bounce_management: BypassBounceManagement,
) -> Self {
self.bypass_bounce_management = Some(bypass_bounce_management);
self
}

/// Set the bypass unsubscrie management setting.
pub fn set_bypass_unsubscribe_management(
mut self,
bypass_unsubscribe_management: BypassUnsubscribeManagement,
) -> Self {
self.bypass_unsubscribe_management = Some(bypass_unsubscribe_management);
self
}
}

impl BypassSpamManagement {
/// Create a new default [`BypassSpamManagement`] instance.
pub fn new() -> Self {
Default::default()
}

/// Enable or disable the setting
pub fn set_enable(mut self, enable: bool) -> Self {
self.enable = enable;
self
}
}

impl BypassBounceManagement {
/// Create a new default [`BypassBounceManagement`] instance.
pub fn new() -> Self {
Default::default()
}

/// Enable or disable the setting
pub fn set_enable(mut self, enable: bool) -> Self {
self.enable = enable;
self
}
}

impl BypassUnsubscribeManagement {
/// Create a new default [`BypassUnsubscribeManagement`] instance.
pub fn new() -> Self {
Default::default()
}

/// Enable or disable the setting
pub fn set_enable(mut self, enable: bool) -> Self {
self.enable = enable;
self
}
}

impl Footer {
/// Create a new default [`Footer`] instance.
pub fn new() -> Self {
Default::default()
}

/// Enable or disable the footer
pub fn set_enable(mut self, enable: bool) -> Self {
self.enable = enable;
self
}

/// Set the text of the footer.
pub fn set_text(mut self, text: String) -> Self {
self.text = Some(text);
self
}

/// Set the html content of the footer.
pub fn set_html(mut self, html: String) -> Self {
self.html = Some(html);
self
}
}

impl SandboxMode {
/// Create a new default [`SandboxMode`] instance.
pub fn new() -> Self {
Default::default()
}

/// Enable or disable the setting
pub fn set_enable(mut self, enable: bool) -> Self {
self.enable = enable;
self
}
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn mail_settings_empty() {
let settings = MailSettings::default();
let settings_json = serde_json::to_string(&settings).unwrap();
let expected = "{}";
assert_eq!(settings_json, expected);
}

#[test]
fn mail_settings_top_level_bypass_filters() {
let settings =
MailSettings::default().set_bypass_filter_settings(BypassFilterSettings::TopLevel(
TopLevelBypassFilterSettings::new()
.set_bypass_list_management(BypassListManagement::new().set_enable(true)),
));
let settings_json = serde_json::to_string(&settings).unwrap();
let expected = r#"{"bypass_list_management":{"enable":true}}"#;
assert_eq!(settings_json, expected);
}

#[test]
fn mail_settings_granular_bypass_filters() {
let settings =
MailSettings::new().set_bypass_filter_settings(BypassFilterSettings::Granular(
GranularBypassFilterSettings::new()
.set_bypass_unsubscribe_management(
BypassUnsubscribeManagement::new().set_enable(true),
)
.set_bypass_bounce_management(BypassBounceManagement::new().set_enable(true))
.set_bypass_spam_management(BypassSpamManagement::new().set_enable(true)),
));
let settings_json = serde_json::to_string(&settings).unwrap();
let expected = r#"{"bypass_spam_management":{"enable":true},"bypass_bounce_management":{"enable":true},"bypass_unsubscribe_management":{"enable":true}}"#;
assert_eq!(settings_json, expected);
}

#[test]
fn mail_settings_no_bypass_defaults() {
let settings = MailSettings::default()
.set_footer(Default::default())
.set_sandbox_mode(Default::default());
let settings_json = serde_json::to_string(&settings).unwrap();
let expected = r#"{"footer":{"enable":false},"sandbox_mode":{"enable":false}}"#;
assert_eq!(settings_json, expected);
}

#[test]
fn mail_settings_no_bypass() {
let settings = MailSettings::new()
.set_footer(
Footer::new()
.set_enable(true)
.set_html("html".to_string())
.set_text("text".to_string()),
)
.set_sandbox_mode(SandboxMode::new().set_enable(true));
let settings_json = serde_json::to_string(&settings).unwrap();
let expected = r#"{"footer":{"enable":true,"text":"text","html":"html"},"sandbox_mode":{"enable":true}}"#;
assert_eq!(settings_json, expected);
}
}
Loading
Loading