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"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "linkify"
|
||||||
|
version = "0.10.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f1dfa36d52c581e9ec783a7ce2a5e0143da6237be5811a0b3153fedfdbe9f780"
|
||||||
|
dependencies = [
|
||||||
|
"memchr",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.13"
|
version = "0.4.13"
|
||||||
@ -3228,6 +3237,7 @@ dependencies = [
|
|||||||
"async-graphql-rocket",
|
"async-graphql-rocket",
|
||||||
"css-inline",
|
"css-inline",
|
||||||
"glog",
|
"glog",
|
||||||
|
"linkify",
|
||||||
"log 0.4.20",
|
"log 0.4.20",
|
||||||
"lol_html",
|
"lol_html",
|
||||||
"mailparse",
|
"mailparse",
|
||||||
|
|||||||
@ -27,6 +27,7 @@ lol_html = "1.2.0"
|
|||||||
css-inline = "0.13.0"
|
css-inline = "0.13.0"
|
||||||
anyhow = "1.0.79"
|
anyhow = "1.0.79"
|
||||||
maplit = "1.0.2"
|
maplit = "1.0.2"
|
||||||
|
linkify = "0.10.0"
|
||||||
|
|
||||||
[dependencies.rocket_contrib]
|
[dependencies.rocket_contrib]
|
||||||
version = "0.4.11"
|
version = "0.4.11"
|
||||||
|
|||||||
@ -16,7 +16,7 @@ use memmap::MmapOptions;
|
|||||||
use notmuch::Notmuch;
|
use notmuch::Notmuch;
|
||||||
use rocket::time::Instant;
|
use rocket::time::Instant;
|
||||||
|
|
||||||
use crate::sanitize_html;
|
use crate::{linkify_html, sanitize_html};
|
||||||
|
|
||||||
pub struct QueryRoot;
|
pub struct QueryRoot;
|
||||||
|
|
||||||
@ -347,8 +347,11 @@ impl QueryRoot {
|
|||||||
.get_first_value("date")
|
.get_first_value("date")
|
||||||
.and_then(|d| mailparse::dateparse(&d).ok());
|
.and_then(|d| mailparse::dateparse(&d).ok());
|
||||||
let body = match extract_body(&m)? {
|
let body = match extract_body(&m)? {
|
||||||
Body::PlainText(PlainText { text, content_tree }) => Body::PlainText(PlainText {
|
Body::PlainText(PlainText { text, content_tree }) => Body::Html(Html {
|
||||||
text,
|
html: format!(
|
||||||
|
r#"<p class="view-part-text-plain">{}</p>"#,
|
||||||
|
linkify_html(&text)
|
||||||
|
),
|
||||||
content_tree: if debug_content_tree {
|
content_tree: if debug_content_tree {
|
||||||
render_content_type_tree(&m)
|
render_content_type_tree(&m)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@ -3,6 +3,7 @@ pub mod graphql;
|
|||||||
pub mod nm;
|
pub mod nm;
|
||||||
|
|
||||||
use css_inline::{CSSInliner, InlineError, InlineOptions};
|
use css_inline::{CSSInliner, InlineError, InlineOptions};
|
||||||
|
use linkify::{LinkFinder, LinkKind};
|
||||||
use log::error;
|
use log::error;
|
||||||
use lol_html::{element, errors::RewritingError, rewrite_str, RewriteStrSettings};
|
use lol_html::{element, errors::RewritingError, rewrite_str, RewriteStrSettings};
|
||||||
use maplit::{hashmap, hashset};
|
use maplit::{hashmap, hashset};
|
||||||
@ -16,6 +17,22 @@ pub enum SanitizeError {
|
|||||||
InlineError(#[from] InlineError),
|
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> {
|
pub fn sanitize_html(html: &str) -> Result<String, SanitizeError> {
|
||||||
let element_content_handlers = vec![
|
let element_content_handlers = vec![
|
||||||
// Open links in new tab
|
// Open links in new tab
|
||||||
@ -204,8 +221,6 @@ pub fn sanitize_html(html: &str) -> Result<String, SanitizeError> {
|
|||||||
//let clean_html = inlined_html;
|
//let clean_html = inlined_html;
|
||||||
|
|
||||||
Ok(rewrite_str(
|
Ok(rewrite_str(
|
||||||
// TODO(wathiede): replace ammonia with more lol-html rules.
|
|
||||||
// &ammonia::clean(&html),
|
|
||||||
&clean_html,
|
&clean_html,
|
||||||
RewriteStrSettings {
|
RewriteStrSettings {
|
||||||
element_content_handlers,
|
element_content_handlers,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user