diff --git a/crates/jmap/src/submission/set.rs b/crates/jmap/src/submission/set.rs index 07b6992d..5a182aac 100644 --- a/crates/jmap/src/submission/set.rs +++ b/crates/jmap/src/submission/set.rs @@ -516,6 +516,7 @@ impl EmailSubmissionSet for Server { }; // Add recipients to envelope if missing + let mut bcc_header = None; if rcpt_to.is_empty() { let mut envelope_values = Vec::new(); for header in &metadata.contents.parts[0].headers { @@ -523,6 +524,9 @@ impl EmailSubmissionSet for Server { header.name, HeaderName::To | HeaderName::Cc | HeaderName::Bcc ) { + if matches!(header.name, HeaderName::Bcc) { + bcc_header = Some(header); + } if let HeaderValue::Address(addr) = &header.value { for address in addr.iter() { if let Some(address) = address.address().and_then(sanitize_email) { @@ -555,6 +559,11 @@ impl EmailSubmissionSet for Server { return Ok(Err(SetError::new(SetErrorType::NoRecipients) .with_description("No recipients found in email."))); } + } else { + bcc_header = metadata.contents.parts[0] + .headers + .iter() + .find(|header| matches!(header.name, HeaderName::Bcc)); } // Update sendAt @@ -570,7 +579,7 @@ impl EmailSubmissionSet for Server { ); // Obtain raw message - let message = + let mut message = if let Some(message) = self.get_blob(&metadata.blob_hash, 0..usize::MAX).await? { if message.len() > self.core.jmap.mail_max_size { return Ok(Err(SetError::new(SetErrorType::InvalidEmail) @@ -587,6 +596,14 @@ impl EmailSubmissionSet for Server { .with_description("Blob for email not found."))); }; + // Remove BCC header if present + if let Some(bcc_header) = bcc_header { + let mut new_message = Vec::with_capacity(message.len()); + new_message.extend_from_slice(&message[..bcc_header.offset_field]); + new_message.extend_from_slice(&message[bcc_header.offset_end..]); + message = new_message; + } + // Begin local SMTP session let mut session = Session::::local(self.clone(), instance.clone(), SessionData::default()); diff --git a/tests/src/jmap/email_submission.rs b/tests/src/jmap/email_submission.rs index f680e810..49d84e96 100644 --- a/tests/src/jmap/email_submission.rs +++ b/tests/src/jmap/email_submission.rs @@ -194,8 +194,13 @@ pub async fn test(params: &mut JMAPTest) { )); // Submit a valid message submission - let email_body = - "From: jdoe@example.com\r\nTo: jane_smith@remote.org\r\nSubject: hey\r\n\r\ntest"; + let email_body = concat!( + "From: jdoe@example.com\r\n", + "To: jane_smith@remote.org\r\n", + "Bcc: bill@remote.org\r\n", + "Subject: hey\r\n\r\n", + "test" + ); let email_id = client .email_import( email_body.as_bytes().to_vec(), @@ -212,12 +217,13 @@ pub async fn test(params: &mut JMAPTest) { .unwrap(); // Confirm that the message has been delivered + let email_body = email_body.replace("Bcc: bill@remote.org\r\n", ""); assert_message_delivery( &mut smtp_rx, MockMessage::new( "", - [""], - email_body, + ["", ""], + &email_body, ), ) .await; @@ -253,7 +259,7 @@ pub async fn test(params: &mut JMAPTest) { .contains(&rcpt_to.as_str())); assert!( - message.message.contains(email_body), + message.message.contains(&email_body), "Got [{}], Expected[{}]", message.message, email_body @@ -304,7 +310,7 @@ pub async fn test(params: &mut JMAPTest) { .take_id(); assert_message_delivery( &mut smtp_rx, - MockMessage::new("", [""], email_body), + MockMessage::new("", [""], &email_body), ) .await; expect_nothing(&mut smtp_rx).await; diff --git a/tests/src/jmap/mod.rs b/tests/src/jmap/mod.rs index 362187fb..092d806d 100644 --- a/tests/src/jmap/mod.rs +++ b/tests/src/jmap/mod.rs @@ -383,14 +383,14 @@ pub async fn jmap_tests() { thread_get::test(&mut params).await; thread_merge::test(&mut params).await; mailbox::test(&mut params).await; - delivery::test(&mut params).await;*/ + delivery::test(&mut params).await; auth_acl::test(&mut params).await; auth_limits::test(&mut params).await; auth_oauth::test(&mut params).await; event_source::test(&mut params).await; push_subscription::test(&mut params).await; sieve_script::test(&mut params).await; - vacation_response::test(&mut params).await; + vacation_response::test(&mut params).await;*/ email_submission::test(&mut params).await; websocket::test(&mut params).await; quota::test(&mut params).await;