Compare commits
1 Commits
release-0.
...
paolobarbo
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3b5d760f8 |
@@ -1,11 +1,11 @@
|
||||
use std::{mem, ops::Deref};
|
||||
use std::{mem, ops::Deref, sync::Arc};
|
||||
|
||||
use crate::message::header::ContentTransferEncoding;
|
||||
|
||||
/// A [`Message`][super::Message] or [`SinglePart`][super::SinglePart] body that has already been encoded.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Body {
|
||||
buf: Vec<u8>,
|
||||
buf: Arc<[u8]>,
|
||||
encoding: ContentTransferEncoding,
|
||||
}
|
||||
|
||||
@@ -39,7 +39,7 @@ impl Body {
|
||||
|
||||
let encoding = buf.encoding(false);
|
||||
buf.encode_crlf();
|
||||
Self::new_impl(buf.into(), encoding)
|
||||
Self::new_impl(Vec::from(buf).into(), encoding)
|
||||
}
|
||||
|
||||
/// Encode the supplied `buf`, using the provided `encoding`.
|
||||
@@ -77,7 +77,7 @@ impl Body {
|
||||
}
|
||||
|
||||
buf.encode_crlf();
|
||||
Ok(Self::new_impl(buf.into(), encoding))
|
||||
Ok(Self::new_impl(Vec::from(buf).into(), encoding))
|
||||
}
|
||||
|
||||
/// Builds a new `Body` using a pre-encoded buffer.
|
||||
@@ -87,11 +87,14 @@ impl Body {
|
||||
/// `buf` shouldn't contain non-ascii characters, lines longer than 1000 characters or nul bytes.
|
||||
#[inline]
|
||||
pub fn dangerous_pre_encoded(buf: Vec<u8>, encoding: ContentTransferEncoding) -> Self {
|
||||
Self { buf, encoding }
|
||||
Self {
|
||||
buf: buf.into(),
|
||||
encoding,
|
||||
}
|
||||
}
|
||||
|
||||
/// Encodes the supplied `buf` using the provided `encoding`
|
||||
fn new_impl(buf: Vec<u8>, encoding: ContentTransferEncoding) -> Self {
|
||||
fn new_impl(buf: Arc<[u8]>, encoding: ContentTransferEncoding) -> Self {
|
||||
match encoding {
|
||||
ContentTransferEncoding::SevenBit
|
||||
| ContentTransferEncoding::EightBit
|
||||
@@ -133,7 +136,16 @@ impl Body {
|
||||
|
||||
/// Consumes `Body` and returns the inner `Vec<u8>`
|
||||
#[inline]
|
||||
#[deprecated(
|
||||
note = "The inner memory is not stored into `Vec<u8>` anymore. Consider using `into_inner`"
|
||||
)]
|
||||
pub fn into_vec(self) -> Vec<u8> {
|
||||
self.buf.to_vec()
|
||||
}
|
||||
|
||||
/// Consumes `Body` and returns the inner `Arc<[u8]>`
|
||||
#[inline]
|
||||
pub fn into_inner(self) -> Arc<[u8]> {
|
||||
self.buf
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ pub use self::{
|
||||
special::*,
|
||||
textual::*,
|
||||
};
|
||||
use super::EmailFormat;
|
||||
use crate::BoxError;
|
||||
|
||||
mod content;
|
||||
@@ -154,6 +155,19 @@ impl Display for Headers {
|
||||
}
|
||||
}
|
||||
|
||||
impl EmailFormat for Headers {
|
||||
fn format<'a>(&'a self, out: &mut impl Extend<Cow<'a, [u8]>>) {
|
||||
for value in &self.headers {
|
||||
out.extend([
|
||||
Cow::Borrowed(value.name.as_bytes()),
|
||||
Cow::Borrowed(b": "),
|
||||
Cow::Borrowed(value.encoded_value.as_bytes()),
|
||||
Cow::Borrowed(b"\r\n"),
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A possible error when converting a `HeaderName` from another type.
|
||||
// comes from `http` crate
|
||||
#[allow(missing_copy_implementations)]
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use std::{io::Write, iter::repeat_with};
|
||||
use std::{borrow::Cow, iter::repeat_with, sync::Arc};
|
||||
|
||||
use mime::Mime;
|
||||
|
||||
@@ -28,7 +28,7 @@ impl Part {
|
||||
}
|
||||
|
||||
impl EmailFormat for Part {
|
||||
fn format(&self, out: &mut Vec<u8>) {
|
||||
fn format<'a>(&'a self, out: &mut impl Extend<Cow<'a, [u8]>>) {
|
||||
match self {
|
||||
Part::Single(part) => part.format(out),
|
||||
Part::Multi(part) => part.format(out),
|
||||
@@ -71,7 +71,7 @@ impl SinglePartBuilder {
|
||||
|
||||
SinglePart {
|
||||
headers: self.headers,
|
||||
body: body.into_vec(),
|
||||
body: body.into_inner(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -100,7 +100,7 @@ impl Default for SinglePartBuilder {
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct SinglePart {
|
||||
headers: Headers,
|
||||
body: Vec<u8>,
|
||||
body: Arc<[u8]>,
|
||||
}
|
||||
|
||||
impl SinglePart {
|
||||
@@ -138,24 +138,18 @@ impl SinglePart {
|
||||
|
||||
/// Get message content formatted for sending
|
||||
pub fn formatted(&self) -> Vec<u8> {
|
||||
let mut out = Vec::new();
|
||||
self.format(&mut out);
|
||||
out
|
||||
}
|
||||
|
||||
/// Format only the signlepart body
|
||||
fn format_body(&self, out: &mut Vec<u8>) {
|
||||
out.extend_from_slice(&self.body);
|
||||
out.extend_from_slice(b"\r\n");
|
||||
self.format_to_vec()
|
||||
}
|
||||
}
|
||||
|
||||
impl EmailFormat for SinglePart {
|
||||
fn format(&self, out: &mut Vec<u8>) {
|
||||
write!(out, "{}", self.headers)
|
||||
.expect("A Write implementation panicked while formatting headers");
|
||||
out.extend_from_slice(b"\r\n");
|
||||
self.format_body(out);
|
||||
fn format<'a>(&'a self, out: &mut impl Extend<Cow<'a, [u8]>>) {
|
||||
self.headers.format(out);
|
||||
out.extend([
|
||||
Cow::Borrowed("\r\n".as_bytes()),
|
||||
Cow::Borrowed(&self.body),
|
||||
Cow::Borrowed(b"\r\n"),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,33 +378,36 @@ impl MultiPart {
|
||||
|
||||
/// Get message content formatted for SMTP
|
||||
pub fn formatted(&self) -> Vec<u8> {
|
||||
let mut out = Vec::new();
|
||||
self.format(&mut out);
|
||||
out
|
||||
self.format_to_vec()
|
||||
}
|
||||
|
||||
/// Format only the multipart body
|
||||
fn format_body(&self, out: &mut Vec<u8>) {
|
||||
fn format_body<'a>(&'a self, out: &mut impl Extend<Cow<'a, [u8]>>) {
|
||||
let boundary = self.boundary();
|
||||
|
||||
for part in &self.parts {
|
||||
out.extend_from_slice(b"--");
|
||||
out.extend_from_slice(boundary.as_bytes());
|
||||
out.extend_from_slice(b"\r\n");
|
||||
out.extend([
|
||||
Cow::Borrowed("--".as_bytes()),
|
||||
// FIXME: this clone shouldn't exist
|
||||
Cow::Owned(boundary.clone().into()),
|
||||
Cow::Borrowed("\r\n".as_bytes()),
|
||||
]);
|
||||
part.format(out);
|
||||
}
|
||||
|
||||
out.extend_from_slice(b"--");
|
||||
out.extend_from_slice(boundary.as_bytes());
|
||||
out.extend_from_slice(b"--\r\n");
|
||||
out.extend([
|
||||
Cow::Borrowed("--".as_bytes()),
|
||||
Cow::Owned(boundary.into()),
|
||||
Cow::Borrowed("--\r\n".as_bytes()),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
impl EmailFormat for MultiPart {
|
||||
fn format(&self, out: &mut Vec<u8>) {
|
||||
write!(out, "{}", self.headers)
|
||||
.expect("A Write implementation panicked while formatting headers");
|
||||
out.extend_from_slice(b"\r\n");
|
||||
fn format<'a>(&'a self, out: &mut impl Extend<Cow<'a, [u8]>>) {
|
||||
self.headers.format(out);
|
||||
out.extend([Cow::Borrowed("\r\n".as_bytes())]);
|
||||
|
||||
self.format_body(out);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
//! ```
|
||||
//! </details>
|
||||
|
||||
use std::{io::Write, iter, time::SystemTime};
|
||||
use std::{borrow::Cow, iter, sync::Arc, time::SystemTime};
|
||||
|
||||
pub use attachment::Attachment;
|
||||
pub use body::{Body, IntoBody, MaybeString};
|
||||
@@ -226,7 +226,23 @@ const DEFAULT_MESSAGE_ID_DOMAIN: &str = "localhost";
|
||||
/// Something that can be formatted as an email message
|
||||
trait EmailFormat {
|
||||
// Use a writer?
|
||||
fn format(&self, out: &mut Vec<u8>);
|
||||
fn format<'a>(&'a self, out: &mut impl Extend<Cow<'a, [u8]>>);
|
||||
|
||||
fn format_to_vec(&self) -> Vec<u8> {
|
||||
struct Formatter(Vec<u8>);
|
||||
|
||||
impl<'a> Extend<Cow<'a, [u8]>> for Formatter {
|
||||
fn extend<T: IntoIterator<Item = Cow<'a, [u8]>>>(&mut self, iter: T) {
|
||||
for chunk in iter {
|
||||
self.0.extend_from_slice(&chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let mut formatted = Formatter(Vec::new());
|
||||
self.format(&mut formatted);
|
||||
formatted.0
|
||||
}
|
||||
}
|
||||
|
||||
/// A builder for messages
|
||||
@@ -454,7 +470,7 @@ impl MessageBuilder {
|
||||
let body = body.into_body(maybe_encoding);
|
||||
|
||||
self.headers.set(body.encoding());
|
||||
self.build(MessageBody::Raw(body.into_vec()))
|
||||
self.build(MessageBody::Raw(body.into_inner()))
|
||||
}
|
||||
|
||||
/// Create message using mime body ([`MultiPart`][self::MultiPart])
|
||||
@@ -489,7 +505,7 @@ pub struct Message {
|
||||
#[derive(Clone, Debug)]
|
||||
enum MessageBody {
|
||||
Mime(Part),
|
||||
Raw(Vec<u8>),
|
||||
Raw(Arc<[u8]>),
|
||||
}
|
||||
|
||||
impl Message {
|
||||
@@ -515,9 +531,7 @@ impl Message {
|
||||
|
||||
/// Get message content formatted for SMTP
|
||||
pub fn formatted(&self) -> Vec<u8> {
|
||||
let mut out = Vec::new();
|
||||
self.format(&mut out);
|
||||
out
|
||||
self.format_to_vec()
|
||||
}
|
||||
|
||||
#[cfg(feature = "dkim")]
|
||||
@@ -593,15 +607,13 @@ impl Message {
|
||||
}
|
||||
|
||||
impl EmailFormat for Message {
|
||||
fn format(&self, out: &mut Vec<u8>) {
|
||||
write!(out, "{}", self.headers)
|
||||
.expect("A Write implementation panicked while formatting headers");
|
||||
fn format<'a>(&'a self, out: &mut impl Extend<Cow<'a, [u8]>>) {
|
||||
self.headers.format(out);
|
||||
|
||||
match &self.body {
|
||||
MessageBody::Mime(p) => p.format(out),
|
||||
MessageBody::Raw(r) => {
|
||||
out.extend_from_slice(b"\r\n");
|
||||
out.extend_from_slice(r)
|
||||
out.extend([Cow::Borrowed("\r\n".as_bytes()), Cow::Borrowed(r)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user