1use sova_core::{Request, Result};
4use sova_mail::{Content, Envelope, MailExt, Mailable};
5#[cfg(feature = "templates")]
6use serde_json::json;
7
8pub struct VerifyEmailMail {
10 pub link: String,
11 pub(crate) prefer_view: bool,
13}
14
15impl VerifyEmailMail {
16 pub fn new(link: impl Into<String>) -> Self {
17 Self {
18 link: link.into(),
19 prefer_view: true,
20 }
21 }
22}
23
24impl Mailable for VerifyEmailMail {
25 fn envelope(&self) -> Envelope {
26 Envelope::new("Verify your email")
27 }
28
29 fn content(&self) -> Content {
30 let text = format!("Verify your email:\n\n{}\n", self.link);
31 let html = format!(
32 "<p>Verify your email:</p><p><a href=\"{0}\">{0}</a></p>",
33 self.link
34 );
35 #[cfg(feature = "templates")]
36 if self.prefer_view {
37 return Content::view_with_text(
38 "mail/verify.html",
39 json!({ "link": self.link }),
40 text,
41 );
42 }
43 Content::html_with_text(html, text)
44 }
45}
46
47pub struct ResetPasswordMail {
49 pub link: String,
50 pub(crate) prefer_view: bool,
51}
52
53impl ResetPasswordMail {
54 pub fn new(link: impl Into<String>) -> Self {
55 Self {
56 link: link.into(),
57 prefer_view: true,
58 }
59 }
60}
61
62impl Mailable for ResetPasswordMail {
63 fn envelope(&self) -> Envelope {
64 Envelope::new("Reset your password")
65 }
66
67 fn content(&self) -> Content {
68 let text = format!("Reset your password:\n\n{}\n", self.link);
69 let html = format!(
70 "<p>Reset your password:</p><p><a href=\"{0}\">{0}</a></p>",
71 self.link
72 );
73 #[cfg(feature = "templates")]
74 if self.prefer_view {
75 return Content::view_with_text(
76 "mail/reset.html",
77 json!({ "link": self.link }),
78 text,
79 );
80 }
81 Content::html_with_text(html, text)
82 }
83}
84
85fn templates_ready(req: &Request) -> bool {
86 #[cfg(feature = "templates")]
87 {
88 req.try_state::<sova_templates::MiniJinjaTemplates>()
89 .is_some()
90 }
91 #[cfg(not(feature = "templates"))]
92 {
93 let _ = req;
94 false
95 }
96}
97
98pub async fn send_verify(req: &Request, to: &str, link: &str) -> Result<()> {
99 let mut mail = VerifyEmailMail::new(link);
100 mail.prefer_view = templates_ready(req);
101 req.mail().to(to).send_mail(mail).await
102}
103
104pub async fn send_reset(req: &Request, to: &str, link: &str) -> Result<()> {
105 let mut mail = ResetPasswordMail::new(link);
106 mail.prefer_view = templates_ready(req);
107 req.mail().to(to).send_mail(mail).await
108}