Compare commits
8 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9dadc4d6eb | ||
|
|
bb7815a366 | ||
|
|
b24c0a367d | ||
|
|
e0637c9ed4 | ||
|
|
6c3de0e85b | ||
|
|
692f8a5346 | ||
|
|
60f06f1682 | ||
|
|
29b130c919 |
@@ -46,7 +46,6 @@ lettre_email = "0.8"
|
||||
```rust,no_run
|
||||
extern crate lettre;
|
||||
extern crate lettre_email;
|
||||
extern crate mime;
|
||||
|
||||
use lettre::{EmailTransport, SmtpTransport};
|
||||
use lettre_email::EmailBuilder;
|
||||
@@ -60,7 +59,6 @@ fn main() {
|
||||
.from("user@example.com")
|
||||
.subject("Hi, Hello world")
|
||||
.text("Hello world.")
|
||||
.attachment(Path::new("Cargo.toml"), None, &mime::TEXT_PLAIN).unwrap()
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ is-it-maintained-open-issues = { repository = "lettre/lettre" }
|
||||
|
||||
[dependencies]
|
||||
log = "^0.4"
|
||||
nom = { version = "^3.2", optional = true }
|
||||
nom = { version = "^4.0", optional = true }
|
||||
bufstream = { version = "^0.1", optional = true }
|
||||
native-tls = { version = "^0.1", optional = true }
|
||||
base64 = { version = "^0.9", optional = true }
|
||||
|
||||
@@ -37,7 +37,7 @@ pub enum Error {
|
||||
/// TLS error
|
||||
Tls(native_tls::Error),
|
||||
/// Parsing error
|
||||
Parsing(nom::simple_errors::Err),
|
||||
Parsing(nom::ErrorKind),
|
||||
}
|
||||
|
||||
impl Display for Error {
|
||||
@@ -77,7 +77,7 @@ impl StdError for Error {
|
||||
Utf8Parsing(ref err) => Some(&*err),
|
||||
Io(ref err) => Some(&*err),
|
||||
Tls(ref err) => Some(&*err),
|
||||
Parsing(ref err) => Some(&*err),
|
||||
Parsing(_) => None,
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@@ -95,8 +95,8 @@ impl From<native_tls::Error> for Error {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<nom::simple_errors::Err> for Error {
|
||||
fn from(err: nom::simple_errors::Err) -> Error {
|
||||
impl From<nom::ErrorKind> for Error {
|
||||
fn from(err: nom::ErrorKind) -> Error {
|
||||
Parsing(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
//! SMTP response, containing a mandatory return code and an optional text
|
||||
//! message
|
||||
|
||||
use nom::{crlf, ErrorKind as NomErrorKind, IResult as NomResult};
|
||||
use nom::simple_errors::Err as NomError;
|
||||
use nom::{crlf, ErrorKind as NomErrorKind};
|
||||
use std::fmt::{Display, Formatter, Result};
|
||||
use std::result;
|
||||
use std::str::{FromStr, from_utf8};
|
||||
@@ -126,13 +125,12 @@ pub struct Response {
|
||||
}
|
||||
|
||||
impl FromStr for Response {
|
||||
type Err = NomError;
|
||||
type Err = NomErrorKind;
|
||||
|
||||
fn from_str(s: &str) -> result::Result<Response, NomError> {
|
||||
fn from_str(s: &str) -> result::Result<Response, NomErrorKind> {
|
||||
match parse_response(s.as_bytes()) {
|
||||
NomResult::Done(_, res) => Ok(res),
|
||||
NomResult::Error(e) => Err(e),
|
||||
NomResult::Incomplete(_) => Err(NomErrorKind::Complete),
|
||||
Ok((_, res)) => Ok(res),
|
||||
Err(e) => Err(e.into_error_kind()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -106,6 +106,14 @@ impl IntoEmail for SimpleEmail {
|
||||
builder.set_subject(self.subject.unwrap());
|
||||
}
|
||||
|
||||
if self.in_reply_to.is_some() {
|
||||
builder.add_in_reply_to(self.in_reply_to.unwrap().into_mailbox());
|
||||
}
|
||||
|
||||
if self.reference.is_some() {
|
||||
builder.add_reference(self.reference.unwrap().into_mailbox());
|
||||
}
|
||||
|
||||
// No date for now
|
||||
|
||||
match (self.text, self.html) {
|
||||
@@ -131,6 +139,8 @@ pub struct SimpleEmail {
|
||||
cc: Vec<Mailbox>,
|
||||
bcc: Vec<Mailbox>,
|
||||
reply_to: Option<Mailbox>,
|
||||
in_reply_to: Option<Mailbox>,
|
||||
reference: Option<Mailbox>,
|
||||
subject: Option<String>,
|
||||
date: Option<Tm>,
|
||||
html: Option<String>,
|
||||
@@ -184,6 +194,18 @@ impl SimpleEmail {
|
||||
self.cc.push(address.into_mailbox());
|
||||
}
|
||||
|
||||
/// Adds a `In-Reply-To` to the header
|
||||
pub fn in_reply_to<A: IntoMailbox>(mut self, address: A) -> SimpleEmail {
|
||||
self.in_reply_to = Some(address.into_mailbox());
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a `Reference` to the header
|
||||
pub fn reference<A: IntoMailbox>(mut self, address: A) -> SimpleEmail {
|
||||
self.reference = Some(address.into_mailbox());
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a `Bcc` header and stores the recipient address
|
||||
pub fn bcc<A: IntoMailbox>(mut self, address: A) -> SimpleEmail {
|
||||
self.add_bcc(address);
|
||||
@@ -296,6 +318,10 @@ pub struct EmailBuilder {
|
||||
envelope: Option<Envelope>,
|
||||
/// Date issued
|
||||
date_issued: bool,
|
||||
/// Reference Header
|
||||
reference_header: Vec<Address>,
|
||||
/// In-Reply-To Header
|
||||
in_reply_to_header: Vec<Address>
|
||||
}
|
||||
|
||||
/// Simple email representation
|
||||
@@ -392,6 +418,8 @@ impl EmailBuilder {
|
||||
sender_header: None,
|
||||
envelope: None,
|
||||
date_issued: false,
|
||||
reference_header: vec![],
|
||||
in_reply_to_header: vec![]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -471,6 +499,28 @@ impl EmailBuilder {
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a `In-Reply-To` header
|
||||
pub fn add_in_reply_to<A: IntoMailbox>(&mut self, address: A) {
|
||||
self.in_reply_to_header.push(Address::Mailbox(address.into_mailbox()));
|
||||
}
|
||||
|
||||
/// Adds a `Reference` header
|
||||
pub fn add_reference<A: IntoMailbox>(&mut self, address: A) {
|
||||
self.reference_header.push(Address::Mailbox(address.into_mailbox()));
|
||||
}
|
||||
|
||||
/// Adds a `In-Reply-To` header
|
||||
pub fn in_reply_to<A: IntoMailbox>(mut self, address: A) -> EmailBuilder {
|
||||
self.add_in_reply_to(address);
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a `Reference` header
|
||||
pub fn reference<A: IntoMailbox>(mut self, address: A) -> EmailBuilder {
|
||||
self.add_reference(address);
|
||||
self
|
||||
}
|
||||
|
||||
/// Adds a `Reply-To` header
|
||||
pub fn add_reply_to<A: IntoMailbox>(&mut self, address: A) {
|
||||
let mailbox = address.into_mailbox();
|
||||
@@ -773,16 +823,24 @@ impl EmailBuilder {
|
||||
self.message
|
||||
.add_header(Header::new_with_value("Cc".into(), self.cc_header).unwrap());
|
||||
}
|
||||
if !self.bcc_header.is_empty() {
|
||||
self.message
|
||||
.add_header(Header::new_with_value("Bcc".into(), self.bcc_header).unwrap());
|
||||
}
|
||||
if !self.reply_to_header.is_empty() {
|
||||
self.message.add_header(
|
||||
Header::new_with_value("Reply-To".into(), self.reply_to_header).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
if !self.reference_header.is_empty() {
|
||||
self.message.add_header(
|
||||
Header::new_with_value("Reference".into(), self.reference_header).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
if !self.in_reply_to_header.is_empty() {
|
||||
self.message.add_header(
|
||||
Header::new_with_value("In-Reply-To".into(), self.in_reply_to_header).unwrap(),
|
||||
);
|
||||
}
|
||||
|
||||
if !self.date_issued {
|
||||
self.message
|
||||
.add_header(("Date", Tm::rfc822z(&now()).to_string().as_ref()));
|
||||
@@ -902,7 +960,7 @@ mod test {
|
||||
"Date: {}\r\nSubject: Hello\r\nX-test: value\r\nSender: \
|
||||
<sender@localhost>\r\nTo: <user@localhost>\r\nFrom: \
|
||||
<user@localhost>\r\nCc: \"Alias\" <cc@localhost>\r\n\
|
||||
Bcc: <bcc@localhost>\r\nReply-To: <reply@localhost>\r\n\
|
||||
Reply-To: <reply@localhost>\r\n\
|
||||
MIME-Version: 1.0\r\nMessage-ID: \
|
||||
<{}.lettre@localhost>\r\n\r\nHello World!\r\n",
|
||||
date_now.rfc822z(),
|
||||
|
||||
@@ -83,6 +83,56 @@ fn main() {
|
||||
}
|
||||
```
|
||||
|
||||
You can specify custom TLS settings:
|
||||
|
||||
```rust,no_run
|
||||
extern crate native_tls;
|
||||
extern crate lettre;
|
||||
extern crate lettre_email;
|
||||
|
||||
use native_tls::TlsConnector;
|
||||
use native_tls::{Protocol};
|
||||
use lettre::smtp::authentication::{Credentials, Mechanism};
|
||||
use lettre::{EmailTransport, SimpleSendableEmail, ClientTlsParameters, ClientSecurity};
|
||||
use lettre::smtp::ConnectionReuseParameters;
|
||||
use lettre::smtp::{SmtpTransportBuilder};
|
||||
use lettre_email::EmailBuilder;
|
||||
|
||||
fn main() {
|
||||
let email = SimpleSendableEmail::new(
|
||||
"user@localhost".to_string(),
|
||||
&["root@localhost".to_string()],
|
||||
"message_id".to_string(),
|
||||
"Hello world".to_string(),
|
||||
).unwrap();
|
||||
|
||||
let mut tls_builder = TlsConnector::builder().unwrap();
|
||||
tls_builder.supported_protocols(&[Protocol::Tlsv10]).unwrap();
|
||||
let tls_parameters =
|
||||
ClientTlsParameters::new(
|
||||
"smtp.example.com".to_string(),
|
||||
tls_builder.build().unwrap()
|
||||
);
|
||||
|
||||
let mut mailer = SmtpTransportBuilder::new(
|
||||
("smtp.example.com", 465), ClientSecurity::Wrapper(tls_parameters)
|
||||
)
|
||||
.expect("Failed to create transport")
|
||||
.authentication_mechanism(Mechanism::Login)
|
||||
.credentials(Credentials::new(
|
||||
"example_username".to_string(), "example_password".to_string()
|
||||
))
|
||||
.connection_reuse(ConnectionReuseParameters::ReuseUnlimited)
|
||||
.build();
|
||||
|
||||
let result = mailer.send(&email);
|
||||
|
||||
assert!(result.is_ok());
|
||||
|
||||
mailer.close();
|
||||
}
|
||||
```
|
||||
|
||||
#### Lower level
|
||||
|
||||
You can also send commands, here is a simple email transaction without
|
||||
|
||||
Reference in New Issue
Block a user