mirror of
https://github.com/chatmail/core.git
synced 2026-05-07 08:56:30 +03:00
[wip, not compiling] extract function group_headers_by_confidentiality()
This commit is contained in:
@@ -947,6 +947,22 @@ impl MimeFactory {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.pre_message_mode == PreMessageMode::Post {
|
||||||
|
headers.push((
|
||||||
|
"Chat-Is-Post-Message",
|
||||||
|
mail_builder::headers::raw::Raw::new("1").into(),
|
||||||
|
));
|
||||||
|
} else if let PreMessageMode::Pre {
|
||||||
|
post_msg_rfc724_mid,
|
||||||
|
} = &self.pre_message_mode
|
||||||
|
{
|
||||||
|
headers.push((
|
||||||
|
"Chat-Post-Message-ID",
|
||||||
|
mail_builder::headers::message_id::MessageId::new(post_msg_rfc724_mid.clone())
|
||||||
|
.into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
let is_encrypted = self.will_be_encrypted();
|
let is_encrypted = self.will_be_encrypted();
|
||||||
|
|
||||||
// Add ephemeral timer for non-MDN messages.
|
// Add ephemeral timer for non-MDN messages.
|
||||||
@@ -993,155 +1009,17 @@ impl MimeFactory {
|
|||||||
Loaded::Mdn { .. } => self.render_mdn()?,
|
Loaded::Mdn { .. } => self.render_mdn()?,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Split headers based on header confidentiality policy.
|
let HeadersByConfidentiality {
|
||||||
|
mut unprotected_headers,
|
||||||
// Headers that must go into IMF header section.
|
hidden_headers,
|
||||||
//
|
protected_headers,
|
||||||
// These are standard headers such as Date, In-Reply-To, References, which cannot be placed
|
} = group_headers_by_confidentiality(
|
||||||
// anywhere else according to the standard. Placing headers here also allows them to be fetched
|
headers,
|
||||||
// individually over IMAP without downloading the message body. This is why Chat-Version is
|
&self.from_addr,
|
||||||
// placed here.
|
self.timestamp,
|
||||||
let mut unprotected_headers: Vec<(&'static str, HeaderType<'static>)> = Vec::new();
|
is_encrypted,
|
||||||
|
is_securejoin_message,
|
||||||
// Headers that MUST NOT (only) go into IMF header section:
|
);
|
||||||
// - Large headers which may hit the header section size limit on the server, such as
|
|
||||||
// Chat-User-Avatar with a base64-encoded image inside.
|
|
||||||
// - Headers duplicated here that servers mess up with in the IMF header section, like
|
|
||||||
// Message-ID.
|
|
||||||
// - Nonstandard headers that should be DKIM-protected because e.g. OpenDKIM only signs
|
|
||||||
// known headers.
|
|
||||||
//
|
|
||||||
// The header should be hidden from MTA
|
|
||||||
// by moving it either into protected part
|
|
||||||
// in case of encrypted mails
|
|
||||||
// or unprotected MIME preamble in case of unencrypted mails.
|
|
||||||
let mut hidden_headers: Vec<(&'static str, HeaderType<'static>)> = Vec::new();
|
|
||||||
|
|
||||||
// Opportunistically protected headers.
|
|
||||||
//
|
|
||||||
// These headers are placed into encrypted part *if* the message is encrypted. Place headers
|
|
||||||
// which are not needed before decryption (e.g. Chat-Group-Name) or are not interesting if the
|
|
||||||
// message cannot be decrypted (e.g. Chat-Disposition-Notification-To) here.
|
|
||||||
//
|
|
||||||
// If the message is not encrypted, these headers are placed into IMF header section, so make
|
|
||||||
// sure that the message will be encrypted if you place any sensitive information here.
|
|
||||||
let mut protected_headers: Vec<(&'static str, HeaderType<'static>)> = Vec::new();
|
|
||||||
|
|
||||||
// MIME header <https://datatracker.ietf.org/doc/html/rfc2045>.
|
|
||||||
unprotected_headers.push((
|
|
||||||
"MIME-Version",
|
|
||||||
mail_builder::headers::raw::Raw::new("1.0").into(),
|
|
||||||
));
|
|
||||||
|
|
||||||
if self.pre_message_mode == PreMessageMode::Post {
|
|
||||||
unprotected_headers.push((
|
|
||||||
"Chat-Is-Post-Message",
|
|
||||||
mail_builder::headers::raw::Raw::new("1").into(),
|
|
||||||
));
|
|
||||||
} else if let PreMessageMode::Pre {
|
|
||||||
post_msg_rfc724_mid,
|
|
||||||
} = &self.pre_message_mode
|
|
||||||
{
|
|
||||||
protected_headers.push((
|
|
||||||
"Chat-Post-Message-ID",
|
|
||||||
mail_builder::headers::message_id::MessageId::new(post_msg_rfc724_mid.clone())
|
|
||||||
.into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
for header @ (original_header_name, _header_value) in &headers {
|
|
||||||
let header_name = original_header_name.to_lowercase();
|
|
||||||
if header_name == "message-id" {
|
|
||||||
unprotected_headers.push(header.clone());
|
|
||||||
hidden_headers.push(header.clone());
|
|
||||||
} else if is_hidden(&header_name) {
|
|
||||||
hidden_headers.push(header.clone());
|
|
||||||
} else if header_name == "from" {
|
|
||||||
// Unencrypted securejoin messages should _not_ include the display name:
|
|
||||||
if is_encrypted || !is_securejoin_message {
|
|
||||||
protected_headers.push(header.clone());
|
|
||||||
}
|
|
||||||
|
|
||||||
unprotected_headers.push((
|
|
||||||
original_header_name,
|
|
||||||
Address::new_address(None::<&'static str>, self.from_addr.clone()).into(),
|
|
||||||
));
|
|
||||||
} else if header_name == "to" {
|
|
||||||
protected_headers.push(header.clone());
|
|
||||||
if is_encrypted {
|
|
||||||
unprotected_headers.push(("To", hidden_recipients().into()));
|
|
||||||
} else {
|
|
||||||
unprotected_headers.push(header.clone());
|
|
||||||
}
|
|
||||||
} else if header_name == "chat-broadcast-secret" {
|
|
||||||
if is_encrypted {
|
|
||||||
protected_headers.push(header.clone());
|
|
||||||
} else {
|
|
||||||
bail!("Message is unecrypted, cannot include broadcast secret");
|
|
||||||
}
|
|
||||||
} else if is_encrypted && header_name == "date" {
|
|
||||||
protected_headers.push(header.clone());
|
|
||||||
|
|
||||||
// Randomized date goes to unprotected header.
|
|
||||||
//
|
|
||||||
// We cannot just send "Thu, 01 Jan 1970 00:00:00 +0000"
|
|
||||||
// or omit the header because GMX then fails with
|
|
||||||
//
|
|
||||||
// host mx00.emig.gmx.net[212.227.15.9] said:
|
|
||||||
// 554-Transaction failed
|
|
||||||
// 554-Reject due to policy restrictions.
|
|
||||||
// 554 For explanation visit https://postmaster.gmx.net/en/case?...
|
|
||||||
// (in reply to end of DATA command)
|
|
||||||
//
|
|
||||||
// and the explanation page says
|
|
||||||
// "The time information deviates too much from the actual time".
|
|
||||||
//
|
|
||||||
// We also limit the range to 6 days (518400 seconds)
|
|
||||||
// because with a larger range we got
|
|
||||||
// error "500 Date header far in the past/future"
|
|
||||||
// which apparently originates from Symantec Messaging Gateway
|
|
||||||
// and means the message has a Date that is more
|
|
||||||
// than 7 days in the past:
|
|
||||||
// <https://github.com/chatmail/core/issues/7466>
|
|
||||||
let timestamp_offset = rand::random_range(0..518400);
|
|
||||||
let protected_timestamp = self.timestamp.saturating_sub(timestamp_offset);
|
|
||||||
let unprotected_date =
|
|
||||||
chrono::DateTime::<chrono::Utc>::from_timestamp(protected_timestamp, 0)
|
|
||||||
.unwrap()
|
|
||||||
.to_rfc2822();
|
|
||||||
unprotected_headers.push((
|
|
||||||
"Date",
|
|
||||||
mail_builder::headers::raw::Raw::new(unprotected_date).into(),
|
|
||||||
));
|
|
||||||
} else if is_encrypted {
|
|
||||||
protected_headers.push(header.clone());
|
|
||||||
|
|
||||||
match header_name.as_str() {
|
|
||||||
"subject" => {
|
|
||||||
unprotected_headers.push((
|
|
||||||
"Subject",
|
|
||||||
mail_builder::headers::raw::Raw::new("[...]").into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
"in-reply-to"
|
|
||||||
| "references"
|
|
||||||
| "auto-submitted"
|
|
||||||
| "chat-version"
|
|
||||||
| "autocrypt-setup-message" => {
|
|
||||||
unprotected_headers.push(header.clone());
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// Other headers are removed from unprotected part.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// Copy the header to the protected headers
|
|
||||||
// in case of signed-only message.
|
|
||||||
// If the message is not signed, this value will not be used.
|
|
||||||
protected_headers.push(header.clone());
|
|
||||||
unprotected_headers.push(header.clone())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let use_std_header_protection = context
|
let use_std_header_protection = context
|
||||||
.get_config_bool(Config::StdHeaderProtectionComposing)
|
.get_config_bool(Config::StdHeaderProtectionComposing)
|
||||||
@@ -2098,6 +1976,158 @@ impl MimeFactory {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct HeadersByConfidentiality {
|
||||||
|
/// Headers that must go into IMF header section.
|
||||||
|
///
|
||||||
|
/// These are standard headers such as Date, In-Reply-To, References, which cannot be placed
|
||||||
|
/// anywhere else according to the standard. Placing headers here also allows them to be fetched
|
||||||
|
/// individually over IMAP without downloading the message body. This is why Chat-Version is
|
||||||
|
/// placed here.
|
||||||
|
unprotected_headers: Vec<(&'static str, HeaderType<'static>)>,
|
||||||
|
|
||||||
|
/// Headers that MUST NOT (only) go into IMF header section:
|
||||||
|
/// - Large headers which may hit the header section size limit on the server, such as
|
||||||
|
/// Chat-User-Avatar with a base64-encoded image inside.
|
||||||
|
/// - Headers duplicated here that servers mess up with in the IMF header section, like
|
||||||
|
/// Message-ID.
|
||||||
|
/// - Nonstandard headers that should be DKIM-protected because e.g. OpenDKIM only signs
|
||||||
|
/// known headers.
|
||||||
|
///
|
||||||
|
/// The header should be hidden from MTA
|
||||||
|
/// by moving it either into protected part
|
||||||
|
/// in case of encrypted mails
|
||||||
|
/// or unprotected MIME preamble in case of unencrypted mails.
|
||||||
|
hidden_headers: Vec<(&'static str, HeaderType<'static>)>,
|
||||||
|
|
||||||
|
/// Opportunistically protected headers.
|
||||||
|
///
|
||||||
|
/// These headers are placed into encrypted part *if* the message is encrypted. Place headers
|
||||||
|
/// which are not needed before decryption (e.g. Chat-Group-Name) or are not interesting if the
|
||||||
|
/// message cannot be decrypted (e.g. Chat-Disposition-Notification-To) here.
|
||||||
|
///
|
||||||
|
/// If the message is not encrypted, these headers are placed into IMF header section, so make
|
||||||
|
/// sure that the message will be encrypted if you place any sensitive information here.
|
||||||
|
protected_headers: Vec<(&'static str, HeaderType<'static>)>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Split headers based on header confidentiality policy.
|
||||||
|
/// See [`HeadersByConfidentiality`] for more info.
|
||||||
|
fn group_headers_by_confidentiality(
|
||||||
|
headers: Vec<(&'static str, HeaderType<'static>)>,
|
||||||
|
from_addr: &str,
|
||||||
|
timestamp: i64,
|
||||||
|
is_encrypted: bool,
|
||||||
|
is_securejoin_message: bool,
|
||||||
|
) -> HeadersByConfidentiality {
|
||||||
|
let mut unprotected_headers: Vec<(&'static str, HeaderType<'static>)> = Vec::new();
|
||||||
|
let mut hidden_headers: Vec<(&'static str, HeaderType<'static>)> = Vec::new();
|
||||||
|
let mut protected_headers: Vec<(&'static str, HeaderType<'static>)> = Vec::new();
|
||||||
|
|
||||||
|
// MIME header <https://datatracker.ietf.org/doc/html/rfc2045>.
|
||||||
|
unprotected_headers.push((
|
||||||
|
"MIME-Version",
|
||||||
|
mail_builder::headers::raw::Raw::new("1.0").into(),
|
||||||
|
));
|
||||||
|
|
||||||
|
for header @ (original_header_name, _header_value) in &headers {
|
||||||
|
let header_name = original_header_name.to_lowercase();
|
||||||
|
if header_name == "message-id" {
|
||||||
|
unprotected_headers.push(header.clone());
|
||||||
|
hidden_headers.push(header.clone());
|
||||||
|
} else if is_hidden(&header_name) {
|
||||||
|
hidden_headers.push(header.clone());
|
||||||
|
} else if header_name == "from" {
|
||||||
|
// Unencrypted securejoin messages should _not_ include the display name:
|
||||||
|
if is_encrypted || !is_securejoin_message {
|
||||||
|
protected_headers.push(header.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
unprotected_headers.push((
|
||||||
|
original_header_name,
|
||||||
|
Address::new_address(None::<&'static str>, from_addr.to_string()).into(),
|
||||||
|
));
|
||||||
|
} else if header_name == "to" {
|
||||||
|
protected_headers.push(header.clone());
|
||||||
|
if is_encrypted {
|
||||||
|
unprotected_headers.push(("To", hidden_recipients().into()));
|
||||||
|
} else {
|
||||||
|
unprotected_headers.push(header.clone());
|
||||||
|
}
|
||||||
|
} else if header_name == "chat-broadcast-secret" {
|
||||||
|
if is_encrypted {
|
||||||
|
protected_headers.push(header.clone());
|
||||||
|
}
|
||||||
|
} else if is_encrypted && header_name == "date" {
|
||||||
|
protected_headers.push(header.clone());
|
||||||
|
|
||||||
|
// Randomized date goes to unprotected header.
|
||||||
|
//
|
||||||
|
// We cannot just send "Thu, 01 Jan 1970 00:00:00 +0000"
|
||||||
|
// or omit the header because GMX then fails with
|
||||||
|
//
|
||||||
|
// host mx00.emig.gmx.net[212.227.15.9] said:
|
||||||
|
// 554-Transaction failed
|
||||||
|
// 554-Reject due to policy restrictions.
|
||||||
|
// 554 For explanation visit https://postmaster.gmx.net/en/case?...
|
||||||
|
// (in reply to end of DATA command)
|
||||||
|
//
|
||||||
|
// and the explanation page says
|
||||||
|
// "The time information deviates too much from the actual time".
|
||||||
|
//
|
||||||
|
// We also limit the range to 6 days (518400 seconds)
|
||||||
|
// because with a larger range we got
|
||||||
|
// error "500 Date header far in the past/future"
|
||||||
|
// which apparently originates from Symantec Messaging Gateway
|
||||||
|
// and means the message has a Date that is more
|
||||||
|
// than 7 days in the past:
|
||||||
|
// <https://github.com/chatmail/core/issues/7466>
|
||||||
|
let timestamp_offset = rand::random_range(0..518400);
|
||||||
|
let protected_timestamp = timestamp.saturating_sub(timestamp_offset);
|
||||||
|
let unprotected_date =
|
||||||
|
chrono::DateTime::<chrono::Utc>::from_timestamp(protected_timestamp, 0)
|
||||||
|
.unwrap()
|
||||||
|
.to_rfc2822();
|
||||||
|
unprotected_headers.push((
|
||||||
|
"Date",
|
||||||
|
mail_builder::headers::raw::Raw::new(unprotected_date).into(),
|
||||||
|
));
|
||||||
|
} else if is_encrypted {
|
||||||
|
protected_headers.push(header.clone());
|
||||||
|
|
||||||
|
match header_name.as_str() {
|
||||||
|
"subject" => {
|
||||||
|
unprotected_headers.push((
|
||||||
|
"Subject",
|
||||||
|
mail_builder::headers::raw::Raw::new("[...]").into(),
|
||||||
|
));
|
||||||
|
}
|
||||||
|
"in-reply-to"
|
||||||
|
| "references"
|
||||||
|
| "auto-submitted"
|
||||||
|
| "chat-version"
|
||||||
|
| "autocrypt-setup-message"
|
||||||
|
| "chat-is-post-message" => {
|
||||||
|
unprotected_headers.push(header.clone());
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
// Other headers are removed from unprotected part.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Copy the header to the protected headers
|
||||||
|
// in case of signed-only message.
|
||||||
|
// If the message is not signed, this value will not be used.
|
||||||
|
protected_headers.push(header.clone());
|
||||||
|
unprotected_headers.push(header.clone())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
HeadersByConfidentiality {
|
||||||
|
unprotected_headers,
|
||||||
|
hidden_headers,
|
||||||
|
protected_headers,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn hidden_recipients() -> Address<'static> {
|
fn hidden_recipients() -> Address<'static> {
|
||||||
Address::new_group(Some("hidden-recipients".to_string()), Vec::new())
|
Address::new_group(Some("hidden-recipients".to_string()), Vec::new())
|
||||||
}
|
}
|
||||||
@@ -2217,7 +2247,7 @@ pub(crate) async fn render_symm_encrypted_securejoin_message(
|
|||||||
let mut headers = Vec::<(&'static str, HeaderType<'static>)>::new();
|
let mut headers = Vec::<(&'static str, HeaderType<'static>)>::new();
|
||||||
|
|
||||||
let from_addr = context.get_primary_self_addr().await?;
|
let from_addr = context.get_primary_self_addr().await?;
|
||||||
let from = new_address_with_name("", from_addr);
|
let from = new_address_with_name("", from_addr.to_string());
|
||||||
|
|
||||||
let mut to: Vec<Address<'static>> = Vec::new();
|
let mut to: Vec<Address<'static>> = Vec::new();
|
||||||
to.push(hidden_recipients());
|
to.push(hidden_recipients());
|
||||||
@@ -2276,116 +2306,19 @@ pub(crate) async fn render_symm_encrypted_securejoin_message(
|
|||||||
|
|
||||||
let message: MimePart<'static> = MimePart::new("text/plain", "Secure-Join");
|
let message: MimePart<'static> = MimePart::new("text/plain", "Secure-Join");
|
||||||
|
|
||||||
// Split headers based on header confidentiality policy.
|
let is_encrypted = true;
|
||||||
|
let is_securejoin_message = true;
|
||||||
// Headers that must go into IMF header section.
|
let HeadersByConfidentiality {
|
||||||
//
|
unprotected_headers,
|
||||||
// These are standard headers such as Date, In-Reply-To, References, which cannot be placed
|
hidden_headers,
|
||||||
// anywhere else according to the standard. Placing headers here also allows them to be fetched
|
protected_headers,
|
||||||
// individually over IMAP without downloading the message body. This is why Chat-Version is
|
} = group_headers_by_confidentiality(
|
||||||
// placed here.
|
headers,
|
||||||
let mut unprotected_headers: Vec<(&'static str, HeaderType<'static>)> = Vec::new();
|
&from_addr,
|
||||||
|
timestamp,
|
||||||
// Headers that MUST NOT (only) go into IMF header section:
|
is_encrypted,
|
||||||
// - Large headers which may hit the header section size limit on the server, such as
|
is_securejoin_message,
|
||||||
// Chat-User-Avatar with a base64-encoded image inside.
|
);
|
||||||
// - Headers duplicated here that servers mess up with in the IMF header section, like
|
|
||||||
// Message-ID.
|
|
||||||
// - Nonstandard headers that should be DKIM-protected because e.g. OpenDKIM only signs
|
|
||||||
// known headers.
|
|
||||||
//
|
|
||||||
// The header should be hidden from MTA
|
|
||||||
// by moving it either into protected part
|
|
||||||
// in case of encrypted mails
|
|
||||||
// or unprotected MIME preamble in case of unencrypted mails.
|
|
||||||
let mut hidden_headers: Vec<(&'static str, HeaderType<'static>)> = Vec::new();
|
|
||||||
|
|
||||||
// Opportunistically protected headers.
|
|
||||||
//
|
|
||||||
// These headers are placed into encrypted part *if* the message is encrypted. Place headers
|
|
||||||
// which are not needed before decryption (e.g. Chat-Group-Name) or are not interesting if the
|
|
||||||
// message cannot be decrypted (e.g. Chat-Disposition-Notification-To) here.
|
|
||||||
//
|
|
||||||
// If the message is not encrypted, these headers are placed into IMF header section, so make
|
|
||||||
// sure that the message will be encrypted if you place any sensitive information here.
|
|
||||||
let mut protected_headers: Vec<(&'static str, HeaderType<'static>)> = Vec::new();
|
|
||||||
|
|
||||||
// MIME header <https://datatracker.ietf.org/doc/html/rfc2045>.
|
|
||||||
unprotected_headers.push((
|
|
||||||
"MIME-Version",
|
|
||||||
mail_builder::headers::raw::Raw::new("1.0").into(),
|
|
||||||
));
|
|
||||||
|
|
||||||
for header @ (original_header_name, _header_value) in &headers {
|
|
||||||
let header_name = original_header_name.to_lowercase();
|
|
||||||
if header_name == "message-id" {
|
|
||||||
unprotected_headers.push(header.clone());
|
|
||||||
hidden_headers.push(header.clone());
|
|
||||||
} else if is_hidden(&header_name) {
|
|
||||||
hidden_headers.push(header.clone());
|
|
||||||
} else if header_name == "from" {
|
|
||||||
protected_headers.push(header.clone());
|
|
||||||
|
|
||||||
unprotected_headers.push(header.clone());
|
|
||||||
} else if header_name == "to" {
|
|
||||||
unprotected_headers.push(("To", hidden_recipients().into()));
|
|
||||||
} else if header_name == "date" {
|
|
||||||
protected_headers.push(header.clone());
|
|
||||||
|
|
||||||
// Randomized date goes to unprotected header.
|
|
||||||
//
|
|
||||||
// We cannot just send "Thu, 01 Jan 1970 00:00:00 +0000"
|
|
||||||
// or omit the header because GMX then fails with
|
|
||||||
//
|
|
||||||
// host mx00.emig.gmx.net[212.227.15.9] said:
|
|
||||||
// 554-Transaction failed
|
|
||||||
// 554-Reject due to policy restrictions.
|
|
||||||
// 554 For explanation visit https://postmaster.gmx.net/en/case?...
|
|
||||||
// (in reply to end of DATA command)
|
|
||||||
//
|
|
||||||
// and the explanation page says
|
|
||||||
// "The time information deviates too much from the actual time".
|
|
||||||
//
|
|
||||||
// We also limit the range to 6 days (518400 seconds)
|
|
||||||
// because with a larger range we got
|
|
||||||
// error "500 Date header far in the past/future"
|
|
||||||
// which apparently originates from Symantec Messaging Gateway
|
|
||||||
// and means the message has a Date that is more
|
|
||||||
// than 7 days in the past:
|
|
||||||
// <https://github.com/chatmail/core/issues/7466>
|
|
||||||
let timestamp_offset = rand::random_range(0..518400);
|
|
||||||
let protected_timestamp = timestamp.saturating_sub(timestamp_offset);
|
|
||||||
let unprotected_date =
|
|
||||||
chrono::DateTime::<chrono::Utc>::from_timestamp(protected_timestamp, 0)
|
|
||||||
.unwrap()
|
|
||||||
.to_rfc2822();
|
|
||||||
unprotected_headers.push((
|
|
||||||
"Date",
|
|
||||||
mail_builder::headers::raw::Raw::new(unprotected_date).into(),
|
|
||||||
));
|
|
||||||
} else {
|
|
||||||
protected_headers.push(header.clone());
|
|
||||||
|
|
||||||
match header_name.as_str() {
|
|
||||||
"subject" => {
|
|
||||||
unprotected_headers.push((
|
|
||||||
"Subject",
|
|
||||||
mail_builder::headers::raw::Raw::new("[...]").into(),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
"in-reply-to"
|
|
||||||
| "references"
|
|
||||||
| "auto-submitted"
|
|
||||||
| "chat-version"
|
|
||||||
| "autocrypt-setup-message" => {
|
|
||||||
unprotected_headers.push(header.clone());
|
|
||||||
}
|
|
||||||
_ => {
|
|
||||||
// Other headers are removed from unprotected part.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let outer_message = {
|
let outer_message = {
|
||||||
// Store protected headers in the inner message.
|
// Store protected headers in the inner message.
|
||||||
|
|||||||
Reference in New Issue
Block a user