BCC not removed from JMAP EmailSubmissions (fixes #618)

This commit is contained in:
mdecimus
2025-01-29 16:42:29 +01:00
parent 1b7cfe2b59
commit dc2a59e8d9
3 changed files with 32 additions and 9 deletions

View File

@@ -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::<NullIo>::local(self.clone(), instance.clone(), SessionData::default());

View File

@@ -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(
"<jdoe@example.com>",
["<jane_smith@remote.org>"],
email_body,
["<bill@remote.org>", "<jane_smith@remote.org>"],
&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("<jdoe@example.com>", ["<tim@foobar.com>"], email_body),
MockMessage::new("<jdoe@example.com>", ["<tim@foobar.com>"], &email_body),
)
.await;
expect_nothing(&mut smtp_rx).await;

View File

@@ -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;