forge
ExploreLog in

Tahinli/forge

public
0 watching
★ 0
1.5 KiB
1//! The log transport: each message becomes one file under `<data_dir>/mail-log/`. For development
2//! and tests (`[mail] transport = "log"`). The files hold the full body, one-time links included,
3//! so this transport is not for production.
4
5use std::path::PathBuf;
6
7use forge_core::mail::{MailError, OutgoingMail};
8
9use super::{Mailer, SendFuture};
10
11/// Writes messages to a directory.
12pub struct LogMailer {
13 dir: PathBuf,
14}
15
16impl LogMailer {
17 pub fn new(dir: PathBuf) -> LogMailer {
18 LogMailer { dir }
19 }
20
21 async fn write(&self, mail: &OutgoingMail) -> Result<(), MailError> {
22 tokio::fs::create_dir_all(&self.dir)
23 .await
24 .map_err(|e| MailError::Transient(format!("cannot create the mail log: {e}")))?;
25 let name = format!("{}.txt", ulid::Ulid::generate());
26 let mut text = format!("To: {}\nSubject: {}\n", mail.to, mail.subject);
27 if let Some(id) = &mail.message_id {
28 text.push_str(&format!("Message-ID: {id}\n"));
29 }
30 if let Some(parent) = &mail.in_reply_to {
31 text.push_str(&format!("In-Reply-To: {parent}\nReferences: {parent}\n"));
32 }
33 text.push_str(&format!("\n{}", mail.body));
34 tokio::fs::write(self.dir.join(name), text)
35 .await
36 .map_err(|e| MailError::Transient(format!("cannot write the mail log: {e}")))
37 }
38}
39
40impl Mailer for LogMailer {
41 fn send<'a>(&'a self, mail: &'a OutgoingMail) -> SendFuture<'a> {
42 Box::pin(self.write(mail))
43 }
44}