Skip to content

Commit

Permalink
BCC not removed from JMAP EmailSubmissions (fixes #618)
Browse files Browse the repository at this point in the history
  • Loading branch information
mdecimus committed Jan 29, 2025
1 parent 1b7cfe2 commit dc2a59e
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 9 deletions.
19 changes: 18 additions & 1 deletion crates/jmap/src/submission/set.rs
Original file line number Diff line number Diff line change
Expand Up @@ -516,13 +516,17 @@ 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 {
if matches!(
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) {
Expand Down Expand Up @@ -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
Expand All @@ -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)
Expand All @@ -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::<NullIo>::local(self.clone(), instance.clone(), SessionData::default());
Expand Down
18 changes: 12 additions & 6 deletions tests/src/jmap/email_submission.rs
Original file line number Diff line number Diff line change
Expand Up @@ -194,8 +194,13 @@ pub async fn test(params: &mut JMAPTest) {
));

// Submit a valid message submission
let email_body =
"From: [email protected]\r\nTo: [email protected]\r\nSubject: hey\r\n\r\ntest";
let email_body = concat!(
"From: [email protected]\r\n",
"To: [email protected]\r\n",
"Bcc: [email protected]\r\n",
"Subject: hey\r\n\r\n",
"test"
);
let email_id = client
.email_import(
email_body.as_bytes().to_vec(),
Expand All @@ -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: [email protected]\r\n", "");
assert_message_delivery(
&mut smtp_rx,
MockMessage::new(
"<[email protected]>",
["<[email protected]>"],
email_body,
["<[email protected]>", "<[email protected]>"],
&email_body,
),
)
.await;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -304,7 +310,7 @@ pub async fn test(params: &mut JMAPTest) {
.take_id();
assert_message_delivery(
&mut smtp_rx,
MockMessage::new("<[email protected]>", ["<[email protected]>"], email_body),
MockMessage::new("<[email protected]>", ["<[email protected]>"], &email_body),
)
.await;
expect_nothing(&mut smtp_rx).await;
Expand Down
4 changes: 2 additions & 2 deletions tests/src/jmap/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down

0 comments on commit dc2a59e

Please sign in to comment.