linkify URLs in plaintext emails.
This commit is contained in:
parent
569781b592
commit
568d83f029
10
Cargo.lock
generated
10
Cargo.lock
generated
@ -1747,6 +1747,15 @@ version = "0.2.152"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
||||
|
||||
[[package]]
|
||||
name = "linkify"
|
||||
version = "0.10.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1dfa36d52c581e9ec783a7ce2a5e0143da6237be5811a0b3153fedfdbe9f780"
|
||||
dependencies = [
|
||||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "linux-raw-sys"
|
||||
version = "0.4.13"
|
||||
@ -3228,6 +3237,7 @@ dependencies = [
|
||||
"async-graphql-rocket",
|
||||
"css-inline",
|
||||
"glog",
|
||||
"linkify",
|
||||
"log 0.4.20",
|
||||
"lol_html",
|
||||
"mailparse",
|
||||
|
||||
@ -27,6 +27,7 @@ lol_html = "1.2.0"
|
||||
css-inline = "0.13.0"
|
||||
anyhow = "1.0.79"
|
||||
maplit = "1.0.2"
|
||||
linkify = "0.10.0"
|
||||
|
||||
[dependencies.rocket_contrib]
|
||||
version = "0.4.11"
|
||||
|
||||
@ -16,7 +16,7 @@ use memmap::MmapOptions;
|
||||
use notmuch::Notmuch;
|
||||
use rocket::time::Instant;
|
||||
|
||||
use crate::sanitize_html;
|
||||
use crate::{linkify_html, sanitize_html};
|
||||
|
||||
pub struct QueryRoot;
|
||||
|
||||
@ -347,8 +347,11 @@ impl QueryRoot {
|
||||
.get_first_value("date")
|
||||
.and_then(|d| mailparse::dateparse(&d).ok());
|
||||
let body = match extract_body(&m)? {
|
||||
Body::PlainText(PlainText { text, content_tree }) => Body::PlainText(PlainText {
|
||||
text,
|
||||
Body::PlainText(PlainText { text, content_tree }) => Body::Html(Html {
|
||||
html: format!(
|
||||
r#"<p class="view-part-text-plain">{}</p>"#,
|
||||
linkify_html(&text)
|
||||
),
|
||||
content_tree: if debug_content_tree {
|
||||
render_content_type_tree(&m)
|
||||
} else {
|
||||
|
||||
@ -3,6 +3,7 @@ pub mod graphql;
|
||||
pub mod nm;
|
||||
|
||||
use css_inline::{CSSInliner, InlineError, InlineOptions};
|
||||
use linkify::{LinkFinder, LinkKind};
|
||||
use log::error;
|
||||
use lol_html::{element, errors::RewritingError, rewrite_str, RewriteStrSettings};
|
||||
use maplit::{hashmap, hashset};
|
||||
@ -16,6 +17,22 @@ pub enum SanitizeError {
|
||||
InlineError(#[from] InlineError),
|
||||
}
|
||||
|
||||
pub fn linkify_html(text: &str) -> String {
|
||||
let finder = LinkFinder::new();
|
||||
let mut parts = Vec::new();
|
||||
for span in finder.spans(text) {
|
||||
// TODO(wathiede): use Cow<str>?
|
||||
match span.kind() {
|
||||
// Text as-is
|
||||
None => parts.push(span.as_str().to_string()),
|
||||
// Wrap in anchor tag
|
||||
Some(LinkKind::Url) => parts.push(format!(r#"<a href="{0}">{0}</a>"#, span.as_str())),
|
||||
_ => todo!("unhandled kind: {:?}", span.kind().unwrap()),
|
||||
}
|
||||
}
|
||||
parts.join("")
|
||||
}
|
||||
|
||||
pub fn sanitize_html(html: &str) -> Result<String, SanitizeError> {
|
||||
let element_content_handlers = vec![
|
||||
// Open links in new tab
|
||||
@ -204,8 +221,6 @@ pub fn sanitize_html(html: &str) -> Result<String, SanitizeError> {
|
||||
//let clean_html = inlined_html;
|
||||
|
||||
Ok(rewrite_str(
|
||||
// TODO(wathiede): replace ammonia with more lol-html rules.
|
||||
// &ammonia::clean(&html),
|
||||
&clean_html,
|
||||
RewriteStrSettings {
|
||||
element_content_handlers,
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user