1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
use std::time::Duration;
use lettre::{
message::Mailbox,
transport::smtp::client::{Tls, TlsParameters},
AsyncSmtpTransport, Message, Tokio1Executor,
};
use rocket::http::uri::Absolute;
use serde_json::json;
use crate::types::UserID;
pub struct Mailer {
from: Mailbox,
verify_base: Absolute<'static>,
transport: AsyncSmtpTransport<Tokio1Executor>,
}
impl Mailer {
pub fn new(
from: Mailbox,
host: &str,
port: u16,
verify_base: Absolute<'static>,
) -> anyhow::Result<Self> {
Ok(Mailer {
from,
verify_base,
transport: AsyncSmtpTransport::<Tokio1Executor>::builder_dangerous(host)
.port(port)
.tls(Tls::Opportunistic(TlsParameters::new(host.to_string())?))
.timeout(Some(Duration::from_secs(5)))
.build(),
})
}
pub(crate) async fn send_account_verify(
&self,
uid: &UserID,
to: &str,
code: &str,
) -> anyhow::Result<()> {
let fragment = base64::encode_config(
serde_json::to_string(&json!({
"uid": uid,
"email": to,
"code": code,
}))?,
base64::URL_SAFE,
);
let email = Message::builder()
.from(self.from.clone())
.to(to.parse()?)
.subject("account verify code")
.body(format!("{}/#/verify/{fragment}", self.verify_base))?;
lettre::AsyncTransport::send(&self.transport, email).await?;
Ok(())
}
pub(crate) async fn send_session_verify(&self, to: &str, code: &str) -> anyhow::Result<()> {
let email = Message::builder()
.from(self.from.clone())
.to(to.parse()?)
.subject("session verify code")
.body(format!("{code}"))?;
lettre::AsyncTransport::send(&self.transport, email).await?;
Ok(())
}
pub(crate) async fn send_password_changed(&self, to: &str) -> anyhow::Result<()> {
let email = Message::builder()
.from(self.from.clone())
.to(to.parse()?)
.subject("account password has been changed")
.body(String::from(
"your account password has been changed. if you haven't done this, \
you're probably in trouble now.",
))?;
lettre::AsyncTransport::send(&self.transport, email).await?;
Ok(())
}
pub(crate) async fn send_password_forgot(&self, to: &str, code: &str) -> anyhow::Result<()> {
let email = Message::builder()
.from(self.from.clone())
.to(to.parse()?)
.subject("account reset code")
.body(code.to_string())?;
lettre::AsyncTransport::send(&self.transport, email).await?;
Ok(())
}
pub(crate) async fn send_account_reset(&self, to: &str) -> anyhow::Result<()> {
let email = Message::builder()
.from(self.from.clone())
.to(to.parse()?)
.subject("account has been reset")
.body(String::from(
"your account has been reset. if you haven't done this, \
you're probably in trouble now.",
))?;
lettre::AsyncTransport::send(&self.transport, email).await?;
Ok(())
}
}
|