Seal header contents (#591)

This commit is contained in:
Paolo Barbolini
2021-04-01 12:18:38 +02:00
committed by GitHub
parent b10f6ff8de
commit 29affe9398
7 changed files with 83 additions and 34 deletions

View File

@@ -112,7 +112,7 @@ impl TryFrom<&Headers> for Envelope {
fn try_from(headers: &Headers) -> Result<Self, Self::Error> { fn try_from(headers: &Headers) -> Result<Self, Self::Error> {
let from = match headers.get::<header::Sender>() { let from = match headers.get::<header::Sender>() {
// If there is a Sender, use it // If there is a Sender, use it
Some(header::Sender(a)) => Some(a.email.clone()), Some(sender) => Some(Mailbox::from(sender.clone()).email),
// ... else try From // ... else try From
None => match headers.get::<header::From>() { None => match headers.get::<header::From>() {
Some(header::From(a)) => { Some(header::From(a)) => {

View File

@@ -122,10 +122,6 @@ mod executor;
pub mod message; pub mod message;
pub mod transport; pub mod transport;
#[cfg(feature = "builder")]
#[macro_use]
extern crate hyperx;
#[cfg(feature = "async-std1")] #[cfg(feature = "async-std1")]
pub use self::executor::AsyncStd1Executor; pub use self::executor::AsyncStd1Executor;
#[cfg(all(any(feature = "tokio02", feature = "tokio1", feature = "async-std1")))] #[cfg(all(any(feature = "tokio02", feature = "tokio1", feature = "async-std1")))]
@@ -208,9 +204,9 @@ mod test {
let to = Mailboxes::new().with("amousset@example.com".parse().unwrap()); let to = Mailboxes::new().with("amousset@example.com".parse().unwrap());
let mut headers = Headers::new(); let mut headers = Headers::new();
headers.set(header::From(from)); headers.set(header::From::from(from));
headers.set(header::Sender(sender)); headers.set(header::Sender::from(sender));
headers.set(header::To(to)); headers.set(header::To::from(to));
assert_eq!( assert_eq!(
Envelope::try_from(&headers).unwrap(), Envelope::try_from(&headers).unwrap(),
@@ -228,8 +224,8 @@ mod test {
let sender = Mailbox::new(None, "kayo2@example.com".parse().unwrap()); let sender = Mailbox::new(None, "kayo2@example.com".parse().unwrap());
let mut headers = Headers::new(); let mut headers = Headers::new();
headers.set(header::From(from)); headers.set(header::From::from(from));
headers.set(header::Sender(sender)); headers.set(header::Sender::from(sender));
assert!(Envelope::try_from(&headers).is_err(),); assert!(Envelope::try_from(&headers).is_err(),);
} }

View File

@@ -7,11 +7,6 @@ use std::{
str::{from_utf8, FromStr}, str::{from_utf8, FromStr},
}; };
header! {
/// `Content-Id` header, defined in [RFC2045](https://tools.ietf.org/html/rfc2045#section-7)
(ContentId, "Content-ID") => [String]
}
/// `Content-Transfer-Encoding` of the body /// `Content-Transfer-Encoding` of the body
/// ///
/// The `Message` builder takes care of choosing the most /// The `Message` builder takes care of choosing the most

View File

@@ -17,7 +17,7 @@ macro_rules! mailbox_header {
($(#[$doc:meta])*($type_name: ident, $header_name: expr)) => { ($(#[$doc:meta])*($type_name: ident, $header_name: expr)) => {
$(#[$doc])* $(#[$doc])*
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct $type_name(pub Mailbox); pub struct $type_name(Mailbox);
impl Header for $type_name { impl Header for $type_name {
fn header_name() -> &'static str { fn header_name() -> &'static str {
@@ -39,6 +39,20 @@ macro_rules! mailbox_header {
f.fmt_line(&self.0.recode_name(utf8_b::encode)) f.fmt_line(&self.0.recode_name(utf8_b::encode))
} }
} }
impl std::convert::From<Mailbox> for $type_name {
#[inline]
fn from(mailbox: Mailbox) -> Self {
Self(mailbox)
}
}
impl std::convert::From<$type_name> for Mailbox {
#[inline]
fn from(this: $type_name) -> Mailbox {
this.0
}
}
}; };
} }
@@ -46,7 +60,7 @@ macro_rules! mailboxes_header {
($(#[$doc:meta])*($type_name: ident, $header_name: expr)) => { ($(#[$doc:meta])*($type_name: ident, $header_name: expr)) => {
$(#[$doc])* $(#[$doc])*
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
pub struct $type_name(pub Mailboxes); pub struct $type_name(pub(crate) Mailboxes);
impl MailboxesHeader for $type_name { impl MailboxesHeader for $type_name {
fn join_mailboxes(&mut self, other: Self) { fn join_mailboxes(&mut self, other: Self) {
@@ -74,6 +88,20 @@ macro_rules! mailboxes_header {
format_mailboxes(self.0.iter(), f) format_mailboxes(self.0.iter(), f)
} }
} }
impl std::convert::From<Mailboxes> for $type_name {
#[inline]
fn from(mailboxes: Mailboxes) -> Self {
Self(mailboxes)
}
}
impl std::convert::From<$type_name> for Mailboxes {
#[inline]
fn from(this: $type_name) -> Mailboxes {
this.0
}
}
}; };
} }

View File

@@ -4,19 +4,29 @@ use hyperx::{
}; };
use std::{fmt::Result as FmtResult, str::from_utf8}; use std::{fmt::Result as FmtResult, str::from_utf8};
#[derive(Debug, Clone, Copy, PartialEq)] #[derive(Debug, Copy, Clone, PartialEq)]
/// Message format version, defined in [RFC2045](https://tools.ietf.org/html/rfc2045#section-4) /// Message format version, defined in [RFC2045](https://tools.ietf.org/html/rfc2045#section-4)
pub struct MimeVersion { pub struct MimeVersion {
pub major: u8, major: u8,
pub minor: u8, minor: u8,
} }
pub const MIME_VERSION_1_0: MimeVersion = MimeVersion { major: 1, minor: 0 }; pub const MIME_VERSION_1_0: MimeVersion = MimeVersion::new(1, 0);
impl MimeVersion { impl MimeVersion {
pub fn new(major: u8, minor: u8) -> Self { pub const fn new(major: u8, minor: u8) -> Self {
MimeVersion { major, minor } MimeVersion { major, minor }
} }
#[inline]
pub const fn major(self) -> u8 {
self.major
}
#[inline]
pub const fn minor(self) -> u8 {
self.minor
}
} }
impl Default for MimeVersion { impl Default for MimeVersion {

View File

@@ -9,7 +9,7 @@ macro_rules! text_header {
($(#[$attr:meta])* Header($type_name: ident, $header_name: expr )) => { ($(#[$attr:meta])* Header($type_name: ident, $header_name: expr )) => {
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
$(#[$attr])* $(#[$attr])*
pub struct $type_name(pub String); pub struct $type_name(String);
impl Header for $type_name { impl Header for $type_name {
fn header_name() -> &'static str { fn header_name() -> &'static str {
@@ -31,6 +31,20 @@ macro_rules! text_header {
fmt_text(&self.0, f) fmt_text(&self.0, f)
} }
} }
impl From<String> for $type_name {
#[inline]
fn from(text: String) -> Self {
Self(text)
}
}
impl AsRef<str> for $type_name {
#[inline]
fn as_ref(&self) -> &str {
&self.0
}
}
}; };
} }
@@ -69,6 +83,11 @@ text_header!(
/// defined in [draft-melnikov-email-user-agent-00](https://tools.ietf.org/html/draft-melnikov-email-user-agent-00#section-3) /// defined in [draft-melnikov-email-user-agent-00](https://tools.ietf.org/html/draft-melnikov-email-user-agent-00#section-3)
Header(UserAgent, "User-Agent") Header(UserAgent, "User-Agent")
); );
text_header! {
/// `Content-Id` header,
/// defined in [RFC2045](https://tools.ietf.org/html/rfc2045#section-7)
Header(ContentId, "Content-ID")
}
fn parse_text(raw: &[u8]) -> HyperResult<String> { fn parse_text(raw: &[u8]) -> HyperResult<String> {
if let Ok(src) = from_utf8(raw) { if let Ok(src) = from_utf8(raw) {

View File

@@ -167,7 +167,7 @@
//! disposition: header::DispositionType::Inline, //! disposition: header::DispositionType::Inline,
//! parameters: vec![], //! parameters: vec![],
//! }) //! })
//! .header(header::ContentId("<123>".into())) //! .header(header::ContentId::from(String::from("<123>")))
//! .body(image_body), //! .body(image_body),
//! ), //! ),
//! ), //! ),
@@ -318,7 +318,8 @@ impl MessageBuilder {
/// ///
/// Shortcut for `self.header(header::Subject(subject.into()))`. /// Shortcut for `self.header(header::Subject(subject.into()))`.
pub fn subject<S: Into<String>>(self, subject: S) -> Self { pub fn subject<S: Into<String>>(self, subject: S) -> Self {
self.header(header::Subject(subject.into())) let s: String = subject.into();
self.header(header::Subject::from(s))
} }
/// Set `Mime-Version` header to 1.0 /// Set `Mime-Version` header to 1.0
@@ -336,7 +337,7 @@ impl MessageBuilder {
/// ///
/// Shortcut for `self.header(header::Sender(mbox))`. /// Shortcut for `self.header(header::Sender(mbox))`.
pub fn sender(self, mbox: Mailbox) -> Self { pub fn sender(self, mbox: Mailbox) -> Self {
self.header(header::Sender(mbox)) self.header(header::Sender::from(mbox))
} }
/// Set or add mailbox to `From` header /// Set or add mailbox to `From` header
@@ -345,7 +346,7 @@ impl MessageBuilder {
/// ///
/// Shortcut for `self.mailbox(header::From(mbox))`. /// Shortcut for `self.mailbox(header::From(mbox))`.
pub fn from(self, mbox: Mailbox) -> Self { pub fn from(self, mbox: Mailbox) -> Self {
self.mailbox(header::From(mbox.into())) self.mailbox(header::From::from(Mailboxes::from(mbox)))
} }
/// Set or add mailbox to `ReplyTo` header /// Set or add mailbox to `ReplyTo` header
@@ -381,13 +382,13 @@ impl MessageBuilder {
/// Set or add message id to [`In-Reply-To` /// Set or add message id to [`In-Reply-To`
/// header](https://tools.ietf.org/html/rfc5322#section-3.6.4) /// header](https://tools.ietf.org/html/rfc5322#section-3.6.4)
pub fn in_reply_to(self, id: String) -> Self { pub fn in_reply_to(self, id: String) -> Self {
self.header(header::InReplyTo(id)) self.header(header::InReplyTo::from(id))
} }
/// Set or add message id to [`References` /// Set or add message id to [`References`
/// header](https://tools.ietf.org/html/rfc5322#section-3.6.4) /// header](https://tools.ietf.org/html/rfc5322#section-3.6.4)
pub fn references(self, id: String) -> Self { pub fn references(self, id: String) -> Self {
self.header(header::References(id)) self.header(header::References::from(id))
} }
/// Set [Message-Id /// Set [Message-Id
@@ -399,7 +400,7 @@ impl MessageBuilder {
/// `<UUID@HOSTNAME>`. /// `<UUID@HOSTNAME>`.
pub fn message_id(self, id: Option<String>) -> Self { pub fn message_id(self, id: Option<String>) -> Self {
match id { match id {
Some(i) => self.header(header::MessageId(i)), Some(i) => self.header(header::MessageId::from(i)),
None => { None => {
#[cfg(feature = "hostname")] #[cfg(feature = "hostname")]
let hostname = hostname::get() let hostname = hostname::get()
@@ -409,7 +410,7 @@ impl MessageBuilder {
#[cfg(not(feature = "hostname"))] #[cfg(not(feature = "hostname"))]
let hostname = DEFAULT_MESSAGE_ID_DOMAIN.to_string(); let hostname = DEFAULT_MESSAGE_ID_DOMAIN.to_string();
self.header(header::MessageId( self.header(header::MessageId::from(
// https://tools.ietf.org/html/rfc5322#section-3.6.4 // https://tools.ietf.org/html/rfc5322#section-3.6.4
format!("<{}@{}>", Uuid::new_v4(), hostname), format!("<{}@{}>", Uuid::new_v4(), hostname),
)) ))
@@ -420,7 +421,7 @@ impl MessageBuilder {
/// Set [User-Agent /// Set [User-Agent
/// header](https://tools.ietf.org/html/draft-melnikov-email-user-agent-004) /// header](https://tools.ietf.org/html/draft-melnikov-email-user-agent-004)
pub fn user_agent(self, id: String) -> Self { pub fn user_agent(self, id: String) -> Self {
self.header(header::UserAgent(id)) self.header(header::UserAgent::from(id))
} }
/// Force specific envelope (by default it is derived from headers) /// Force specific envelope (by default it is derived from headers)
@@ -595,7 +596,7 @@ mod test {
.header(header::To( .header(header::To(
vec!["Pony O.P. <pony@domain.tld>".parse().unwrap()].into(), vec!["Pony O.P. <pony@domain.tld>".parse().unwrap()].into(),
)) ))
.header(header::Subject("яңа ел белән!".into())) .header(header::Subject::from(String::from("яңа ел белән!")))
.body(String::from("Happy new year!")) .body(String::from("Happy new year!"))
.unwrap(); .unwrap();
@@ -641,7 +642,7 @@ mod test {
disposition: header::DispositionType::Inline, disposition: header::DispositionType::Inline,
parameters: vec![], parameters: vec![],
}) })
.header(header::ContentId("<123>".into())) .header(header::ContentId::from(String::from("<123>")))
.body(img), .body(img),
), ),
) )