add dc_msg_set_html() api (#2153)

* draft dc_msg_set_html() api

* implement setting 'html to be send'

* test sending html-parts

* more flexible html-partbuilder

* write html-parts to database and also send them

* add 'sendhtml' command to repl tool
This commit is contained in:
bjoern
2021-01-27 12:56:22 +01:00
committed by GitHub
parent c8c2724c28
commit 1e6d8063c8
8 changed files with 146 additions and 30 deletions

View File

@@ -17,6 +17,7 @@ use crate::context::Context;
use crate::headerdef::{HeaderDef, HeaderDefMap};
use crate::message::{Message, MsgId};
use crate::mimeparser::parse_message_id;
use crate::param::Param::SendHtml;
use crate::plaintext::PlainText;
use lettre_email::PartBuilder;
use mailparse::ParsedContentType;
@@ -31,6 +32,24 @@ impl Message {
pub fn has_html(&self) -> bool {
self.mime_modified
}
/// Set HTML-part part of a message that is about to be sent.
/// The HTML-part is written to the database before sending and
/// used as the `text/html` part in the MIME-structure.
///
/// Received HTML parts are handled differently,
/// they are saved together with the whole MIME-structure
/// in `mime_headers` and the HTML-part is extracted using `MsgId::get_html()`.
/// (To underline this asynchronicity, we are using the wording "SendHtml")
pub fn set_html(&mut self, html: Option<String>) {
if let Some(html) = html {
self.param.set(SendHtml, html);
self.mime_modified = true;
} else {
self.param.remove(SendHtml);
self.mime_modified = false;
}
}
}
/// Type defining a rough mime-type.
@@ -250,33 +269,25 @@ impl MsgId {
None
}
}
}
/// Wraps HTML generated by [`MsgId::get_html`] into a text/html mimepart structure.
///
/// Used on forwarding messages to avoid leaking the original mime structure
/// and also to avoid sending too much, maybe large data.
pub async fn get_html_as_mimepart(self, context: &Context) -> Option<PartBuilder> {
self.get_html(context).await.map(|s| {
PartBuilder::new()
.content_type(&"text/html; charset=utf-8".parse::<mime::Mime>().unwrap())
.body(s)
})
}
// As [`MsgId::get_html_as_mimepart`] but wraps [`MsgId::get_html`] into text/html mime raw string.
pub async fn get_html_as_rawmime(self, context: &Context) -> Option<String> {
self.get_html_as_mimepart(context)
.await
.map(|p| p.build().as_string())
}
/// Wraps HTML text into a new text/html mimepart structure.
///
/// Used on forwarding messages to avoid leaking the original mime structure
/// and also to avoid sending too much, maybe large data.
pub async fn new_html_mimepart(html: String) -> PartBuilder {
PartBuilder::new()
.content_type(&"text/html; charset=utf-8".parse::<mime::Mime>().unwrap())
.body(html)
}
#[cfg(test)]
mod tests {
use super::*;
use crate::chat;
use crate::chat::forward_msgs;
use crate::config::Config;
use crate::constants::DC_CONTACT_ID_SELF;
use crate::constants::{Viewtype, DC_CONTACT_ID_SELF};
use crate::dc_receive_imf::dc_receive_imf;
use crate::message::MessengerMessage;
use crate::test_utils::TestContext;
@@ -519,4 +530,36 @@ test some special html-characters as &lt; &gt; and &amp; but also &quot; and &#x
let html = msg.get_id().get_html(&alice).await.unwrap();
assert!(html.find("this is <b>html</b>").is_some());
}
#[async_std::test]
async fn test_set_html() {
let alice = TestContext::new_alice().await;
let bob = TestContext::new_bob().await;
// alice sends a message with html-part to bob
let chat_id = alice.create_chat(&bob).await.id;
let mut msg = Message::new(Viewtype::Text);
msg.set_text(Some("plain text".to_string()));
msg.set_html(Some("<b>html</b> text".to_string()));
assert!(msg.mime_modified);
chat::send_msg(&alice, chat_id, &mut msg).await.unwrap();
// check the message is written correctly to alice's db
let msg = alice.get_last_msg_in(chat_id).await;
assert_eq!(msg.get_text(), Some("plain text".to_string()));
assert!(!msg.is_forwarded());
assert!(msg.mime_modified);
let html = msg.get_id().get_html(&alice).await.unwrap();
assert!(html.find("<b>html</b> text").is_some());
// let bob receive the message
let chat_id = bob.create_chat(&alice).await.id;
bob.recv_msg(&alice.pop_sent_msg().await).await;
let msg = bob.get_last_msg_in(chat_id).await;
assert_eq!(msg.get_text(), Some("plain text".to_string()));
assert!(!msg.is_forwarded());
assert!(msg.mime_modified);
let html = msg.get_id().get_html(&bob).await.unwrap();
assert!(html.find("<b>html</b> text").is_some());
}
}