crabmail

Static HTML email archive viewer in Rust
git clone git://git.alexwennerberg.com/crabmail
Log | Files | Refs | README | LICENSE

commit 5e5637eec9a07f441a1bc9cc1c1dd1473bd94e94
parent 904dea9b135bf9f60b71d9e842145c73c7d669bc
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Sun,  1 Aug 2021 13:12:20 -0700

Pull more info into thread list

Diffstat:
Msrc/filters.rs | 2++
Msrc/main.rs | 30++++++++++++++++--------------
Mtemplates/threadlist.html | 4++--
3 files changed, 20 insertions(+), 16 deletions(-)

diff --git a/src/filters.rs b/src/filters.rs @@ -7,8 +7,10 @@ pub fn get_header(email: &&ParsedMail, header: &str) -> askama::Result<String> { .unwrap_or("".to_string())) } +// text/* pub fn get_body(email: &&ParsedMail) -> askama::Result<String> { // TODO mimetypes + let is_text = email.ctype.mimetype.starts_with("text/"); if email.subparts.len() > 0 { return Ok(email.subparts[0].get_body().unwrap_or("".to_string())); } diff --git a/src/main.rs b/src/main.rs @@ -9,16 +9,9 @@ mod filters; mod utils; const HELP: &str = "\ -Usage: crabmail (THIS STRING IS JUNK ATM) +Usage: crabmail -FLAGS: - -h, --help Prints this help information and exits. - -v, --version Prints the version and exits - -t, --threads Group messages into threads - -OPTIONS: - -d, --dir Directory to save the HTML files in - -m, --mbox Mbox file, files, or directories to read in +TODO "; // TODO be more clear about the expected input types @@ -58,7 +51,11 @@ fn main() -> Result<()> { let mut f = File::open(&file?.path())?; f.read_to_end(&mut buffer)?; let (headers, _) = parse_headers(&buffer)?; - let msg_id = headers.get_first_value("message-id").unwrap(); // TODO error + let msg_id = headers + .get_first_value("message-id") + .unwrap_or(String::new()); // TODO error + + // TOOD handle case where in reply to is not the root message of the thread let in_reply_to = headers.get_first_value("in-reply-to"); // Note that date can be forged by the client let date = dateparse( @@ -102,7 +99,11 @@ fn main() -> Result<()> { .truncate(true) .open(out_dir.join("index.html"))?; let thread_list = ThreadList { - thread_ids: threads.keys().collect(), + // assumes first message chronologically is the root + messages: threads + .values() + .map(|t| parse_mail(&t[0].data).unwrap()) + .collect(), }; file.write(thread_list.render()?.as_bytes()).ok(); // TODO prevent path traversal bug from ./.. in message id @@ -125,13 +126,14 @@ fn parse_path(s: &std::ffi::OsStr) -> Result<std::path::PathBuf, &'static str> { } #[derive(Template)] -#[template(path = "thread.html")] // using the template in this path, relative +#[template(path = "thread.html")] struct Thread<'a> { messages: Vec<ParsedMail<'a>>, } #[derive(Template)] -#[template(path = "threadlist.html")] // using the template in this path, relative +#[template(path = "threadlist.html")] struct ThreadList<'a> { - thread_ids: Vec<&'a String>, + // message root + messages: Vec<ParsedMail<'a>>, } diff --git a/templates/threadlist.html b/templates/threadlist.html @@ -3,8 +3,8 @@ {% block content %} <div class="page-title"><h1>Crabmail Mailing List</h1></div> <div> - {% for thread in thread_ids %} - <a href="threads/{{thread}}">{{thread}}</a> + {% for message in messages %} + <a href="threads/{{message|get_header("message-id")}}">{{message|get_header("subject")}}</a> {{message|get_header("from")}} {{message|get_header("date")}} <br> {% endfor %} </div>