crabmail

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

commit aa2aa36634029f880ed405d905ef5cb52e5fe1b7
parent 5ebb2455bf0e3432da5772ef277718cc86477782
Author: alex wennerberg <alex@alexwennerberg.com>
Date:   Thu, 16 Dec 2021 18:55:45 -0800

Cleanup threadlist

Diffstat:
Msrc/main.rs | 30++++++++++++++++++++----------
Msrc/style.css | 4++++
Dtemplates/threadlist.html | 21---------------------
3 files changed, 24 insertions(+), 31 deletions(-)

diff --git a/src/main.rs b/src/main.rs @@ -37,7 +37,8 @@ struct Email { from: SingleInfo, subject: String, in_reply_to: Option<String>, - date: u64, // unix epoch. received date + date: u64, // unix epoch. received date (if present) + date_string: String, body: String, mime: String, } @@ -84,7 +85,7 @@ struct ThreadList<'a> { fn short_name(s: &SingleInfo) -> &str { match &s.display_name { Some(dn) => dn, - None => &s.addr + None => &s.addr, } } impl<'a> ThreadList<'a> { @@ -97,7 +98,7 @@ impl<'a> ThreadList<'a> { hr; @ for thread in &self.threads { div(class="message-sum") { - a(class="threadlink", href=format!("threads/{}.html", urlencoding::encode(&thread.messages[0].id))) { + a(class="threadlink", href=format!("threads/{}.html", &thread.hash)) { : &thread.messages[0].subject } br; @@ -136,21 +137,25 @@ impl<'a> MailThread<'a> { @ for message in &self.messages { hr; div(id=&message.id, class="message") { - a(href=format!("mailto:{}", &message.from.addr), class="addr") { + div(class="bold") { + : &message.subject + } + a(href=format!("mailto:{}", &message.from.addr), class="addr bold") { : &message.from.to_string(); } - } + br; span(class="timeago") { - : utils::timeago(message.date) + : &message.date_string } a(title="permalink", href=format!("#{}", &message.id)) { - : "๐Ÿ”—" + : " ๐Ÿ”—" } @ if message.in_reply_to.is_some() { // TODO figure out match a(title="replies-to", href=format!("#{}", message.in_reply_to.clone().unwrap())){ : "Re:" } } + br; br; div(class="email-body") { : Raw(utils::email_body(&message.body)) } @@ -159,6 +164,7 @@ impl<'a> MailThread<'a> { :"โœ‰๏ธ reply" } } + } } } }; @@ -183,6 +189,7 @@ impl Email { let mut pushencode = |k: &str, v| { url.push_str(&format!("{}={}&", k, urlencoding::encode(v))); }; + // TODO verify encoding looks good and use percent_encoding instead pushencode("cc", &from); pushencode("in-reply-to", &self.id); pushencode("subject", &format!("Re: {}", self.subject)); @@ -259,8 +266,10 @@ fn local_parse_email(data: &[u8]) -> Result<Email> { .get_first_value("subject") .unwrap_or("(no subject)".to_owned()); // TODO not guaranteed to be accurate. Maybe use "received"? - let date_string = &headers.get_first_value("date").context("No date header")?; - let date = dateparse(date_string)? as u64; + let date_string = headers.get_first_value("date").context("No date header")?; + + // TODO use received. + let date = dateparse(&date_string)? as u64; let from = addrparse_header(headers.get_first_header("from").context("No from header")?)? .extract_single_info() .context("Could not parse from header")?; @@ -271,6 +280,7 @@ fn local_parse_email(data: &[u8]) -> Result<Email> { from, subject, date, + date_string, body, mime, }); @@ -377,7 +387,7 @@ fn main() -> Result<()> { threads.sort_by_key(|a| a.last_reply); threads.reverse(); - ThreadList{threads}.write_to_file(&out_dir); + ThreadList { threads }.write_to_file(&out_dir); // kinda clunky let css = include_bytes!("style.css"); let mut css_root = File::create(out_dir.join("style.css"))?; diff --git a/src/style.css b/src/style.css @@ -30,6 +30,10 @@ table { border-spacing: 0.5em 0.1em; } color: #369; } +.bold { + font-weight: bold; +} + .threadlink { font-size: 1.3rem; color: #202020; diff --git a/templates/threadlist.html b/templates/threadlist.html @@ -1,21 +0,0 @@ -{% extends "base.html" %} - -{% block content %} -<div class="page-title"><h1>{{config.list_name}}</h1></div> -{% match config.homepage %}{% when Some with (home) %}<a href="{{home}}">about</a> | {%when none%}{%endmatch%} - <a href="mailto:{{config.list_email}}">โœ‰๏ธ {{config.list_email}}</a> - <hr class="thin"> - {% for thread in threads %} - {% let message = thread.messages[0] %} - <div class="message-sum"> - <a href="threads/{{thread.hash}}.html" class="threadlink">{{message.subject}}</a> - <br> - <a href="mailto:{{message.from.addr}}" class="addr">{%match message.from.display_name %} - {% when Some with (name) %} - {{name}}{% when none %}{{message.from.addr}}{% endmatch %}</a> - <span class="timeago"> ยท {{thread.messages.len() - 1}} replies ยท {{thread.last_reply() | time_ago}}</span> - <br> - </div> - {% endfor %} - </div> -{% endblock %}