use std::collections::HashMap;
use std::fs::File;
use std::io::Read;
use std::path::Path;
use crate::{SendgridError, SendgridResult};
macro_rules! add_field {
(
$(#[$outer:meta])*
$method:ident << $field:ident: $ty:ty
) => {
$(#[$outer])*
pub fn $method(mut self, data: $ty) -> Mail<'a> {
self.$field.push(data);
self
}
};
(
$(#[$outer:meta])*
$method:ident = $field:ident: $ty:ty
) => {
$(#[$outer])*
pub fn $method(mut self, data: $ty) -> Mail<'a> {
self.$field = data;
self
}
};
(
$(#[$outer:meta])*
$method:ident <- $field:ident: $ty:ty
) => {
$(#[$outer])*
pub fn $method(mut self, id: String, data: $ty) -> Mail<'a> {
self.$field.insert(id, data);
self
}
};
}
#[derive(Debug)]
pub struct Destination<'a> {
pub address: &'a str,
pub name: &'a str,
}
impl<'a> From<(&'a str, &'a str)> for Destination<'a> {
fn from((address, name): (&'a str, &'a str)) -> Self {
Self { address, name }
}
}
#[derive(Debug, Default)]
pub struct Mail<'a> {
pub to: Vec<Destination<'a>>,
pub cc: Vec<&'a str>,
pub bcc: Vec<&'a str>,
pub from: &'a str,
pub subject: &'a str,
pub html: &'a str,
pub text: &'a str,
pub from_name: &'a str,
pub reply_to: &'a str,
pub date: &'a str,
pub attachments: HashMap<String, String>,
pub content: HashMap<String, &'a str>,
pub headers: HashMap<String, &'a str>,
pub x_smtpapi: &'a str,
}
impl<'a> Mail<'a> {
pub fn new() -> Mail<'a> {
Mail::default()
}
add_field!(
add_cc
<< cc: &'a str
);
add_field!(
add_to
<< to: Destination<'a>
);
add_field!(
add_from = from: &'a str
);
add_field!(
add_subject = subject: &'a str
);
add_field!(
add_html = html: &'a str
);
add_field!(
add_text = text: &'a str
);
add_field!(
add_bcc
<< bcc: &'a str
);
add_field!(
add_from_name = from_name: &'a str
);
add_field!(
add_reply_to = reply_to: &'a str
);
add_field!(
add_date = date: &'a str
);
pub fn build(self) -> Mail<'a> {
self
}
pub fn add_attachment<P: AsRef<Path>>(mut self, path: P) -> SendgridResult<Mail<'a>> {
let mut file = File::open(&path)?;
let mut data = String::new();
file.read_to_string(&mut data)?;
if let Some(name) = path.as_ref().to_str() {
self.attachments.insert(String::from(name), data);
} else {
return Err(SendgridError::InvalidFilename);
}
Ok(self)
}
add_field!(
add_content <- content: &'a str
);
add_field!(
add_header <- headers: &'a str
);
pub(crate) fn make_header_string(&mut self) -> SendgridResult<String> {
let string = serde_json::to_string(&self.headers)?;
Ok(string)
}
add_field!(
add_x_smtpapi = x_smtpapi: &'a str
);
}