2019-03-04 16:57:36 +00:00
|
|
|
use std::path::PathBuf;
|
|
|
|
|
2019-03-13 09:32:21 +00:00
|
|
|
use failure;
|
2018-12-25 19:06:28 +00:00
|
|
|
use handlebars::Handlebars;
|
2019-03-04 16:57:36 +00:00
|
|
|
use lettre::{EmailTransport, SendmailTransport, FileEmailTransport};
|
2018-11-02 10:50:57 +00:00
|
|
|
use lettre_email::EmailBuilder;
|
2019-03-13 09:32:21 +00:00
|
|
|
use url;
|
2018-11-02 10:50:57 +00:00
|
|
|
use serde::Serialize;
|
|
|
|
|
2019-03-05 16:30:56 +00:00
|
|
|
use database::types::Email;
|
2019-02-07 19:58:31 +00:00
|
|
|
use Result;
|
2018-11-02 10:50:57 +00:00
|
|
|
|
2019-03-11 15:34:18 +00:00
|
|
|
mod context {
|
|
|
|
#[derive(Serialize, Clone)]
|
|
|
|
pub struct Verification {
|
2019-03-11 16:02:45 +00:00
|
|
|
pub primary_fp: String,
|
2019-03-12 15:52:46 +00:00
|
|
|
pub uri: String,
|
2019-03-11 15:34:18 +00:00
|
|
|
pub userid: String,
|
2019-03-13 09:32:21 +00:00
|
|
|
pub base_uri: String,
|
2019-03-11 15:34:18 +00:00
|
|
|
pub domain: String,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Serialize, Clone)]
|
2019-04-05 15:07:40 +00:00
|
|
|
pub struct Manage {
|
2019-03-12 15:52:46 +00:00
|
|
|
pub uri: String,
|
2019-03-13 09:32:21 +00:00
|
|
|
pub base_uri: String,
|
2019-03-11 15:34:18 +00:00
|
|
|
pub domain: String,
|
|
|
|
}
|
2018-11-02 10:50:57 +00:00
|
|
|
}
|
|
|
|
|
2019-03-04 15:43:10 +00:00
|
|
|
pub struct Service {
|
|
|
|
from: String,
|
2019-03-13 09:32:21 +00:00
|
|
|
base_uri: String,
|
2019-03-13 08:56:33 +00:00
|
|
|
domain: String,
|
2019-03-04 15:43:10 +00:00
|
|
|
templates: Handlebars,
|
|
|
|
transport: Transport,
|
|
|
|
}
|
|
|
|
|
|
|
|
enum Transport {
|
|
|
|
Sendmail,
|
2019-03-04 16:57:36 +00:00
|
|
|
Filemail(PathBuf),
|
2019-03-04 15:43:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Service {
|
|
|
|
/// Sends mail via sendmail.
|
2019-03-13 09:32:21 +00:00
|
|
|
pub fn sendmail(from: String, base_uri: String, templates: Handlebars)
|
|
|
|
-> Result<Self> {
|
|
|
|
Self::new(from, base_uri, templates, Transport::Sendmail)
|
2019-03-04 15:43:10 +00:00
|
|
|
}
|
|
|
|
|
2019-03-04 16:57:36 +00:00
|
|
|
/// Sends mail by storing it in the given directory.
|
2019-03-13 09:32:21 +00:00
|
|
|
pub fn filemail(from: String, base_uri: String, templates: Handlebars,
|
2019-03-13 08:56:33 +00:00
|
|
|
path: PathBuf)
|
2019-03-13 09:32:21 +00:00
|
|
|
-> Result<Self> {
|
|
|
|
Self::new(from, base_uri, templates, Transport::Filemail(path))
|
|
|
|
}
|
|
|
|
|
|
|
|
fn new(from: String, base_uri: String, templates: Handlebars,
|
|
|
|
transport: Transport)
|
|
|
|
-> Result<Self> {
|
|
|
|
let domain =
|
|
|
|
url::Url::parse(&base_uri)
|
|
|
|
?.host_str().ok_or_else(|| failure::err_msg("No host in base-URI"))
|
|
|
|
?.to_string();
|
|
|
|
Ok(Self {
|
2019-03-04 16:57:36 +00:00
|
|
|
from: from,
|
2019-03-13 09:32:21 +00:00
|
|
|
base_uri: base_uri,
|
2019-03-13 08:56:33 +00:00
|
|
|
domain: domain,
|
2019-03-04 16:57:36 +00:00
|
|
|
templates: templates,
|
2019-03-13 09:32:21 +00:00
|
|
|
transport: transport,
|
|
|
|
})
|
2019-03-04 16:57:36 +00:00
|
|
|
}
|
|
|
|
|
2019-04-27 22:05:49 +00:00
|
|
|
pub fn send_verification(&self, tpk_name: String, userid: &Email,
|
2019-03-13 08:56:33 +00:00
|
|
|
token: &str)
|
2019-03-04 15:43:10 +00:00
|
|
|
-> Result<()> {
|
2019-03-11 15:34:18 +00:00
|
|
|
let ctx = context::Verification {
|
2019-04-27 22:05:49 +00:00
|
|
|
primary_fp: tpk_name,
|
2019-03-13 09:32:21 +00:00
|
|
|
uri: format!("{}/publish/{}", self.base_uri, token),
|
2019-03-11 15:34:18 +00:00
|
|
|
userid: userid.to_string(),
|
2019-03-13 09:32:21 +00:00
|
|
|
base_uri: self.base_uri.clone(),
|
2019-03-13 08:56:33 +00:00
|
|
|
domain: self.domain.clone(),
|
2019-03-04 15:43:10 +00:00
|
|
|
};
|
2018-12-25 19:06:28 +00:00
|
|
|
|
2019-03-04 15:43:10 +00:00
|
|
|
self.send(
|
2019-03-05 13:09:23 +00:00
|
|
|
&vec![userid.clone()],
|
2019-03-04 15:43:10 +00:00
|
|
|
"Please verify your email address",
|
|
|
|
"verify",
|
|
|
|
ctx,
|
2019-02-07 19:58:31 +00:00
|
|
|
)
|
2019-03-04 15:43:10 +00:00
|
|
|
}
|
2018-11-02 10:50:57 +00:00
|
|
|
|
2019-04-05 15:07:40 +00:00
|
|
|
pub fn send_manage_token(&self, recipients: &[Email], uri: &str)
|
|
|
|
-> Result<()> {
|
|
|
|
let ctx = context::Manage {
|
|
|
|
uri: uri.to_string(),
|
|
|
|
base_uri: self.base_uri.clone(),
|
|
|
|
domain: self.domain.clone(),
|
|
|
|
};
|
|
|
|
|
|
|
|
self.send(
|
|
|
|
recipients,
|
|
|
|
&format!("{}: Manage your key", &self.domain),
|
|
|
|
"manage",
|
|
|
|
ctx,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
|
2019-03-05 13:09:23 +00:00
|
|
|
fn send<T>(&self, to: &[Email], subject: &str, template: &str, ctx: T)
|
2019-03-04 15:43:10 +00:00
|
|
|
-> Result<()>
|
|
|
|
where T: Serialize + Clone,
|
|
|
|
{
|
|
|
|
let tmpl_html = format!("{}-html", template);
|
|
|
|
let tmpl_txt = format!("{}-txt", template);
|
|
|
|
let (html, txt) = {
|
|
|
|
if let (Ok(inner_html), Ok(inner_txt)) = (
|
|
|
|
self.templates.render(&tmpl_html, &ctx),
|
|
|
|
self.templates.render(&tmpl_txt, &ctx),
|
|
|
|
) {
|
|
|
|
(Some(inner_html), Some(inner_txt))
|
|
|
|
} else {
|
|
|
|
(None, None)
|
|
|
|
}
|
|
|
|
};
|
2018-11-02 10:50:57 +00:00
|
|
|
|
2019-04-05 16:23:59 +00:00
|
|
|
if cfg!(debug_assertions) {
|
|
|
|
for recipient in to.iter() {
|
|
|
|
println!("To: {}", recipient.to_string());
|
|
|
|
}
|
|
|
|
println!("{}", txt.as_ref().unwrap().to_string());
|
|
|
|
}
|
|
|
|
|
2019-03-05 13:09:23 +00:00
|
|
|
let mut email = EmailBuilder::new()
|
2019-03-04 15:43:10 +00:00
|
|
|
.from(self.from.clone())
|
|
|
|
.subject(subject)
|
|
|
|
.alternative(
|
|
|
|
html.ok_or(failure::err_msg("Email template failed to render"))?,
|
|
|
|
txt.ok_or(failure::err_msg("Email template failed to render"))?,
|
2019-03-05 13:09:23 +00:00
|
|
|
);
|
|
|
|
|
|
|
|
for recipient in to.iter() {
|
|
|
|
email.add_to(recipient.to_string());
|
|
|
|
}
|
|
|
|
|
|
|
|
let email = email
|
2019-03-04 15:43:10 +00:00
|
|
|
.build()
|
|
|
|
.unwrap();
|
|
|
|
|
|
|
|
match self.transport {
|
|
|
|
Transport::Sendmail => {
|
|
|
|
let mut transport = SendmailTransport::new();
|
|
|
|
transport.send(&email)?;
|
|
|
|
},
|
2019-03-04 16:57:36 +00:00
|
|
|
Transport::Filemail(ref path) => {
|
|
|
|
let mut transport = FileEmailTransport::new(path);
|
|
|
|
transport.send(&email)?;
|
|
|
|
},
|
2019-03-04 15:43:10 +00:00
|
|
|
}
|
2018-11-02 10:50:57 +00:00
|
|
|
|
2019-03-04 15:43:10 +00:00
|
|
|
Ok(())
|
|
|
|
}
|
2018-11-02 10:50:57 +00:00
|
|
|
}
|