diff --git a/CHANGELOG.md b/CHANGELOG.md index 33954c041..500f46ebc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Changes - Validate signatures in try_decrypt() even if the message isn't encrypted #3859 - Don't parse the message again after detached signatures validation #3862 +- Move format=flowed support to a separate crate #3869 ### API-Changes diff --git a/Cargo.lock b/Cargo.lock index cbc7a9693..198ae37eb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -887,6 +887,7 @@ dependencies = [ "encoded-words", "escaper", "fast-socks5", + "format-flowed", "futures", "futures-lite", "hex", @@ -1445,6 +1446,10 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "format-flowed" +version = "1.0.0" + [[package]] name = "futures" version = "0.3.25" diff --git a/Cargo.toml b/Cargo.toml index 4d09f5492..9fbd387e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,6 +19,7 @@ panic = 'abort' [dependencies] deltachat_derive = { path = "./deltachat_derive" } +format-flowed = { path = "./format-flowed" } ansi_term = { version = "0.12.1", optional = true } anyhow = "1" @@ -99,7 +100,8 @@ members = [ "deltachat-ffi", "deltachat_derive", "deltachat-jsonrpc", - "deltachat-rpc-server" + "deltachat-rpc-server", + "format-flowed", ] [[example]] diff --git a/format-flowed/Cargo.toml b/format-flowed/Cargo.toml new file mode 100644 index 000000000..480704215 --- /dev/null +++ b/format-flowed/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "format-flowed" +version = "1.0.0" +description = "format=flowed support" +edition = "2021" +license = "MPL-2.0" + +keywords = ["email"] +categories = ["email"] + +[dependencies] diff --git a/src/format_flowed.rs b/format-flowed/src/lib.rs similarity index 79% rename from src/format_flowed.rs rename to format-flowed/src/lib.rs index cea31306d..67d18e8d1 100644 --- a/src/format_flowed.rs +++ b/format-flowed/src/lib.rs @@ -62,7 +62,7 @@ fn format_line_flowed(line: &str, prefix: &str) -> String { /// /// RFC 2646 technique is used to insert soft line breaks, so DelSp /// SHOULD be set to "no" when sending. -pub(crate) fn format_flowed(text: &str) -> String { +pub fn format_flowed(text: &str) -> String { let mut result = String::new(); for line in text.split('\n') { @@ -147,8 +147,6 @@ pub fn unformat_flowed(text: &str, delsp: bool) -> String { #[cfg(test)] mod tests { use super::*; - use crate::test_utils::TestContext; - use anyhow::Result; #[test] fn test_format_flowed() { @@ -220,51 +218,4 @@ mod tests { > unwrapped on the receiver"; assert_eq!(format_flowed_quote(quote), expected); } - - #[tokio::test(flavor = "multi_thread", worker_threads = 2)] - async fn test_send_quotes() -> Result<()> { - let alice = TestContext::new_alice().await; - let bob = TestContext::new_bob().await; - let chat = alice.create_chat(&bob).await; - - let sent = alice.send_text(chat.id, "> First quote").await; - let received = bob.recv_msg(&sent).await; - assert_eq!(received.text.as_deref(), Some("> First quote")); - assert!(received.quoted_text().is_none()); - assert!(received.quoted_message(&bob).await?.is_none()); - - let sent = alice.send_text(chat.id, "> Second quote").await; - let received = bob.recv_msg(&sent).await; - assert_eq!(received.text.as_deref(), Some("> Second quote")); - assert!(received.quoted_text().is_none()); - assert!(received.quoted_message(&bob).await?.is_none()); - - Ok(()) - } - - #[tokio::test(flavor = "multi_thread", worker_threads = 2)] - async fn test_format_flowed_round_trip() -> Result<()> { - let alice = TestContext::new_alice().await; - let bob = TestContext::new_bob().await; - let chat = alice.create_chat(&bob).await; - - let text = " Foo bar"; - let sent = alice.send_text(chat.id, text).await; - let received = bob.recv_msg(&sent).await; - assert_eq!(received.text.as_deref(), Some(text)); - - let text = "Foo bar baz"; - let sent = alice.send_text(chat.id, text).await; - let received = bob.recv_msg(&sent).await; - assert_eq!(received.text.as_deref(), Some(text)); - - let python_program = "\ -def hello(): - return 'Hello, world!'"; - let sent = alice.send_text(chat.id, python_program).await; - let received = bob.recv_msg(&sent).await; - assert_eq!(received.text.as_deref(), Some(python_program)); - - Ok(()) - } } diff --git a/src/lib.rs b/src/lib.rs index 7def6a20b..771783ba6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,7 +74,6 @@ pub mod imex; mod scheduler; #[macro_use] mod job; -mod format_flowed; pub mod key; mod keyring; pub mod location; diff --git a/src/message.rs b/src/message.rs index 2baef9d3f..a1e1b0b97 100644 --- a/src/message.rs +++ b/src/message.rs @@ -2340,4 +2340,51 @@ mod tests { ); assert_eq!(Viewtype::Webxdc, Viewtype::from_i32(80).unwrap()); } + + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_send_quotes() -> Result<()> { + let alice = TestContext::new_alice().await; + let bob = TestContext::new_bob().await; + let chat = alice.create_chat(&bob).await; + + let sent = alice.send_text(chat.id, "> First quote").await; + let received = bob.recv_msg(&sent).await; + assert_eq!(received.text.as_deref(), Some("> First quote")); + assert!(received.quoted_text().is_none()); + assert!(received.quoted_message(&bob).await?.is_none()); + + let sent = alice.send_text(chat.id, "> Second quote").await; + let received = bob.recv_msg(&sent).await; + assert_eq!(received.text.as_deref(), Some("> Second quote")); + assert!(received.quoted_text().is_none()); + assert!(received.quoted_message(&bob).await?.is_none()); + + Ok(()) + } + + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] + async fn test_format_flowed_round_trip() -> Result<()> { + let alice = TestContext::new_alice().await; + let bob = TestContext::new_bob().await; + let chat = alice.create_chat(&bob).await; + + let text = " Foo bar"; + let sent = alice.send_text(chat.id, text).await; + let received = bob.recv_msg(&sent).await; + assert_eq!(received.text.as_deref(), Some(text)); + + let text = "Foo bar baz"; + let sent = alice.send_text(chat.id, text).await; + let received = bob.recv_msg(&sent).await; + assert_eq!(received.text.as_deref(), Some(text)); + + let python_program = "\ +def hello(): + return 'Hello, world!'"; + let sent = alice.send_text(chat.id, python_program).await; + let received = bob.recv_msg(&sent).await; + assert_eq!(received.text.as_deref(), Some(python_program)); + + Ok(()) + } } diff --git a/src/mimefactory.rs b/src/mimefactory.rs index 5f6f33adb..184acaae0 100644 --- a/src/mimefactory.rs +++ b/src/mimefactory.rs @@ -4,6 +4,7 @@ use std::convert::TryInto; use anyhow::{bail, ensure, Context as _, Result}; use chrono::TimeZone; +use format_flowed::{format_flowed, format_flowed_quote}; use lettre_email::{mime, Address, Header, MimeMultipartType, PartBuilder}; use tokio::fs; @@ -15,7 +16,6 @@ use crate::contact::Contact; use crate::context::{get_version_str, Context}; use crate::e2ee::EncryptHelper; use crate::ephemeral::Timer as EphemeralTimer; -use crate::format_flowed::{format_flowed, format_flowed_quote}; use crate::html::new_html_mimepart; use crate::location; use crate::message::{self, Message, MsgId, Viewtype}; diff --git a/src/mimeparser.rs b/src/mimeparser.rs index 7996a01b8..5d43db545 100644 --- a/src/mimeparser.rs +++ b/src/mimeparser.rs @@ -9,6 +9,7 @@ use std::str; use anyhow::{bail, Context as _, Result}; use deltachat_derive::{FromSql, ToSql}; +use format_flowed::unformat_flowed; use lettre_email::mime::{self, Mime}; use mailparse::{addrparse_header, DispositionType, MailHeader, MailHeaderMap, SingleInfo}; use once_cell::sync::Lazy; @@ -24,7 +25,6 @@ use crate::decrypt::{ }; use crate::dehtml::dehtml; use crate::events::EventType; -use crate::format_flowed::unformat_flowed; use crate::headerdef::{HeaderDef, HeaderDefMap}; use crate::key::{DcKey, Fingerprint, SignedPublicKey, SignedSecretKey}; use crate::keyring::Keyring;