1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
use std::io::Write;
#[cfg(feature = "serdex")]
use serde::{Deserialize, Serialize};
use crate::{
codec::Encode,
types::{address::Address, core::NString},
List1OrNil,
};
/// The fields of the envelope structure are in the following
/// order: date, subject, from, sender, reply-to, to, cc, bcc,
/// in-reply-to, and message-id.
/// The date, subject, in-reply-to, and message-id fields are strings.
/// The from, sender, reply-to, to, cc, and bcc fields are parenthesized lists of address structures.
///
/// See [Address](struct.Address.html).
///
/// [RFC-2822] group syntax is indicated by a special form of
/// address structure in which the host name field is NIL. If the
/// mailbox name field is also NIL, this is an end of group marker
/// (semi-colon in RFC 822 syntax). If the mailbox name field is
/// non-NIL, this is a start of group marker, and the mailbox name
/// field holds the group name phrase.
///
/// 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.
///
/// Note: some servers may return a NIL envelope member in the
/// "present but empty" case. Clients SHOULD treat NIL and
/// empty string as identical.
///
/// Note: [RFC-2822] requires that all messages have a valid
/// Date header. Therefore, the date member in the envelope can
/// not be NIL or the empty string.
///
/// Note: [RFC-2822] requires that the In-Reply-To and
/// Message-ID headers, if present, have non-empty content.
/// Therefore, the in-reply-to and message-id members in the
/// envelope can not be the empty string.
///
/// If the From, To, cc, and bcc header lines are absent in the
/// [RFC-2822] header, or are present but empty, the corresponding
/// member of the envelope is NIL.
///
/// 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.
/// TODO: many invariants here...
#[cfg_attr(feature = "serdex", derive(Serialize, Deserialize))]
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct Envelope {
pub date: NString, // TODO: must not be empty string
pub subject: NString,
pub from: Vec<Address>, // encode as nil if empty?
pub sender: Vec<Address>, // TODO: set to from if absent or empty
pub reply_to: Vec<Address>, // TODO: set to from if absent or empty
pub to: Vec<Address>, // encode as nil if empty?
pub cc: Vec<Address>, // encode as nil if empty?
pub bcc: Vec<Address>, // encode as nil if empty?
pub in_reply_to: NString, // TODO: must not be empty string
pub message_id: NString, // TODO: must not be empty string
}
impl Encode for Envelope {
fn encode(&self, writer: &mut impl Write) -> std::io::Result<()> {
writer.write_all(b"(")?;
self.date.encode(writer)?;
writer.write_all(b" ")?;
self.subject.encode(writer)?;
writer.write_all(b" ")?;
List1OrNil(&self.from, b"").encode(writer)?;
writer.write_all(b" ")?;
List1OrNil(&self.sender, b"").encode(writer)?;
writer.write_all(b" ")?;
List1OrNil(&self.reply_to, b"").encode(writer)?;
writer.write_all(b" ")?;
List1OrNil(&self.to, b"").encode(writer)?;
writer.write_all(b" ")?;
List1OrNil(&self.cc, b"").encode(writer)?;
writer.write_all(b" ")?;
List1OrNil(&self.bcc, b"").encode(writer)?;
writer.write_all(b" ")?;
self.in_reply_to.encode(writer)?;
writer.write_all(b" ")?;
self.message_id.encode(writer)?;
writer.write_all(b")")
}
}