1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
use std::error::Error;
use std::fs;
use std::path::Path;
use lettre::Message;
use lettre::message::header::{ContentTransferEncoding, ContentType};
use lettre::message::SinglePartBuilder;
use log::warn;
use visdom::types::Elements;
use visdom::Vis;
pub struct HtmlToEmail {
html: String,
from: String,
to: String,
}
impl HtmlToEmail {
pub fn new(html: String, from: String, to: String) -> Self {
Self {
html,
from,
to,
}
}
pub fn run(&self) -> Result<(), Box<dyn Error>> {
let output = self.html.trim_end_matches(".html").to_string() + ".eml";
if Path::new(&output).exists() {
warn!("target {} exist", output);
return Ok(());
}
let data = fs::read_to_string(self.html.clone())?;
let doc = Vis::load(data.as_str())?;
self.clean_doc(&doc);
let title = doc.find("title").text().to_string();
let body = SinglePartBuilder::new()
.header(ContentTransferEncoding::Base64)
.header(ContentType::TEXT_HTML)
.body(doc.html());
let email = Message::builder()
.from(self.from.parse()?)
.to(self.to.parse()?)
.subject(title)
.singlepart(body)?;
fs::write(output, email.formatted())?;
Ok(())
}
pub fn clean_doc(&self, doc: &Elements) {
doc.find(r#"div:contains("ads from inoreader")"#).closest("center").remove();
doc.find(r#"img[src='https://img.solidot.org//0/446/liiLIZF8Uh6yM.jpg']"#).remove();
doc.find("iframe").remove();
doc.find("link").remove();
doc.find("script").remove();
doc.find("button").remove();
doc.find("input").remove();
doc.find("*[contenteditable=true]").remove_attr("contenteditable");
}
}