diff options
author | Quentin Dufour <quentin@deuxfleurs.fr> | 2024-01-04 20:54:21 +0100 |
---|---|---|
committer | Quentin Dufour <quentin@deuxfleurs.fr> | 2024-01-04 20:54:21 +0100 |
commit | 2a9ae1297bf5c4a4b9552eeabb00246d76004f63 (patch) | |
tree | d3f3a14f2a05ef34ff9461ef82b072b64e06a209 /src/imap/imf_view.rs | |
parent | b22df840dbda699957ae48eca019e3ecfa493bd9 (diff) | |
download | aerogramme-2a9ae1297bf5c4a4b9552eeabb00246d76004f63.tar.gz aerogramme-2a9ae1297bf5c4a4b9552eeabb00246d76004f63.zip |
bcp commit
Diffstat (limited to 'src/imap/imf_view.rs')
-rw-r--r-- | src/imap/imf_view.rs | 129 |
1 files changed, 129 insertions, 0 deletions
diff --git a/src/imap/imf_view.rs b/src/imap/imf_view.rs new file mode 100644 index 0000000..dce53e6 --- /dev/null +++ b/src/imap/imf_view.rs @@ -0,0 +1,129 @@ +use std::borrow::Cow; +use std::iter::zip; +use std::num::NonZeroU32; +use std::sync::Arc; + +use anyhow::{anyhow, bail, Error, Result}; +use chrono::{Offset, TimeZone, Utc}; + +use futures::stream::{FuturesOrdered, StreamExt}; + +use imap_codec::imap_types::body::{BasicFields, Body as FetchBody, BodyStructure, SpecificFields}; +use imap_codec::imap_types::core::{AString, Atom, IString, NString, NonEmptyVec}; +use imap_codec::imap_types::datetime::DateTime; +use imap_codec::imap_types::envelope::{Address, Envelope}; +use imap_codec::imap_types::fetch::{ + MacroOrMessageDataItemNames, MessageDataItem, MessageDataItemName, Section as FetchSection, +}; +use imap_codec::imap_types::flag::{Flag, FlagFetch, FlagPerm, StoreResponse, StoreType}; +use imap_codec::imap_types::response::{Code, Data, Status}; +use imap_codec::imap_types::sequence::{self, SequenceSet}; + +use eml_codec::{ + header, imf, mime, + mime::r#type::Deductible, + part::{composite::Message, AnyPart}, +}; + +use crate::cryptoblob::Key; +use crate::imap::response::Body; +use crate::mail::mailbox::{MailMeta, Mailbox}; +use crate::mail::uidindex::{ImapUid, ImapUidvalidity, UidIndex}; +use crate::mail::unique_ident::UniqueIdent; + + + + +/// Envelope rules are defined in RFC 3501, section 7.4.2 +/// https://datatracker.ietf.org/doc/html/rfc3501#section-7.4.2 +/// +/// Some important notes: +/// +/// If the Sender or Reply-To lines are absent in the [RFC-2822] +/// header, or are present but empty, the server sets the +/// corresponding member of the envelope to be the same value as +/// the from member (the client is not expected to know to do +/// this). Note: [RFC-2822] requires that all messages have a valid +/// From header. Therefore, the from, sender, and reply-to +/// members in the envelope can not be NIL. +/// +/// If the Date, Subject, In-Reply-To, and Message-ID header lines +/// are absent in the [RFC-2822] header, the corresponding member +/// of the envelope is NIL; if these header lines are present but +/// empty the corresponding member of the envelope is the empty +/// string. + +//@FIXME return an error if the envelope is invalid instead of panicking +//@FIXME some fields must be defaulted if there are not set. +pub fn message_envelope(msg: &imf::Imf) -> Envelope<'static> { + let from = msg.from.iter().map(convert_mbx).collect::<Vec<_>>(); + + Envelope { + date: NString( + msg.date + .as_ref() + .map(|d| IString::try_from(d.to_rfc3339()).unwrap()), + ), + subject: NString( + msg.subject + .as_ref() + .map(|d| IString::try_from(d.to_string()).unwrap()), + ), + sender: msg + .sender + .as_ref() + .map(|v| vec![convert_mbx(v)]) + .unwrap_or(from.clone()), + reply_to: if msg.reply_to.is_empty() { + from.clone() + } else { + convert_addresses(&msg.reply_to) + }, + from, + to: convert_addresses(&msg.to), + cc: convert_addresses(&msg.cc), + bcc: convert_addresses(&msg.bcc), + in_reply_to: NString( + msg.in_reply_to + .iter() + .next() + .map(|d| IString::try_from(d.to_string()).unwrap()), + ), + message_id: NString( + msg.msg_id + .as_ref() + .map(|d| IString::try_from(d.to_string()).unwrap()), + ), + } +} + +pub fn convert_addresses(addrlist: &Vec<imf::address::AddressRef>) -> Vec<Address<'static>> { + let mut acc = vec![]; + for item in addrlist { + match item { + imf::address::AddressRef::Single(a) => acc.push(convert_mbx(a)), + imf::address::AddressRef::Many(l) => acc.extend(l.participants.iter().map(convert_mbx)), + } + } + return acc; +} + +pub fn convert_mbx(addr: &imf::mailbox::MailboxRef) -> Address<'static> { + Address { + name: NString( + addr.name + .as_ref() + .map(|x| IString::try_from(x.to_string()).unwrap()), + ), + // SMTP at-domain-list (source route) seems obsolete since at least 1991 + // https://www.mhonarc.org/archive/html/ietf-822/1991-06/msg00060.html + adl: NString(None), + mailbox: NString(Some( + IString::try_from(addr.addrspec.local_part.to_string()).unwrap(), + )), + host: NString(Some( + IString::try_from(addr.addrspec.domain.to_string()).unwrap(), + )), + } +} + |