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");
    }
}