Merge pull request #293 from amousset/fix-vec-attachment
feat(email): Improve attachment methods
This commit is contained in:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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")]
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
@@ -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};
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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();
|
||||||
|
|
||||||
|
|||||||
@@ -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"))
|
||||||
|
|||||||
Reference in New Issue
Block a user