use base64::prelude::*;
use serde::{Deserialize, Serialize, Serializer};
use std::collections::HashMap;
fn as_base64<T, S>(data: &T, serializer: S) -> Result<S::Ok, S::Error>
where
T: AsRef<[u8]>,
S: Serializer,
{
serializer.serialize_str(&BASE64_STANDARD.encode(data.as_ref()))
}
#[derive(Serialize, Debug)]
pub enum TrackLinks {
None,
HtmlTAndText,
HtmlOnly,
TextOnly,
}
#[derive(Serialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct EmailHeader {
pub name: String,
pub value: String,
}
#[derive(Serialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct Attachment {
pub name: String,
#[serde(serialize_with = "as_base64")]
pub content: Vec<u8>,
pub content_type: String,
}
#[derive(Serialize, Debug)]
#[serde(untagged)]
pub enum EmailBody {
#[serde(rename = "TextBody")]
Text(String),
#[serde(rename = "HtmlBody")]
Html(String),
HtmlAndText {
#[serde(rename = "TextBody")]
text: String,
#[serde(rename = "HtmlBody")]
html: String,
},
}
#[derive(Serialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct Email {
pub from: String,
pub to: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub cc: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bcc: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subject: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tag: Option<String>,
#[serde(flatten)]
pub body: EmailBody,
#[serde(skip_serializing_if = "Option::is_none")]
pub reply_to: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub headers: Option<Vec<EmailHeader>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub track_opens: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub track_links: Option<TrackLinks>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub attachments: Option<Vec<Attachment>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub message_stream: Option<String>,
}
impl Email {
pub fn new(from: String, to: String, body: EmailBody) -> Email {
Email {
from,
to,
cc: None,
bcc: None,
subject: None,
tag: None,
body,
reply_to: None,
headers: None,
track_opens: None,
track_links: None,
metadata: None,
attachments: None,
message_stream: None,
}
}
}
#[derive(Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct EmailResponse {
pub to: String,
pub submitted_at: String,
#[serde(rename = "MessageID")]
pub message_id: String,
pub error_code: i32,
pub message: String,
}
#[derive(Serialize, Debug)]
pub enum TemplateToUse {
#[serde(rename = "TemplateId")]
Id(String),
#[serde(rename = "TemplateAlias")]
Alias(String),
}
#[derive(Serialize, Debug)]
#[serde(rename_all = "PascalCase")]
pub struct TemplatedEmail<M>
where
M: Serialize,
{
#[serde(flatten)]
pub template: TemplateToUse,
pub template_model: M,
#[serde(skip_serializing_if = "Option::is_none")]
pub inline_css: Option<bool>,
pub from: String,
pub to: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub cc: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub bcc: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tag: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub reply_to: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub headers: Option<Vec<EmailHeader>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub track_opens: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub track_links: Option<TrackLinks>,
#[serde(skip_serializing_if = "Option::is_none")]
pub metadata: Option<HashMap<String, String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub attachments: Option<Vec<Attachment>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub message_stream: Option<String>,
}
impl<M> TemplatedEmail<M>
where
M: Serialize,
{
pub fn new(from: String, to: String, template: TemplateToUse, model: M) -> TemplatedEmail<M> {
TemplatedEmail {
template,
template_model: model,
inline_css: None,
from,
to,
cc: None,
bcc: None,
tag: None,
reply_to: None,
headers: None,
track_opens: None,
track_links: None,
metadata: None,
attachments: None,
message_stream: None,
}
}
}
#[derive(Debug, Deserialize)]
#[serde(rename_all = "PascalCase")]
pub struct APIError {
pub error_code: String,
pub message: String,
}