Introduced e-mail parsing and minor error handling for encoding or parsing issues

This commit is contained in:
Philip (a-0) 2022-09-03 21:02:22 +02:00
parent 5ac1425b44
commit ad3245f884
3 changed files with 58 additions and 3 deletions

View file

@ -11,6 +11,7 @@ serde = "1.0.144"
serde_yaml = "0.9.10" serde_yaml = "0.9.10"
postbus = "0.2.0" postbus = "0.2.0"
mailparse = "0.13.8"
ruma = "0.6.4" ruma = "0.6.4"
matrix-sdk = "0.5.0" matrix-sdk = "0.5.0"

View file

@ -1,5 +1,6 @@
use std::sync::Arc; use std::sync::Arc;
use async_trait::async_trait; use async_trait::async_trait;
use mailparse::ParsedMail;
use matrix_sdk::Client; use matrix_sdk::Client;
use postbus::{Handler, SmtpService, SmtpState, command::Mailbox}; use postbus::{Handler, SmtpService, SmtpState, command::Mailbox};
use crate::config::Mapping; use crate::config::Mapping;
@ -56,8 +57,61 @@ impl Handler for ToMatrixConverter {
} }
async fn save(&self, state: &SmtpState) -> bool { async fn save(&self, state: &SmtpState) -> bool {
for recipient in &state.recipients { for recipient in &state.recipients {
matrix::send(&state.from, &recipient, &state.data, &self.matrix_clients, &self.mappings).await; match mailparse::parse_mail(state.data.as_bytes()) {
Ok(mail) => matrix::send(&state.from, &recipient,
&mail_to_plain_message(&mail, &state.from, &recipient),
&mail_to_html_message(&mail, &state.from, &recipient),
&self.matrix_clients, &self.mappings).await,
Err(e) => {
println!("{}", e);
matrix::send(&state.from, &recipient,
&format!("Error parsing e-mail. This is a dump of the whole data section:\n{}", &state.data),
&format!("Error parsing e-mail. This is a dump of the whole data section:<br>{}", &state.data),
&self.matrix_clients, &self.mappings).await;
}
}
} }
true true
} }
} }
fn mail_to_plain_message(mail: &ParsedMail, from: &Option<Mailbox>, to: &Mailbox) -> String {
format!("From {} to {}\nSubject: {}\n---\n{}",
match from {
Some(fr) => mailbox_to_addr(fr),
None => "[unknown sender]".to_string(),
},
mailbox_to_addr(to),
get_subject(mail),
match mail.get_body() {
Ok(body) => body,
Err(e) => "WARNING! E-mail content could not be decoded.".to_string(),
}
)
}
fn mail_to_html_message(mail: &ParsedMail, from: &Option<Mailbox>, to: &Mailbox) -> String {
format!("<b>From</b> {} <b>to</b> {}<br><b>Subject:</b> {}<hline>{}",
match from {
Some(fr) => mailbox_to_addr(fr),
None => "[unknown sender]".to_string(),
},
mailbox_to_addr(to),
get_subject(mail),
match mail.get_body() {
Ok(body) => body,
Err(e) => "<b>WARNING! E-mail content could not be decoded.<b>".to_string(),
}
)
}
fn get_subject(mail: &ParsedMail) -> String {
for header in &mail.headers {
if header.get_key() == "Subject" {
return header.get_value();
}
}
return String::from("[no subject found]");
}
pub fn mailbox_to_addr(mb: &Mailbox) -> String {
format!("{}@{}", mb.local, mb.domain.0)
}

View file

@ -84,7 +84,7 @@ async fn client_from_mxid(mxid: &str, clients: &Vec<Client>) -> Option<Client> {
None None
} }
pub async fn send(from_mail: &Option<Mailbox>, recipient: &Mailbox, content: &str, clients: &Vec<Client>, mappings: &Vec<Mapping>) { pub async fn send(from_mail: &Option<Mailbox>, recipient: &Mailbox, plain_content: &str, html_content: &str, clients: &Vec<Client>, mappings: &Vec<Mapping>) {
for mapping in mappings { for mapping in mappings {
let mut applies = true; let mut applies = true;
@ -151,7 +151,7 @@ pub async fn send(from_mail: &Option<Mailbox>, recipient: &Mailbox, content: &st
continue; continue;
} }
}; };
match room.send(RoomMessageEventContent::text_html(content, content), None).await { match room.send(RoomMessageEventContent::text_html(plain_content, html_content), None).await {
Ok(_) => (), Ok(_) => (),
Err(_e) => println!("Sending message failed"), Err(_e) => println!("Sending message failed"),
}; };