hagrid-keyserver--hagrid/src/mail.rs

143 lines
3.6 KiB
Rust
Raw Normal View History

use std::path::PathBuf;
2018-12-25 19:06:28 +00:00
use handlebars::Handlebars;
use lettre::{EmailTransport, SendmailTransport, FileEmailTransport};
use lettre_email::EmailBuilder;
use serde::Serialize;
use sequoia_openpgp as openpgp;
use database::types::Email;
2019-02-07 19:58:31 +00:00
use Result;
mod context {
#[derive(Serialize, Clone)]
pub struct Verification {
pub primary_fp: String,
pub token: String,
pub userid: String,
pub domain: String,
}
#[derive(Serialize, Clone)]
pub struct Deletion {
pub token: String,
pub domain: String,
}
}
pub struct Service {
from: String,
templates: Handlebars,
transport: Transport,
}
enum Transport {
Sendmail,
Filemail(PathBuf),
}
impl Service {
/// Sends mail via sendmail.
pub fn sendmail(from: String, templates: Handlebars) -> Self {
Self {
from: from,
templates: templates,
transport: Transport::Sendmail,
2019-02-07 19:58:31 +00:00
}
}
/// Sends mail by storing it in the given directory.
pub fn filemail(from: String, templates: Handlebars, path: PathBuf)
-> Self
{
Self {
from: from,
templates: templates,
transport: Transport::Filemail(path),
}
}
pub fn send_verification(&self, tpk: &openpgp::TPK, userid: &Email,
token: &str, domain: &str)
-> Result<()> {
let ctx = context::Verification {
primary_fp: tpk.fingerprint().to_string(),
token: token.to_string(),
userid: userid.to_string(),
domain: domain.to_string(),
};
2018-12-25 19:06:28 +00:00
self.send(
&vec![userid.clone()],
"Please verify your email address",
"verify",
ctx,
2019-02-07 19:58:31 +00:00
)
}
pub fn send_confirmation(&self, userids: &[Email], token: &str,
domain: &str)
-> Result<()> {
let ctx = context::Deletion {
token: token.to_string(),
domain: domain.to_string(),
};
self.send(
userids,
"Please confirm deletion of your key",
"confirm",
ctx,
)
}
fn send<T>(&self, to: &[Email], subject: &str, template: &str, ctx: T)
-> 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)
}
};
let mut email = EmailBuilder::new()
.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"))?,
);
for recipient in to.iter() {
email.add_to(recipient.to_string());
}
let email = email
.build()
.unwrap();
match self.transport {
Transport::Sendmail => {
let mut transport = SendmailTransport::new();
transport.send(&email)?;
},
Transport::Filemail(ref path) => {
let mut transport = FileEmailTransport::new(path);
transport.send(&email)?;
},
}
Ok(())
}
}