Make the gmx test pass

This commit is contained in:
Hocuri
2020-06-10 14:44:55 +02:00
parent e1711855cc
commit 777df24c75
5 changed files with 530 additions and 47 deletions

View File

@@ -2356,7 +2356,7 @@ mod tests {
"snaerituhaeirns@gmail.com",
"9c9c2a32-056b-3592-c372-d7e8f0bd4bc2@gmx.de",
include_bytes!("../test-data/message/gmx_ndn.eml"),
"Delivery Status Notification (Failure) ** Die Adresse wurde nicht gefunden **\n\nIhre Nachricht wurde nicht an assidhfaaspocwaeofi@gmail.com zugestellt, weil die Adresse nicht gefunden wurde oder keine E-Mails empfangen kann.\n\nHier erfahren Sie mehr: https://support.google.com/mail/?p=NoSuchUser\n\nAntwort:\n\n550 5.1.1 The email account that you tried to reach does not exist. Please try double-checking the recipient\'s email address for typos or unnecessary spaces. Learn more at https://support.google.com/mail/?p=NoSuchUser i18sor6261697wrs.38 - gsmtp",
"Mail delivery failed: returning message to sender This message was created automatically by mail delivery software.\n\nA message that you sent could not be delivered to one or more of\nits recipients. This is a permanent error. The following address(es)\nfailed:\n\nsnaerituhaeirns@gmail.com:\nSMTP error from remote server for RCPT TO command, host: gmail-smtp-in.l.google.com (66.102.1.27) reason: 550-5.1.1 The email account that you tried to reach does not exist. Please\n try\n550-5.1.1 double-checking the recipient\'s email address for typos or\n550-5.1.1 unnecessary spaces. Learn more at\n550 5.1.1 https://support.google.com/mail/?p=NoSuchUser f6si2517766wmc.21\n9 - gsmtp"
)
.await;
}
@@ -2466,7 +2466,7 @@ mod tests {
let chats = Chatlist::try_load(&t.ctx, 0, None, None).await.unwrap();
let msg_id = chats.get_msg_id(0).unwrap();
let raw = include_bytes!("../test-data/message/gmail_ndn.eml");
let raw = include_bytes!("../test-data/message/gmail_ndn_group.eml");
dc_receive_imf(&t.ctx, raw, "INBOX", 1, false)
.await
.unwrap();

View File

@@ -3,6 +3,7 @@ use std::future::Future;
use std::pin::Pin;
use deltachat_derive::{FromSql, ToSql};
use lazy_static::lazy_static;
use lettre_email::mime::{self, Mime};
use mailparse::{addrparse_header, DispositionType, MailHeader, MailHeaderMap, SingleInfo};
@@ -186,6 +187,7 @@ impl MimeMessage {
failed_msg: None,
};
parser.parse_mime_recursive(context, &mail).await?;
parser.heuristically_parse_ndn().await;
parser.parse_headers(context)?;
Ok(parser)
@@ -855,6 +857,82 @@ impl MimeMessage {
Ok(None)
}
fn process_delivery_status(
&self,
context: &Context,
report: &mailparse::ParsedMail<'_>,
) -> Result<Option<FailedMsg>> {
// parse as mailheaders
if let Some(original_msg) = report
.subparts
.iter()
.find(|p| p.ctype.mimetype.contains("rfc822"))
{
let report_body = original_msg.get_body_raw()?;
let (report_fields, _) = mailparse::parse_headers(&report_body)?;
if let Some(original_message_id) = report_fields
.get_header_value(HeaderDef::MessageId)
.and_then(|v| parse_message_id(&v).ok())
{
let mut to_list = get_all_addresses_from_header(&report.headers, |header_key| {
header_key == "X-Failed-Recipients"
});
let to = if to_list.len() == 1 {
Some(to_list.pop().unwrap())
} else {
None // We do not know which recipient failed
};
return Ok(Some(FailedMsg {
rfc724_mid: original_message_id,
failed_recipient: to.map(|s| s.addr),
}));
}
warn!(
context,
"ignoring unknown ndn-notification, Message-Id: {:?}",
report_fields.get_header_value(HeaderDef::MessageId)
);
}
Ok(None)
}
async fn heuristically_parse_ndn(&mut self) -> Option<()> {
if self
.get(HeaderDef::Subject)?
.to_ascii_lowercase()
.contains("fail")
&& self
.get(HeaderDef::From_)?
.to_ascii_lowercase()
.contains("daemon")
&& self.failed_msg.is_none()
{
for line in self
.parts
.iter()
.filter_map(|p| p.msg_raw.as_ref())
.flat_map(|p| p.lines())
{
lazy_static! {
static ref RE: regex::Regex = regex::Regex::new(r"Message-ID:(.*)").unwrap();
}
if let Some(c) = RE.captures(line) {
if let Ok(original_message_id) = parse_message_id(&c[1]) {
self.failed_msg = Some(FailedMsg {
rfc724_mid: original_message_id,
failed_recipient: None,
})
}
}
}
}
None
}
/// Handle reports (only MDNs for now)
pub async fn handle_reports(
&self,
@@ -877,54 +955,17 @@ impl MimeMessage {
}
if let Some(original_message_id) = &self.failed_msg {
let error = parts
.iter()
.find(|p| p.typ == Viewtype::Text)
.map(|p| &p.msg);
let error = parts.iter().find(|p| p.typ == Viewtype::Text).map(|p| {
let msg = &p.msg;
match msg.find("\n--- ") {
Some(footer_start) => &msg[..footer_start],
None => msg,
}
.trim()
});
message::ndn_from_ext(context, original_message_id, error).await
}
}
fn process_delivery_status(
&self,
context: &Context,
report: &mailparse::ParsedMail<'_>,
) -> Result<Option<FailedMsg>> {
// parse as mailheaders
if let Some(original_msg) = report
.subparts
.iter()
.find(|p| p.ctype.mimetype.contains("rfc822"))
{
let report_body = original_msg.get_body_raw()?;
let (report_fields, _) = mailparse::parse_headers(&report_body)?;
if let Some(original_message_id) = report_fields
.get_header_value(HeaderDef::MessageId)
.and_then(|v| parse_message_id(&v).ok())
{
let mut to_list = get_recipients(&report_fields);
let to = if to_list.len() == 1 {
Some(to_list.pop().unwrap())
} else {
None // We do not know which recipient failed
};
return Ok(Some(FailedMsg {
rfc724_mid: original_message_id,
failed_recipient: to.map(|s| s.addr),
}));
}
warn!(
context,
"ignoring unknown ndn-notification, Message-Id: {:?}",
report_fields.get_header_value(HeaderDef::MessageId)
);
}
Ok(None)
}
}
async fn update_gossip_peerstates(