diff --git a/deltachat-jsonrpc/src/api.rs b/deltachat-jsonrpc/src/api.rs index 0e41758e4..fdb03fabc 100644 --- a/deltachat-jsonrpc/src/api.rs +++ b/deltachat-jsonrpc/src/api.rs @@ -1476,6 +1476,20 @@ impl CommandApi { deltachat::contact::make_vcard(&ctx, &contacts).await } + /// Sets vCard containing the given contacts to the message draft. + async fn set_draft_vcard( + &self, + account_id: u32, + msg_id: u32, + contacts: Vec, + ) -> Result<()> { + let ctx = self.get_context(account_id).await?; + let contacts: Vec<_> = contacts.iter().map(|&c| ContactId::new(c)).collect(); + let mut msg = Message::load_from_db(&ctx, MsgId::new(msg_id)).await?; + msg.make_vcard(&ctx, &contacts).await?; + msg.get_chat_id().set_draft(&ctx, Some(&mut msg)).await + } + // --------------------------------------------- // chat // --------------------------------------------- diff --git a/src/message.rs b/src/message.rs index 85093b744..f8c1bd23e 100644 --- a/src/message.rs +++ b/src/message.rs @@ -16,7 +16,7 @@ use crate::config::Config; use crate::constants::{ Blocked, Chattype, VideochatType, DC_CHAT_ID_TRASH, DC_DESIRED_TEXT_LEN, DC_MSG_ID_LAST_SPECIAL, }; -use crate::contact::{Contact, ContactId}; +use crate::contact::{self, Contact, ContactId}; use crate::context::Context; use crate::debug_logging::set_debug_logging_xdc; use crate::download::DownloadState; @@ -1081,6 +1081,18 @@ impl Message { Ok(()) } + /// Makes message a vCard-containing message using the specified contacts. + pub async fn make_vcard(&mut self, context: &Context, contacts: &[ContactId]) -> Result<()> { + ensure!( + matches!(self.viewtype, Viewtype::File | Viewtype::Vcard), + "Wrong viewtype for vCard: {}", + self.viewtype, + ); + let vcard = contact::make_vcard(context, contacts).await?; + self.set_file_from_bytes(context, "vcard.vcf", vcard.as_bytes(), None) + .await + } + /// Set different sender name for a message. /// This overrides the name set by the `set_config()`-option `displayname`. pub fn set_override_sender_name(&mut self, name: Option) { diff --git a/src/receive_imf/tests.rs b/src/receive_imf/tests.rs index 3f56c22e9..9ae1ca25a 100644 --- a/src/receive_imf/tests.rs +++ b/src/receive_imf/tests.rs @@ -10,6 +10,7 @@ use crate::chat::{ }; use crate::chatlist::Chatlist; use crate::constants::{DC_GCL_FOR_FORWARDING, DC_GCL_NO_SPECIALS}; +use crate::contact; use crate::download::MIN_DOWNLOAD_LIMIT; use crate::imap::prefetch_should_download; use crate::imex::{imex, ImexMode}; @@ -4697,6 +4698,39 @@ async fn test_receive_vcard() -> Result<()> { Ok(()) } +#[tokio::test(flavor = "multi_thread", worker_threads = 2)] +async fn test_make_n_send_vcard() -> Result<()> { + let mut tcm = TestContextManager::new(); + let alice = &tcm.alice().await; + let bob = &tcm.bob().await; + let vcard = "BEGIN:VCARD\n\ + VERSION:4.0\n\ + FN:Claire\n\ + EMAIL;TYPE=work:claire@example.org\n\ + END:VCARD"; + let contact_ids = contact::import_vcard(alice, vcard).await?; + assert_eq!(contact_ids.len(), 1); + + let mut msg = Message::new(Viewtype::File); + msg.make_vcard(alice, &contact_ids).await?; + + let alice_bob_chat = alice.create_chat(bob).await; + let sent = alice.send_msg(alice_bob_chat.id, &mut msg).await; + let rcvd = bob.recv_msg(&sent).await; + let sent = Message::load_from_db(alice, sent.sender_msg_id).await?; + + assert_eq!(sent.viewtype, Viewtype::Vcard); + assert_eq!(rcvd.viewtype, Viewtype::Vcard); + + let vcard = tokio::fs::read(rcvd.get_file(bob).unwrap()).await?; + let vcard = std::str::from_utf8(&vcard)?; + let parsed = deltachat_contact_tools::parse_vcard(vcard); + assert_eq!(parsed.len(), 1); + assert_eq!(&parsed[0].addr, "claire@example.org"); + + Ok(()) +} + #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn test_group_no_recipients() -> Result<()> { let t = &TestContext::new_alice().await;