Merge pull request #293 from amousset/fix-vec-attachment

feat(email): Improve attachment methods
This commit is contained in:
Alexis Mousset
2018-05-31 09:02:14 +02:00
committed by GitHub
10 changed files with 37 additions and 70 deletions

View File

@@ -3,7 +3,7 @@ rust:
- stable - stable
- beta - beta
- nightly - nightly
- 1.20.0 - 1.26.0
matrix: matrix:
allow_failures: allow_failures:
- rust: nightly - rust: nightly

View File

@@ -3,14 +3,14 @@
//! It can be useful for testing purposes, or if you want to keep track of sent messages. //! It can be useful for testing purposes, or if you want to keep track of sent messages.
//! //!
use Envelope;
use SendableEmail;
use Transport;
use file::error::FileResult; use file::error::FileResult;
use serde_json; use serde_json;
use std::fs::File; use std::fs::File;
use std::io::prelude::*; use std::io::prelude::*;
use std::path::{Path, PathBuf}; use std::path::{Path, PathBuf};
use Envelope;
use SendableEmail;
use Transport;
pub mod error; pub mod error;

View File

@@ -4,8 +4,10 @@
//! //!
#![doc(html_root_url = "https://docs.rs/lettre/0.9.0")] #![doc(html_root_url = "https://docs.rs/lettre/0.9.0")]
#![deny(missing_copy_implementations, trivial_casts, trivial_numeric_casts, unsafe_code, #![deny(
unstable_features, unused_import_braces, unused_qualifications)] missing_copy_implementations, trivial_casts, trivial_numeric_casts, unsafe_code,
unstable_features, unused_import_braces, unused_qualifications
)]
#[cfg(feature = "smtp-transport")] #[cfg(feature = "smtp-transport")]
extern crate base64; extern crate base64;
#[cfg(feature = "smtp-transport")] #[cfg(feature = "smtp-transport")]

View File

@@ -1,12 +1,12 @@
//! The sendmail transport sends the email using the local sendmail command. //! The sendmail transport sends the email using the local sendmail command.
//! //!
use sendmail::error::SendmailResult;
use std::io::prelude::*;
use std::io::Read;
use std::process::{Command, Stdio};
use SendableEmail; use SendableEmail;
use Transport; use Transport;
use sendmail::error::SendmailResult;
use std::io::Read;
use std::io::prelude::*;
use std::process::{Command, Stdio};
pub mod error; pub mod error;

View File

@@ -1,6 +1,5 @@
//! SMTP commands //! SMTP commands
use EmailAddress;
use base64; use base64;
use smtp::authentication::{Credentials, Mechanism}; use smtp::authentication::{Credentials, Mechanism};
use smtp::error::Error; use smtp::error::Error;
@@ -8,6 +7,7 @@ use smtp::extension::ClientId;
use smtp::extension::{MailParameter, RcptParameter}; use smtp::extension::{MailParameter, RcptParameter};
use smtp::response::Response; use smtp::response::Response;
use std::fmt::{self, Display, Formatter}; use std::fmt::{self, Display, Formatter};
use EmailAddress;
/// EHLO command /// EHLO command
#[derive(PartialEq, Clone, Debug)] #[derive(PartialEq, Clone, Debug)]

View File

@@ -16,9 +16,9 @@
use native_tls::TlsConnector; use native_tls::TlsConnector;
use smtp::authentication::{Credentials, Mechanism, DEFAULT_ENCRYPTED_MECHANISMS, use smtp::authentication::{Credentials, Mechanism, DEFAULT_ENCRYPTED_MECHANISMS,
DEFAULT_UNENCRYPTED_MECHANISMS}; DEFAULT_UNENCRYPTED_MECHANISMS};
use smtp::client::InnerClient;
use smtp::client::net::ClientTlsParameters; use smtp::client::net::ClientTlsParameters;
use smtp::client::net::DEFAULT_TLS_PROTOCOLS; use smtp::client::net::DEFAULT_TLS_PROTOCOLS;
use smtp::client::InnerClient;
use smtp::commands::*; use smtp::commands::*;
use smtp::error::{Error, SmtpResult}; use smtp::error::{Error, SmtpResult};
use smtp::extension::{ClientId, Extension, MailBodyParameter, MailParameter, ServerInfo}; use smtp::extension::{ClientId, Extension, MailBodyParameter, MailParameter, ServerInfo};

View File

@@ -5,7 +5,7 @@ use nom::simple_errors::Err as NomError;
use nom::{crlf, ErrorKind as NomErrorKind, IResult as NomResult}; use nom::{crlf, ErrorKind as NomErrorKind, IResult as NomResult};
use std::fmt::{Display, Formatter, Result}; use std::fmt::{Display, Formatter, Result};
use std::result; use std::result;
use std::str::{FromStr, from_utf8}; use std::str::{from_utf8, FromStr};
/// First digit indicates severity /// First digit indicates severity
#[derive(PartialEq, Eq, Copy, Clone, Debug)] #[derive(PartialEq, Eq, Copy, Clone, Debug)]

View File

@@ -7,8 +7,8 @@ mod test {
use lettre::file::FileTransport; use lettre::file::FileTransport;
use lettre::{EmailAddress, Envelope, SendableEmail, Transport}; use lettre::{EmailAddress, Envelope, SendableEmail, Transport};
use std::env::temp_dir; use std::env::temp_dir;
use std::fs::File;
use std::fs::remove_file; use std::fs::remove_file;
use std::fs::File;
use std::io::Read; use std::io::Read;
#[test] #[test]

View File

@@ -14,7 +14,7 @@ fn main() {
.from("user@example.com") .from("user@example.com")
.subject("Hi, Hello world") .subject("Hi, Hello world")
.text("Hello world.") .text("Hello world.")
.attachment(Path::new("Cargo.toml"), None, &mime::TEXT_PLAIN).unwrap() .attachment_from_file(Path::new("Cargo.toml"), None, &mime::TEXT_PLAIN).unwrap()
.build() .build()
.unwrap(); .unwrap();

View File

@@ -2,9 +2,11 @@
//! //!
#![doc(html_root_url = "https://docs.rs/lettre_email/0.9.0")] #![doc(html_root_url = "https://docs.rs/lettre_email/0.9.0")]
#![deny(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts, #![deny(
trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces, missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
unused_qualifications)] trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
unused_qualifications
)]
extern crate base64; extern crate base64;
extern crate email as email_format; extern crate email as email_format;
@@ -19,8 +21,7 @@ pub use email_format::{Address, Header, Mailbox, MimeMessage, MimeMultipartType}
use error::Error; use error::Error;
use lettre::{EmailAddress, Envelope, Error as EmailError, SendableEmail}; use lettre::{EmailAddress, Envelope, Error as EmailError, SendableEmail};
use mime::Mime; use mime::Mime;
use std::fs::File; use std::fs;
use std::io::Read;
use std::path::Path; use std::path::Path;
use std::str::FromStr; use std::str::FromStr;
use time::{now, Tm}; use time::{now, Tm};
@@ -218,72 +219,36 @@ impl EmailBuilder {
} }
/// Adds an attachment to the email from a file /// Adds an attachment to the email from a file
pub fn attachment( ///
/// If not specified, the filename will be extracted from the file path.
pub fn attachment_from_file(
self, self,
path: &Path, path: &Path,
filename: Option<&str>, filename: Option<&str>,
content_type: &Mime, content_type: &Mime,
) -> Result<EmailBuilder, Error> { ) -> Result<EmailBuilder, Error> {
let file = File::open(path); self.attachment(
let body = match file { fs::read(path)?.as_slice(),
Ok(mut f) => { filename.unwrap_or(path.file_name()
let mut data = Vec::new(); .and_then(|x| x.to_str())
let read = f.read_to_end(&mut data); .ok_or(Error::CannotParseFilename)?),
match read { content_type,
Ok(_) => data, )
Err(e) => {
return Err(From::from(e));
}
}
}
Err(e) => {
return Err(From::from(e));
}
};
let actual_filename = match filename {
Some(name) => name,
None => match path.file_name() {
Some(name) => match name.to_str() {
Some(name) => name,
None => return Err(Error::CannotParseFilename),
},
None => return Err(Error::CannotParseFilename),
},
};
let encoded_body = base64::encode(&body);
let content = PartBuilder::new()
.body(encoded_body)
.header((
"Content-Disposition",
format!("attachment; filename=\"{}\"", actual_filename),
))
.header(("Content-Type", content_type.to_string()))
.header(("Content-Transfer-Encoding", "base64"))
.build();
Ok(self.message_type(MimeMultipartType::Mixed).child(content))
} }
/// Adds an attachment to the email from a vector of bytes. /// Adds an attachment to the email from a vector of bytes.
/// This is usefull when your attachment is actually not a file, but a sequence of bytes. pub fn attachment(
pub fn attach_from_vec(
self, self,
bytes_vec: &Vec<u8>, body: &[u8],
filename: &str, filename: &str,
content_type: &Mime, content_type: &Mime,
) -> Result<EmailBuilder, Error> { ) -> Result<EmailBuilder, Error> {
let body = bytes_vec;
let actual_filename = filename;
let encoded_body = base64::encode(&body); let encoded_body = base64::encode(&body);
let content = PartBuilder::new() let content = PartBuilder::new()
.body(encoded_body) .body(encoded_body)
.header(( .header((
"Content-Disposition", "Content-Disposition",
format!("attachment; filename=\"{}\"", actual_filename), format!("attachment; filename=\"{}\"", filename),
)) ))
.header(("Content-Type", content_type.to_string())) .header(("Content-Type", content_type.to_string()))
.header(("Content-Transfer-Encoding", "base64")) .header(("Content-Transfer-Encoding", "base64"))