Replace Envelope::message_id_display() with Display impls

Signed-off-by: Manos Pitsidianakis <manos@pitsidianak.is>
pull/473/head
Manos Pitsidianakis 2 months ago
parent 6fbf569fe0
commit 11798be804
No known key found for this signature in database
GPG Key ID: 7729C7707F7E09D0

@ -630,7 +630,7 @@ impl Account {
JobRequest::Generic {
name: format!(
"Update envelope {} in sqlite3 cache",
envelope.message_id_display()
envelope.message_id().display_brackets()
)
.into(),
handle,

@ -60,7 +60,7 @@ impl Account {
#[cfg(feature = "sqlite3")]
pub(super) fn update_cached_env(&mut self, env: Envelope, old_hash: Option<EnvelopeHash>) {
if self.settings.conf.search_backend == SearchBackend::Sqlite3 {
let msg_id = env.message_id_display().to_string();
let msg_id = env.message_id().to_string();
let name = self.name.clone();
let backend = self.backend.clone();
let fut = async move {

@ -335,15 +335,15 @@ impl Composer {
if !acc.is_empty() {
acc.push(' ');
}
acc.push_str(&x.to_string());
acc.push_str(&x.display_brackets().to_string());
acc
}),
envelope.message_id_display()
envelope.message_id().display_brackets()
),
);
ret.draft.set_header(
HeaderName::IN_REPLY_TO,
envelope.message_id_display().into(),
envelope.message_id().display_brackets().to_string(),
);
if let Some(reply_to) = envelope.other_headers().get(HeaderName::TO) {
@ -540,7 +540,7 @@ To: {}
let mut attachment = AttachmentBuilder::new(b"");
let mut disposition: ContentDisposition = ContentDispositionKind::Attachment.into();
{
disposition.filename = Some(format!("{}.eml", env.message_id_raw()));
disposition.filename = Some(format!("{}.eml", env.message_id()));
}
attachment
.set_raw(bytes.to_vec())

@ -800,7 +800,7 @@ pub trait MailListingTrait: ListingTrait {
.collect();
if path.is_dir() {
if envs.len() == 1 {
path.push(format!("{}.mbox", envs[0].message_id_raw()));
path.push(format!("{}.mbox", envs[0].message_id()));
} else {
let now = datetime::timestamp_to_string(
datetime::now(),
@ -810,7 +810,7 @@ pub trait MailListingTrait: ListingTrait {
path.push(format!(
"{}-{}-{}_envelopes.mbox",
now,
envs[0].message_id_raw(),
envs[0].message_id(),
envs.len(),
));
}

@ -582,15 +582,14 @@ impl Component for MailView {
}
Err(err) => {
let err_string = format!(
"Failed to open envelope {}: {}",
"Failed to open envelope {:?}: {}",
context.accounts[&account_hash]
.collection
.envelopes
.read()
.unwrap()
.get(&env_hash)
.map(|env| env.message_id_display())
.unwrap_or_else(|| "Not found".into()),
.map(|env| env.message_id()),
err
);
log::error!("{err_string}");

@ -837,7 +837,7 @@ impl Component for EnvelopeView {
(HeaderName::SUBJECT, envelope.subject()),
(
HeaderName::MESSAGE_ID,
format!("<{}>", envelope.message_id_raw())
envelope.message_id().display_brackets().to_string()
)
);
if self.view_settings.expand_headers {
@ -1496,7 +1496,7 @@ impl Component for EnvelopeView {
let mut path = std::path::Path::new(path).to_path_buf().expand();
if path.is_dir() {
path.push(format!("{}.eml", self.mail.message_id_raw()));
path.push(format!("{}.eml", self.mail.message_id()));
}
if path.is_relative() {
path = context.current_dir().join(&path);
@ -1567,7 +1567,7 @@ impl Component for EnvelopeView {
} else if a_i == 0 {
// Save entire message as eml
if path.is_dir() {
path.push(format!("{}.eml", self.mail.message_id_raw()));
path.push(format!("{}.eml", self.mail.message_id()));
}
if path.is_relative() {
path = context.current_dir().join(&path);

@ -171,10 +171,7 @@ impl AccountCache {
let body = match op.await.map(|bytes| envelope.body_bytes(&bytes)) {
Ok(body) => body.text(Text::Plain),
Err(err) => {
log::error!(
"Failed to open envelope {}: {err}",
envelope.message_id_display(),
);
log::error!("Failed to open envelope {}: {err}", envelope.message_id());
return Err(err);
}
};
@ -187,13 +184,10 @@ impl AccountCache {
"INSERT OR IGNORE INTO accounts (name) VALUES (?1)",
params![acc_name,],
) {
log::error!(
"Failed to insert envelope {}: {err}",
envelope.message_id_display(),
);
log::error!("Failed to insert envelope {}: {err}", envelope.message_id());
return Err(Error::new(format!(
"Failed to insert envelope {}: {err}",
envelope.message_id_display(),
envelope.message_id(),
)));
}
let account_id: i32 = {
@ -223,7 +217,7 @@ impl AccountCache {
envelope.field_cc_to_string(),
envelope.field_bcc_to_string(),
envelope.subject().into_owned().trim_end_matches('\u{0}'),
envelope.message_id_display().to_string(),
envelope.message_id().to_string(),
envelope
.in_reply_to_display()
.map(|f| f.to_string())
@ -238,10 +232,7 @@ impl AccountCache {
.map_err(|e| Error::new(e.to_string()))
{
drop(tx);
log::error!(
"Failed to insert envelope {}: {err}",
envelope.message_id_display(),
);
log::error!("Failed to insert envelope {}: {err}", envelope.message_id());
} else {
tx.commit()?;
}
@ -375,7 +366,7 @@ impl AccountCache {
e.field_cc_to_string(),
e.field_bcc_to_string(),
e.subject().into_owned().trim_end_matches('\u{0}'),
e.message_id_display().to_string(),
e.message_id().to_string(),
e.in_reply_to_display()
.map(|f| f.to_string())
.unwrap_or_default(),
@ -387,7 +378,7 @@ impl AccountCache {
],
)
.chain_err_summary(|| {
format!("Failed to insert envelope {}", e.message_id_display())
format!("Failed to insert envelope {}", e.message_id())
})?;
}
}

@ -81,7 +81,7 @@ ouiijDaaCCGQRgrpH3q4QYYXWDihxBE+7KCDDjnUIEVAADs=
let envelope = Envelope::from_bytes(raw_mail.as_bytes(), None).expect("Could not parse mail");
assert_eq!(envelope.subject().as_ref(), "gratuitously encoded subject");
assert_eq!(envelope.message_id_display().as_ref(), "<h2g7f.z0gy2pgaen5m@example.com>");
assert_eq!(&envelope.message_id().display_bracket().to_string(), "<h2g7f.z0gy2pgaen5m@example.com>");
let body = envelope.body_bytes(raw_mail.as_bytes());
assert_eq!(body.content_type().to_string().as_str(), "multipart/mixed");

@ -75,10 +75,7 @@
//!
//! let envelope = Envelope::from_bytes(raw_mail.as_bytes(), None).expect("Could not parse mail");
//! assert_eq!(envelope.subject().as_ref(), "gratuitously encoded subject");
//! assert_eq!(
//! envelope.message_id_display().as_ref(),
//! "<h2g7f.z0gy2pgaen5m@example.com>"
//! );
//! assert_eq!(envelope.message_id(), "h2g7f.z0gy2pgaen5m@example.com");
//!
//! let body = envelope.body_bytes(raw_mail.as_bytes());
//! assert_eq!(body.content_type().to_string().as_str(), "multipart/mixed");
@ -298,8 +295,8 @@ impl std::fmt::Debug for Envelope {
.field("Date", &self.date)
.field("From", &self.from)
.field("To", &self.to)
.field("Message-ID", &self.message_id_display())
.field("In-Reply-To", &self.in_reply_to_display())
.field("Message-ID", &self.message_id)
.field("In-Reply-To", &self.in_reply_to)
.field("References", &self.references)
.field("Flags", &self.flags)
.field("Hash", &self.hash)
@ -366,7 +363,7 @@ impl Envelope {
let (headers, body) = match parser::mail(bytes) {
Ok(v) => v,
Err(e) => {
debug!("error in parsing mail\n{:?}\n", e);
log::debug!("error in parsing mail\n{:?}\n", e);
let error_msg = String::from("Mail cannot be shown because of errors.");
return Err(Error::new(error_msg));
}
@ -438,7 +435,7 @@ impl Envelope {
self.has_attachments =
Attachment::check_if_has_attachments_quick(body, boundary);
} else {
debug!(
log::debug!(
"{:?} has no boundary field set in multipart/mixed content-type \
field.",
&self
@ -649,14 +646,6 @@ impl Envelope {
&self.message_id
}
pub fn message_id_display(&self) -> Cow<str> {
String::from_utf8_lossy(self.message_id.val())
}
pub fn message_id_raw(&self) -> Cow<str> {
String::from_utf8_lossy(self.message_id.raw())
}
pub fn set_date(&mut self, new_val: &[u8]) -> &mut Self {
let new_val = new_val.trim();
self.date = String::from_utf8_lossy(new_val).into_owned();

@ -555,6 +555,28 @@ impl StrBuilder {
#[derive(Clone, Default, Deserialize, Serialize)]
pub struct MessageID(pub Vec<u8>, pub StrBuilder);
impl MessageID {
pub fn display_brackets(&self) -> impl std::fmt::Display + '_ {
MessageIDBracket(self)
}
/// Formats a slice of [`MessageID`]es with their
/// [`MessageID::display_brackets`] method, separated by comma or
/// `separator` if passed.
pub fn display_slice(slice: &[Self], separator: Option<&str>) -> String {
let separator = separator.unwrap_or(", ");
match slice.first() {
None => String::new(),
Some(f) if slice.len() == 1 => f.display_brackets().to_string(),
Some(_) => slice
.iter()
.map(|a| a.display_brackets().to_string())
.collect::<Vec<String>>()
.join(separator),
}
}
}
impl StrBuild for MessageID {
fn new(string: &[u8], slice: &[u8]) -> Self {
let offset = string.find(slice).unwrap_or(0);
@ -578,15 +600,24 @@ impl StrBuild for MessageID {
}
}
struct MessageIDBracket<'a>(&'a MessageID);
impl<'a> std::fmt::Display for MessageIDBracket<'a> {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(fmt, "<")?;
write!(fmt, "{}", self.0)?;
write!(fmt, ">")
}
}
impl std::fmt::Display for MessageID {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
if self.val().is_ascii() {
write!(f, "{}", unsafe {
std::str::from_utf8_unchecked(self.val())
})
} else {
write!(f, "{}", String::from_utf8_lossy(self.val()))
}
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
let val = String::from_utf8_lossy(self.val());
write!(
fmt,
"{}",
val.trim().trim_start_matches('<').trim_end_matches('>')
)
}
}
@ -596,6 +627,8 @@ impl PartialEq for MessageID {
}
}
impl Eq for MessageID {}
impl PartialEq<str> for MessageID {
fn eq(&self, other: &str) -> bool {
self.raw()
@ -615,7 +648,13 @@ impl PartialEq<&str> for MessageID {
impl std::fmt::Debug for MessageID {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
write!(f, "{}", String::from_utf8(self.raw().to_vec()).unwrap())
write!(f, "{}", String::from_utf8_lossy(self.raw()))
}
}
impl Hash for MessageID {
fn hash<H: Hasher>(&self, state: &mut H) {
self.raw().hash(state)
}
}

@ -199,17 +199,17 @@ impl Draft {
.iter()
.fold(String::new(), |mut acc, x| {
if !acc.is_empty() {
acc.push(' ');
acc.push_str("\n ");
}
acc.push_str(&x.to_string());
acc.push_str(&x.display_brackets().to_string());
acc
}),
envelope.message_id_display()
envelope.message_id().display_brackets()
),
);
ret.headers_mut().insert(
HeaderName::IN_REPLY_TO,
envelope.message_id_display().into(),
envelope.message_id().display_brackets().to_string(),
);
// "Mail-Followup-To/(To+Cc+(Mail-Reply-To/Reply-To/From)) for follow-up,
// Mail-Reply-To/Reply-To/From for reply-to-author."

@ -34,7 +34,6 @@ use std::{
time::{Duration, Instant},
};
use crate::get_path_hash;
mod store;
pub use store::*;
#[macro_use]
@ -49,7 +48,9 @@ pub use connection::*;
use crate::{
backends::prelude::*,
email::address::{MessageID, StrBuild},
error::{Error, ErrorKind, Result, ResultIntoError},
get_path_hash,
utils::futures::timeout,
};
pub type UID = usize;
@ -118,7 +119,7 @@ pub struct UIDStore {
account_hash: AccountHash,
account_name: Arc<str>,
capabilities: Arc<Mutex<Capabilities>>,
message_id_index: Arc<FutureMutex<HashMap<String, EnvelopeHash>>>,
message_id_index: Arc<FutureMutex<HashMap<MessageID, EnvelopeHash>>>,
hash_index: Arc<Mutex<HashMap<EnvelopeHash, (UID, MailboxHash)>>>,
uid_index: Arc<FutureMutex<HashMap<(MailboxHash, UID), EnvelopeHash>>>,
@ -291,7 +292,12 @@ impl MailBackend for NntpType {
res.split_rn()
.skip(1)
.map(|s| s.trim())
.filter(|msg_id| !message_id_lck.contains_key(*msg_id))
.filter(|msg_id| {
!message_id_lck.contains_key(&MessageID::new(
msg_id.as_bytes(),
msg_id.as_bytes(),
))
})
.map(str::to_string)
.collect::<Vec<String>>()
};
@ -319,7 +325,7 @@ impl MailBackend for NntpType {
unseen.insert_new(env.hash());
}
env_hash_set.insert(env.hash());
message_id_lck.insert(env.message_id_display().to_string(), env.hash());
message_id_lck.insert(env.message_id().clone(), env.hash());
hash_index_lck.insert(env.hash(), (num, mailbox_hash));
uid_index_lck.insert((mailbox_hash, num), env.hash());
latest_article = std::cmp::max(latest_article, env.timestamp);
@ -957,7 +963,7 @@ impl FetchState {
} else {
unseen.insert_new(env.hash());
}
message_id_lck.insert(env.message_id_display().to_string(), env.hash());
message_id_lck.insert(env.message_id().clone(), env.hash());
hash_index_lck.insert(env.hash(), (num, mailbox_hash));
uid_index_lck.insert((mailbox_hash, num), env.hash());
if let Some(ref mut v) = latest_article {

@ -1464,7 +1464,7 @@ fn print_threadnodes(
"\t".repeat(level),
node_hash,
"\t".repeat(level),
nodes[&node_hash].message().as_ref().map(|m| format!("{} - {}\n{}\t\t{}", envelopes[m].message_id_display(), envelopes[m].subject(), "\t".repeat(level), envelopes[m].references().iter().map(ToString::to_string).collect::<Vec<String>>().join(", "))).unwrap_or_else(|| "None".to_string()),
nodes[&node_hash].message().as_ref().map(|m| format!("{} - {}\n{}\t\t{}", envelopes[m].message_id(), envelopes[m].subject(), "\t".repeat(level), envelopes[m].references().iter().map(ToString::to_string).collect::<Vec<String>>().join(", "))).unwrap_or_else(|| "None".to_string()),
"\t".repeat(level),
nodes[&node_hash].parent().as_ref().map(ToString::to_string).unwrap_or_else(|| "None".to_string()),
"\t".repeat(level),

Loading…
Cancel
Save