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