Microservice to bring 2FA to self hosted PDSes
1use anyhow::Context;
2use lettre::{AsyncSendmailTransport, AsyncSmtpTransport, AsyncTransport, Message, Tokio1Executor};
3use std::env;
4use url::Url;
5
6pub enum Mailer {
7 Smtp(AsyncSmtpTransport<Tokio1Executor>),
8 Sendmail(AsyncSendmailTransport<Tokio1Executor>),
9}
10
11impl Mailer {
12 pub async fn send(&self, msg: Message) -> anyhow::Result<()> {
13 match self {
14 Mailer::Smtp(m) => {
15 m.send(msg).await.context("SMTP send failed")?;
16 Ok(())
17 }
18 Mailer::Sendmail(m) => {
19 m.send(msg).await.context("sendmail send failed")?;
20 Ok(())
21 }
22 }
23 }
24}
25
26pub fn build_mailer_from_env() -> anyhow::Result<Mailer> {
27 let raw = env::var("PDS_EMAIL_SMTP_URL")
28 .context("PDS_EMAIL_SMTP_URL is not set in your pds.env file")?;
29
30 let url = Url::parse(&raw).context("PDS_EMAIL_SMTP_URL is not a valid URL")?;
31
32 let use_sendmail = url.scheme() == "sendmail"
33 || url
34 .query_pairs()
35 .any(|(k, v)| k == "sendmail" && v == "true");
36
37 if use_sendmail {
38 Ok(Mailer::Sendmail(
39 AsyncSendmailTransport::<Tokio1Executor>::new(),
40 ))
41 } else {
42 Ok(Mailer::Smtp(
43 AsyncSmtpTransport::<Tokio1Executor>::from_url(raw.as_str())?.build(),
44 ))
45 }
46}