mirror of
https://github.com/chatmail/core.git
synced 2026-05-08 17:36:29 +03:00
mimeparser: pass the Context around explicitly
This commit is contained in:
@@ -244,7 +244,7 @@ pub fn dc_receive_imf(
|
|||||||
|
|
||||||
cleanup(context, &create_event_to_send, &created_db_entries);
|
cleanup(context, &create_event_to_send, &created_db_entries);
|
||||||
|
|
||||||
mime_parser.handle_reports(from_id, sent_timestamp, &server_folder, server_uid);
|
mime_parser.handle_reports(context, from_id, sent_timestamp, &server_folder, server_uid);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@@ -1054,7 +1054,7 @@ fn create_or_lookup_group(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// try extract a grpid from a message-id list header value
|
/// try extract a grpid from a message-id list header value
|
||||||
fn extract_grpid<'a>(mime_parser: &'a MimeMessage, headerdef: HeaderDef) -> Option<&'a str> {
|
fn extract_grpid(mime_parser: &MimeMessage, headerdef: HeaderDef) -> Option<&str> {
|
||||||
let header = mime_parser.get(headerdef)?;
|
let header = mime_parser.get(headerdef)?;
|
||||||
let parts = header
|
let parts = header
|
||||||
.split(',')
|
.split(',')
|
||||||
|
|||||||
@@ -36,8 +36,7 @@ use crate::{bail, ensure};
|
|||||||
/// It is created by parsing the raw data of an actual MIME message
|
/// It is created by parsing the raw data of an actual MIME message
|
||||||
/// using the [MimeMessage::from_bytes] constructor.
|
/// using the [MimeMessage::from_bytes] constructor.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct MimeMessage<'a> {
|
pub struct MimeMessage {
|
||||||
pub context: &'a Context,
|
|
||||||
pub parts: Vec<Part>,
|
pub parts: Vec<Part>,
|
||||||
header: HashMap<String, String>,
|
header: HashMap<String, String>,
|
||||||
pub decrypting_failed: bool,
|
pub decrypting_failed: bool,
|
||||||
@@ -91,8 +90,8 @@ impl Default for SystemMessage {
|
|||||||
|
|
||||||
const MIME_AC_SETUP_FILE: &str = "application/autocrypt-setup";
|
const MIME_AC_SETUP_FILE: &str = "application/autocrypt-setup";
|
||||||
|
|
||||||
impl<'a> MimeMessage<'a> {
|
impl MimeMessage {
|
||||||
pub fn from_bytes(context: &'a Context, body: &[u8]) -> Result<Self> {
|
pub fn from_bytes(context: &Context, body: &[u8]) -> Result<Self> {
|
||||||
let mail = mailparse::parse_mail(body)?;
|
let mail = mailparse::parse_mail(body)?;
|
||||||
|
|
||||||
let message_time = mail
|
let message_time = mail
|
||||||
@@ -160,7 +159,6 @@ impl<'a> MimeMessage<'a> {
|
|||||||
signatures,
|
signatures,
|
||||||
gossipped_addr,
|
gossipped_addr,
|
||||||
is_forwarded: false,
|
is_forwarded: false,
|
||||||
context,
|
|
||||||
reports: Vec::new(),
|
reports: Vec::new(),
|
||||||
is_system_message: SystemMessage::Unknown,
|
is_system_message: SystemMessage::Unknown,
|
||||||
location_kml: None,
|
location_kml: None,
|
||||||
@@ -168,14 +166,14 @@ impl<'a> MimeMessage<'a> {
|
|||||||
user_avatar: AvatarAction::None,
|
user_avatar: AvatarAction::None,
|
||||||
group_avatar: AvatarAction::None,
|
group_avatar: AvatarAction::None,
|
||||||
};
|
};
|
||||||
parser.parse_mime_recursive(&mail)?;
|
parser.parse_mime_recursive(context, &mail)?;
|
||||||
parser.parse_headers()?;
|
parser.parse_headers(context)?;
|
||||||
|
|
||||||
Ok(parser)
|
Ok(parser)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parses system messages.
|
/// Parses system messages.
|
||||||
fn parse_system_message_headers(&mut self) -> Result<()> {
|
fn parse_system_message_headers(&mut self, context: &Context) -> Result<()> {
|
||||||
if self.get(HeaderDef::AutocryptSetupMessage).is_some() {
|
if self.get(HeaderDef::AutocryptSetupMessage).is_some() {
|
||||||
self.parts = self
|
self.parts = self
|
||||||
.parts
|
.parts
|
||||||
@@ -190,7 +188,7 @@ impl<'a> MimeMessage<'a> {
|
|||||||
if self.parts.len() == 1 {
|
if self.parts.len() == 1 {
|
||||||
self.is_system_message = SystemMessage::AutocryptSetupMessage;
|
self.is_system_message = SystemMessage::AutocryptSetupMessage;
|
||||||
} else {
|
} else {
|
||||||
warn!(self.context, "could not determine ASM mime-part");
|
warn!(context, "could not determine ASM mime-part");
|
||||||
}
|
}
|
||||||
} else if let Some(value) = self.get(HeaderDef::ChatContent) {
|
} else if let Some(value) = self.get(HeaderDef::ChatContent) {
|
||||||
if value == "location-streaming-enabled" {
|
if value == "location-streaming-enabled" {
|
||||||
@@ -284,8 +282,8 @@ impl<'a> MimeMessage<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_headers(&mut self) -> Result<()> {
|
fn parse_headers(&mut self, context: &Context) -> Result<()> {
|
||||||
self.parse_system_message_headers()?;
|
self.parse_system_message_headers(context)?;
|
||||||
self.parse_avatar_headers();
|
self.parse_avatar_headers();
|
||||||
self.squash_attachment_parts();
|
self.squash_attachment_parts();
|
||||||
|
|
||||||
@@ -330,9 +328,9 @@ impl<'a> MimeMessage<'a> {
|
|||||||
// See if an MDN is requested from the other side
|
// See if an MDN is requested from the other side
|
||||||
if !self.decrypting_failed && !self.parts.is_empty() {
|
if !self.decrypting_failed && !self.parts.is_empty() {
|
||||||
if let Some(ref dn_to_addr) =
|
if let Some(ref dn_to_addr) =
|
||||||
self.parse_first_addr(HeaderDef::ChatDispositionNotificationTo)
|
self.parse_first_addr(context, HeaderDef::ChatDispositionNotificationTo)
|
||||||
{
|
{
|
||||||
if let Some(ref from_addr) = self.parse_first_addr(HeaderDef::From_) {
|
if let Some(ref from_addr) = self.parse_first_addr(context, HeaderDef::From_) {
|
||||||
if compare_addrs(from_addr, dn_to_addr) {
|
if compare_addrs(from_addr, dn_to_addr) {
|
||||||
if let Some(part) = self.parts.last_mut() {
|
if let Some(part) = self.parts.last_mut() {
|
||||||
part.param.set_int(Param::WantsMdn, 1);
|
part.param.set_int(Param::WantsMdn, 1);
|
||||||
@@ -407,31 +405,35 @@ impl<'a> MimeMessage<'a> {
|
|||||||
self.header.get(&headerdef.get_headername())
|
self.header.get(&headerdef.get_headername())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_first_addr(&self, headerdef: HeaderDef) -> Option<MailAddr> {
|
fn parse_first_addr(&self, context: &Context, headerdef: HeaderDef) -> Option<MailAddr> {
|
||||||
if let Some(value) = self.get(headerdef.clone()) {
|
if let Some(value) = self.get(headerdef.clone()) {
|
||||||
match mailparse::addrparse(&value) {
|
match mailparse::addrparse(&value) {
|
||||||
Ok(ref addrs) => {
|
Ok(ref addrs) => {
|
||||||
return addrs.first().cloned();
|
return addrs.first().cloned();
|
||||||
}
|
}
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(self.context, "header {} parse error: {:?}", headerdef, err);
|
warn!(context, "header {} parse error: {:?}", headerdef, err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_mime_recursive(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result<bool> {
|
fn parse_mime_recursive(
|
||||||
|
&mut self,
|
||||||
|
context: &Context,
|
||||||
|
mail: &mailparse::ParsedMail<'_>,
|
||||||
|
) -> Result<bool> {
|
||||||
if mail.ctype.params.get("protected-headers").is_some() {
|
if mail.ctype.params.get("protected-headers").is_some() {
|
||||||
if mail.ctype.mimetype == "text/rfc822-headers" {
|
if mail.ctype.mimetype == "text/rfc822-headers" {
|
||||||
warn!(
|
warn!(
|
||||||
self.context,
|
context,
|
||||||
"Protected headers found in text/rfc822-headers attachment: Will be ignored.",
|
"Protected headers found in text/rfc822-headers attachment: Will be ignored.",
|
||||||
);
|
);
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
warn!(self.context, "Ignoring nested protected headers");
|
warn!(context, "Ignoring nested protected headers");
|
||||||
}
|
}
|
||||||
|
|
||||||
enum MimeS {
|
enum MimeS {
|
||||||
@@ -459,7 +461,7 @@ impl<'a> MimeMessage<'a> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
match m {
|
match m {
|
||||||
MimeS::Multiple => self.handle_multiple(mail),
|
MimeS::Multiple => self.handle_multiple(context, mail),
|
||||||
MimeS::Message => {
|
MimeS::Message => {
|
||||||
let raw = mail.get_body_raw()?;
|
let raw = mail.get_body_raw()?;
|
||||||
if raw.is_empty() {
|
if raw.is_empty() {
|
||||||
@@ -467,13 +469,17 @@ impl<'a> MimeMessage<'a> {
|
|||||||
}
|
}
|
||||||
let mail = mailparse::parse_mail(&raw).unwrap();
|
let mail = mailparse::parse_mail(&raw).unwrap();
|
||||||
|
|
||||||
self.parse_mime_recursive(&mail)
|
self.parse_mime_recursive(context, &mail)
|
||||||
}
|
}
|
||||||
MimeS::Single => self.add_single_part_if_known(mail),
|
MimeS::Single => self.add_single_part_if_known(context, mail),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn handle_multiple(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result<bool> {
|
fn handle_multiple(
|
||||||
|
&mut self,
|
||||||
|
context: &Context,
|
||||||
|
mail: &mailparse::ParsedMail<'_>,
|
||||||
|
) -> Result<bool> {
|
||||||
let mut any_part_added = false;
|
let mut any_part_added = false;
|
||||||
let mimetype = get_mime_type(mail)?.0;
|
let mimetype = get_mime_type(mail)?.0;
|
||||||
match (mimetype.type_(), mimetype.subtype().as_str()) {
|
match (mimetype.type_(), mimetype.subtype().as_str()) {
|
||||||
@@ -484,7 +490,7 @@ impl<'a> MimeMessage<'a> {
|
|||||||
(mime::MULTIPART, "alternative") => {
|
(mime::MULTIPART, "alternative") => {
|
||||||
for cur_data in &mail.subparts {
|
for cur_data in &mail.subparts {
|
||||||
if get_mime_type(cur_data)?.0 == "multipart/mixed" {
|
if get_mime_type(cur_data)?.0 == "multipart/mixed" {
|
||||||
any_part_added = self.parse_mime_recursive(cur_data)?;
|
any_part_added = self.parse_mime_recursive(context, cur_data)?;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -492,7 +498,7 @@ impl<'a> MimeMessage<'a> {
|
|||||||
/* search for text/plain and add this */
|
/* search for text/plain and add this */
|
||||||
for cur_data in &mail.subparts {
|
for cur_data in &mail.subparts {
|
||||||
if get_mime_type(cur_data)?.0.type_() == mime::TEXT {
|
if get_mime_type(cur_data)?.0.type_() == mime::TEXT {
|
||||||
any_part_added = self.parse_mime_recursive(cur_data)?;
|
any_part_added = self.parse_mime_recursive(context, cur_data)?;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -500,7 +506,7 @@ impl<'a> MimeMessage<'a> {
|
|||||||
if !any_part_added {
|
if !any_part_added {
|
||||||
/* `text/plain` not found - use the first part */
|
/* `text/plain` not found - use the first part */
|
||||||
for cur_part in &mail.subparts {
|
for cur_part in &mail.subparts {
|
||||||
if self.parse_mime_recursive(cur_part)? {
|
if self.parse_mime_recursive(context, cur_part)? {
|
||||||
any_part_added = true;
|
any_part_added = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -513,14 +519,14 @@ impl<'a> MimeMessage<'a> {
|
|||||||
being the first one, which may not be always true ...
|
being the first one, which may not be always true ...
|
||||||
however, most times it seems okay. */
|
however, most times it seems okay. */
|
||||||
if let Some(first) = mail.subparts.iter().next() {
|
if let Some(first) = mail.subparts.iter().next() {
|
||||||
any_part_added = self.parse_mime_recursive(first)?;
|
any_part_added = self.parse_mime_recursive(context, first)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(mime::MULTIPART, "encrypted") => {
|
(mime::MULTIPART, "encrypted") => {
|
||||||
// we currently do not try to decrypt non-autocrypt messages
|
// we currently do not try to decrypt non-autocrypt messages
|
||||||
// at all. If we see an encrypted part, we set
|
// at all. If we see an encrypted part, we set
|
||||||
// decrypting_failed.
|
// decrypting_failed.
|
||||||
let msg_body = self.context.stock_str(StockMessage::CantDecryptMsgBody);
|
let msg_body = context.stock_str(StockMessage::CantDecryptMsgBody);
|
||||||
let txt = format!("[{}]", msg_body);
|
let txt = format!("[{}]", msg_body);
|
||||||
|
|
||||||
let mut part = Part::default();
|
let mut part = Part::default();
|
||||||
@@ -543,7 +549,7 @@ impl<'a> MimeMessage<'a> {
|
|||||||
https://k9mail.github.io/2016/11/24/OpenPGP-Considerations-Part-I.html
|
https://k9mail.github.io/2016/11/24/OpenPGP-Considerations-Part-I.html
|
||||||
for background information why we use encrypted+signed) */
|
for background information why we use encrypted+signed) */
|
||||||
if let Some(first) = mail.subparts.iter().next() {
|
if let Some(first) = mail.subparts.iter().next() {
|
||||||
any_part_added = self.parse_mime_recursive(first)?;
|
any_part_added = self.parse_mime_recursive(context, first)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(mime::MULTIPART, "report") => {
|
(mime::MULTIPART, "report") => {
|
||||||
@@ -551,14 +557,14 @@ impl<'a> MimeMessage<'a> {
|
|||||||
if mail.subparts.len() >= 2 {
|
if mail.subparts.len() >= 2 {
|
||||||
if let Some(report_type) = mail.ctype.params.get("report-type") {
|
if let Some(report_type) = mail.ctype.params.get("report-type") {
|
||||||
if report_type == "disposition-notification" {
|
if report_type == "disposition-notification" {
|
||||||
if let Some(report) = self.process_report(mail)? {
|
if let Some(report) = self.process_report(context, mail)? {
|
||||||
self.reports.push(report);
|
self.reports.push(report);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* eg. `report-type=delivery-status`;
|
/* eg. `report-type=delivery-status`;
|
||||||
maybe we should show them as a little error icon */
|
maybe we should show them as a little error icon */
|
||||||
if let Some(first) = mail.subparts.iter().next() {
|
if let Some(first) = mail.subparts.iter().next() {
|
||||||
any_part_added = self.parse_mime_recursive(first)?;
|
any_part_added = self.parse_mime_recursive(context, first)?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -568,7 +574,7 @@ impl<'a> MimeMessage<'a> {
|
|||||||
// Add all parts (in fact, AddSinglePartIfKnown() later check if
|
// Add all parts (in fact, AddSinglePartIfKnown() later check if
|
||||||
// the parts are really supported)
|
// the parts are really supported)
|
||||||
for cur_data in mail.subparts.iter() {
|
for cur_data in mail.subparts.iter() {
|
||||||
if self.parse_mime_recursive(cur_data)? {
|
if self.parse_mime_recursive(context, cur_data)? {
|
||||||
any_part_added = true;
|
any_part_added = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -578,7 +584,11 @@ impl<'a> MimeMessage<'a> {
|
|||||||
Ok(any_part_added)
|
Ok(any_part_added)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_single_part_if_known(&mut self, mail: &mailparse::ParsedMail<'_>) -> Result<bool> {
|
fn add_single_part_if_known(
|
||||||
|
&mut self,
|
||||||
|
context: &Context,
|
||||||
|
mail: &mailparse::ParsedMail<'_>,
|
||||||
|
) -> Result<bool> {
|
||||||
// return true if a part was added
|
// return true if a part was added
|
||||||
let (mime_type, msg_type) = get_mime_type(mail)?;
|
let (mime_type, msg_type) = get_mime_type(mail)?;
|
||||||
let raw_mime = mail.ctype.mimetype.to_lowercase();
|
let raw_mime = mail.ctype.mimetype.to_lowercase();
|
||||||
@@ -589,6 +599,7 @@ impl<'a> MimeMessage<'a> {
|
|||||||
|
|
||||||
if let Ok(filename) = filename {
|
if let Ok(filename) = filename {
|
||||||
self.do_add_single_file_part(
|
self.do_add_single_file_part(
|
||||||
|
context,
|
||||||
msg_type,
|
msg_type,
|
||||||
mime_type,
|
mime_type,
|
||||||
&raw_mime,
|
&raw_mime,
|
||||||
@@ -604,7 +615,7 @@ impl<'a> MimeMessage<'a> {
|
|||||||
let decoded_data = match mail.get_body() {
|
let decoded_data = match mail.get_body() {
|
||||||
Ok(decoded_data) => decoded_data,
|
Ok(decoded_data) => decoded_data,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
warn!(self.context, "Invalid body parsed {:?}", err);
|
warn!(context, "Invalid body parsed {:?}", err);
|
||||||
// Note that it's not always an error - might be no data
|
// Note that it's not always an error - might be no data
|
||||||
return Ok(false);
|
return Ok(false);
|
||||||
}
|
}
|
||||||
@@ -645,6 +656,7 @@ impl<'a> MimeMessage<'a> {
|
|||||||
|
|
||||||
fn do_add_single_file_part(
|
fn do_add_single_file_part(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
context: &Context,
|
||||||
msg_type: Viewtype,
|
msg_type: Viewtype,
|
||||||
mime_type: Mime,
|
mime_type: Mime,
|
||||||
raw_mime: &str,
|
raw_mime: &str,
|
||||||
@@ -659,9 +671,9 @@ impl<'a> MimeMessage<'a> {
|
|||||||
// XXX what if somebody sends eg an "location-highlights.kml"
|
// XXX what if somebody sends eg an "location-highlights.kml"
|
||||||
// attachment unrelated to location streaming?
|
// attachment unrelated to location streaming?
|
||||||
if filename.starts_with("location") || filename.starts_with("message") {
|
if filename.starts_with("location") || filename.starts_with("message") {
|
||||||
let parsed = location::Kml::parse(self.context, decoded_data)
|
let parsed = location::Kml::parse(context, decoded_data)
|
||||||
.map_err(|err| {
|
.map_err(|err| {
|
||||||
warn!(self.context, "failed to parse kml part: {}", err);
|
warn!(context, "failed to parse kml part: {}", err);
|
||||||
})
|
})
|
||||||
.ok();
|
.ok();
|
||||||
if filename.starts_with("location") {
|
if filename.starts_with("location") {
|
||||||
@@ -675,17 +687,17 @@ impl<'a> MimeMessage<'a> {
|
|||||||
/* we have a regular file attachment,
|
/* we have a regular file attachment,
|
||||||
write decoded data to new blob object */
|
write decoded data to new blob object */
|
||||||
|
|
||||||
let blob = match BlobObject::create(self.context, filename, decoded_data) {
|
let blob = match BlobObject::create(context, filename, decoded_data) {
|
||||||
Ok(blob) => blob,
|
Ok(blob) => blob,
|
||||||
Err(err) => {
|
Err(err) => {
|
||||||
error!(
|
error!(
|
||||||
self.context,
|
context,
|
||||||
"Could not add blob for mime part {}, error {}", filename, err
|
"Could not add blob for mime part {}, error {}", filename, err
|
||||||
);
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
info!(self.context, "added blobfile: {:?}", blob.as_name());
|
info!(context, "added blobfile: {:?}", blob.as_name());
|
||||||
|
|
||||||
/* create and register Mime part referencing the new Blob object */
|
/* create and register Mime part referencing the new Blob object */
|
||||||
let mut part = Part::default();
|
let mut part = Part::default();
|
||||||
@@ -759,7 +771,11 @@ impl<'a> MimeMessage<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_report(&self, report: &mailparse::ParsedMail<'_>) -> Result<Option<Report>> {
|
fn process_report(
|
||||||
|
&self,
|
||||||
|
context: &Context,
|
||||||
|
report: &mailparse::ParsedMail<'_>,
|
||||||
|
) -> Result<Option<Report>> {
|
||||||
// parse as mailheaders
|
// parse as mailheaders
|
||||||
let report_body = report.subparts[1].get_body_raw()?;
|
let report_body = report.subparts[1].get_body_raw()?;
|
||||||
let (report_fields, _) = mailparse::parse_headers(&report_body)?;
|
let (report_fields, _) = mailparse::parse_headers(&report_body)?;
|
||||||
@@ -788,7 +804,7 @@ impl<'a> MimeMessage<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
warn!(
|
warn!(
|
||||||
self.context,
|
context,
|
||||||
"ignoring unknown disposition-notification, Message-Id: {:?}",
|
"ignoring unknown disposition-notification, Message-Id: {:?}",
|
||||||
report_fields.get_first_value("Message-ID").ok()
|
report_fields.get_first_value("Message-ID").ok()
|
||||||
);
|
);
|
||||||
@@ -799,6 +815,7 @@ impl<'a> MimeMessage<'a> {
|
|||||||
/// Handle reports (only MDNs for now)
|
/// Handle reports (only MDNs for now)
|
||||||
pub fn handle_reports(
|
pub fn handle_reports(
|
||||||
&self,
|
&self,
|
||||||
|
context: &Context,
|
||||||
from_id: u32,
|
from_id: u32,
|
||||||
sent_timestamp: i64,
|
sent_timestamp: i64,
|
||||||
server_folder: impl AsRef<str>,
|
server_folder: impl AsRef<str>,
|
||||||
@@ -813,13 +830,10 @@ impl<'a> MimeMessage<'a> {
|
|||||||
for original_message_id in
|
for original_message_id in
|
||||||
std::iter::once(&report.original_message_id).chain(&report.additional_message_ids)
|
std::iter::once(&report.original_message_id).chain(&report.additional_message_ids)
|
||||||
{
|
{
|
||||||
if let Some((chat_id, msg_id)) = message::mdn_from_ext(
|
if let Some((chat_id, msg_id)) =
|
||||||
self.context,
|
message::mdn_from_ext(context, from_id, original_message_id, sent_timestamp)
|
||||||
from_id,
|
{
|
||||||
original_message_id,
|
context.call_cb(Event::MsgRead { chat_id, msg_id });
|
||||||
sent_timestamp,
|
|
||||||
) {
|
|
||||||
self.context.call_cb(Event::MsgRead { chat_id, msg_id });
|
|
||||||
mdn_recognized = true;
|
mdn_recognized = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -829,10 +843,10 @@ impl<'a> MimeMessage<'a> {
|
|||||||
let mut param = Params::new();
|
let mut param = Params::new();
|
||||||
param.set(Param::ServerFolder, server_folder.as_ref());
|
param.set(Param::ServerFolder, server_folder.as_ref());
|
||||||
param.set_int(Param::ServerUid, server_uid as i32);
|
param.set_int(Param::ServerUid, server_uid as i32);
|
||||||
if self.has_chat_version() && self.context.get_config_bool(Config::MvboxMove) {
|
if self.has_chat_version() && context.get_config_bool(Config::MvboxMove) {
|
||||||
param.set_int(Param::AlsoMove, 1);
|
param.set_int(Param::AlsoMove, 1);
|
||||||
}
|
}
|
||||||
job_add(self.context, Action::MarkseenMdnOnImap, 0, param, 0);
|
job_add(context, Action::MarkseenMdnOnImap, 0, param, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1166,10 +1180,13 @@ mod tests {
|
|||||||
|
|
||||||
let mimeparser = MimeMessage::from_bytes(&context.ctx, &raw[..]).unwrap();
|
let mimeparser = MimeMessage::from_bytes(&context.ctx, &raw[..]).unwrap();
|
||||||
|
|
||||||
let of = mimeparser.parse_first_addr(HeaderDef::From_).unwrap();
|
let of = mimeparser
|
||||||
|
.parse_first_addr(&context.ctx, HeaderDef::From_)
|
||||||
|
.unwrap();
|
||||||
assert_eq!(of, mailparse::addrparse("hello@one.org").unwrap()[0]);
|
assert_eq!(of, mailparse::addrparse("hello@one.org").unwrap()[0]);
|
||||||
|
|
||||||
let of = mimeparser.parse_first_addr(HeaderDef::ChatDispositionNotificationTo);
|
let of =
|
||||||
|
mimeparser.parse_first_addr(&context.ctx, HeaderDef::ChatDispositionNotificationTo);
|
||||||
assert!(of.is_none());
|
assert!(of.is_none());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -485,7 +485,7 @@ pub(crate) fn handle_securejoin_handshake(
|
|||||||
let scanned_fingerprint_of_alice = get_qr_attr!(context, fingerprint).to_string();
|
let scanned_fingerprint_of_alice = get_qr_attr!(context, fingerprint).to_string();
|
||||||
let auth = get_qr_attr!(context, auth).to_string();
|
let auth = get_qr_attr!(context, auth).to_string();
|
||||||
|
|
||||||
if !encrypted_and_signed(mime_message, &scanned_fingerprint_of_alice) {
|
if !encrypted_and_signed(context, mime_message, &scanned_fingerprint_of_alice) {
|
||||||
could_not_establish_secure_connection(
|
could_not_establish_secure_connection(
|
||||||
context,
|
context,
|
||||||
contact_chat_id,
|
contact_chat_id,
|
||||||
@@ -548,7 +548,7 @@ pub(crate) fn handle_securejoin_handshake(
|
|||||||
return Ok(HandshakeMessage::Ignore);
|
return Ok(HandshakeMessage::Ignore);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
if !encrypted_and_signed(mime_message, &fingerprint) {
|
if !encrypted_and_signed(context, mime_message, &fingerprint) {
|
||||||
could_not_establish_secure_connection(
|
could_not_establish_secure_connection(
|
||||||
context,
|
context,
|
||||||
contact_chat_id,
|
contact_chat_id,
|
||||||
@@ -675,7 +675,7 @@ pub(crate) fn handle_securejoin_handshake(
|
|||||||
true
|
true
|
||||||
};
|
};
|
||||||
if vg_expect_encrypted
|
if vg_expect_encrypted
|
||||||
&& !encrypted_and_signed(mime_message, &scanned_fingerprint_of_alice)
|
&& !encrypted_and_signed(context, mime_message, &scanned_fingerprint_of_alice)
|
||||||
{
|
{
|
||||||
could_not_establish_secure_connection(
|
could_not_establish_secure_connection(
|
||||||
context,
|
context,
|
||||||
@@ -830,22 +830,26 @@ fn mark_peer_as_verified(context: &Context, fingerprint: impl AsRef<str>) -> Res
|
|||||||
* Tools: Misc.
|
* Tools: Misc.
|
||||||
******************************************************************************/
|
******************************************************************************/
|
||||||
|
|
||||||
fn encrypted_and_signed(mimeparser: &MimeMessage, expected_fingerprint: impl AsRef<str>) -> bool {
|
fn encrypted_and_signed(
|
||||||
|
context: &Context,
|
||||||
|
mimeparser: &MimeMessage,
|
||||||
|
expected_fingerprint: impl AsRef<str>,
|
||||||
|
) -> bool {
|
||||||
if !mimeparser.was_encrypted() {
|
if !mimeparser.was_encrypted() {
|
||||||
warn!(mimeparser.context, "Message not encrypted.",);
|
warn!(context, "Message not encrypted.",);
|
||||||
false
|
false
|
||||||
} else if mimeparser.signatures.is_empty() {
|
} else if mimeparser.signatures.is_empty() {
|
||||||
warn!(mimeparser.context, "Message not signed.",);
|
warn!(context, "Message not signed.",);
|
||||||
false
|
false
|
||||||
} else if expected_fingerprint.as_ref().is_empty() {
|
} else if expected_fingerprint.as_ref().is_empty() {
|
||||||
warn!(mimeparser.context, "Fingerprint for comparison missing.",);
|
warn!(context, "Fingerprint for comparison missing.",);
|
||||||
false
|
false
|
||||||
} else if !mimeparser
|
} else if !mimeparser
|
||||||
.signatures
|
.signatures
|
||||||
.contains(expected_fingerprint.as_ref())
|
.contains(expected_fingerprint.as_ref())
|
||||||
{
|
{
|
||||||
warn!(
|
warn!(
|
||||||
mimeparser.context,
|
context,
|
||||||
"Message does not match expected fingerprint {}.",
|
"Message does not match expected fingerprint {}.",
|
||||||
expected_fingerprint.as_ref(),
|
expected_fingerprint.as_ref(),
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user