Compare commits
19 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9d61e6ec1f | ||
|
|
7f8c13910d | ||
|
|
364e40f5d9 | ||
|
|
cb08bc5527 | ||
|
|
6c7c3ba9fa | ||
|
|
53e79c0ac4 | ||
|
|
53f9bada4c | ||
|
|
ce7d55ffa8 | ||
|
|
a6ea43a842 | ||
|
|
eac29768ae | ||
|
|
d944aed9d3 | ||
|
|
67318ac759 | ||
|
|
90999bfc24 | ||
|
|
7635830399 | ||
|
|
4fbd06e18b | ||
|
|
5247e2c2aa | ||
|
|
8e21de8de3 | ||
|
|
d976f48b7b | ||
|
|
9ed51a2d3d |
17
.travis.yml
17
.travis.yml
@@ -1,9 +1,16 @@
|
|||||||
language: rust
|
language: rust
|
||||||
|
|
||||||
rust:
|
rust:
|
||||||
- stable
|
- stable
|
||||||
- beta
|
- beta
|
||||||
- nightly
|
- nightly
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- rust: nightly
|
||||||
|
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
cache:
|
cache:
|
||||||
apt: true
|
apt: true
|
||||||
pip: true
|
pip: true
|
||||||
@@ -12,9 +19,11 @@ cache:
|
|||||||
- target/debug/build
|
- target/debug/build
|
||||||
- target/release/deps
|
- target/release/deps
|
||||||
- target/release/build
|
- target/release/build
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- pip install 'travis-cargo<0.2' --user
|
- pip install 'travis-cargo<0.2' --user
|
||||||
- export PATH=$HOME/.local/bin:$PATH
|
- export PATH=$HOME/.local/bin:$PATH
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
@@ -22,16 +31,20 @@ addons:
|
|||||||
- libcurl4-openssl-dev
|
- libcurl4-openssl-dev
|
||||||
- libelf-dev
|
- libelf-dev
|
||||||
- libdw-dev
|
- libdw-dev
|
||||||
|
|
||||||
before_script:
|
before_script:
|
||||||
- smtp-sink 2525 1000&
|
- smtp-sink 2525 1000&
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- travis-cargo build
|
- travis-cargo build
|
||||||
- travis-cargo test
|
- travis-cargo test
|
||||||
- travis-cargo doc
|
- travis-cargo doc
|
||||||
- travis-cargo --only stable doc-upload
|
|
||||||
after_success:
|
after_success:
|
||||||
|
- ./.travis/doc.sh
|
||||||
|
- ./.travis/coverage.sh
|
||||||
- travis-cargo --only nightly bench
|
- travis-cargo --only nightly bench
|
||||||
- travis-cargo --only stable coveralls --no-sudo
|
|
||||||
env:
|
env:
|
||||||
global:
|
global:
|
||||||
secure: "MaZ3TzuaAHuxmxQkfJdqRfkh7/ieScJRk0T/2yjysZhDMTYyRmp5wh/zkfW1ADuG0uc4Pqsxrsh1J9SVO7O0U5NJA8NKZi/pgiL+FHh0g4YtlHxy2xmFNB5am3Kyc+E7B4XylwTbA9S8ublVM0nvX7yX/a5fbwEUInVk2bA8fpc="
|
secure: "MaZ3TzuaAHuxmxQkfJdqRfkh7/ieScJRk0T/2yjysZhDMTYyRmp5wh/zkfW1ADuG0uc4Pqsxrsh1J9SVO7O0U5NJA8NKZi/pgiL+FHh0g4YtlHxy2xmFNB5am3Kyc+E7B4XylwTbA9S8ublVM0nvX7yX/a5fbwEUInVk2bA8fpc="
|
||||||
|
|||||||
20
.travis/coverage.sh
Executable file
20
.travis/coverage.sh
Executable file
@@ -0,0 +1,20 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
|
||||||
|
if [ "$TRAVIS_RUST_VERSION" != "stable" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
cargo test --no-run
|
||||||
|
|
||||||
|
wget https://github.com/SimonKagstrom/kcov/archive/master.tar.gz
|
||||||
|
tar xzf master.tar.gz
|
||||||
|
mkdir kcov-master/build
|
||||||
|
cd kcov-master/build
|
||||||
|
cmake ..
|
||||||
|
make
|
||||||
|
make install DESTDIR=../tmp
|
||||||
|
cd ../..
|
||||||
|
ls target/debug
|
||||||
|
./kcov-master/tmp/usr/local/bin/kcov --coveralls-id=$TRAVIS_JOB_ID --exclude-pattern=/.cargo target/kcov target/debug/lettre-*
|
||||||
38
.travis/doc.sh
Executable file
38
.travis/doc.sh
Executable file
@@ -0,0 +1,38 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -o errexit
|
||||||
|
|
||||||
|
if [ "$TRAVIS_RUST_VERSION" != "stable" ] || [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
cargo clean
|
||||||
|
cargo doc --no-deps
|
||||||
|
|
||||||
|
git clone --branch gh-pages "https://$GH_TOKEN@github.com/${TRAVIS_REPO_SLUG}.git" deploy_docs
|
||||||
|
cd deploy_docs
|
||||||
|
|
||||||
|
git config user.email "contact@amousset.me"
|
||||||
|
git config user.name "Alexis Mousset"
|
||||||
|
|
||||||
|
if [ "$TRAVIS_BRANCH" == "master" ]; then
|
||||||
|
rm -rf master
|
||||||
|
mv ../target/doc ./master
|
||||||
|
echo "<meta http-equiv=refresh content=0;url=lettre/index.html>" > ./master/index.html
|
||||||
|
elif [ "$TRAVIS_TAG" != "" ]; then
|
||||||
|
rm -rf $TRAVIS_TAG
|
||||||
|
mv ../target/doc ./$TRAVIS_TAG
|
||||||
|
echo "<meta http-equiv=refresh content=0;url=lettre/index.html>" > ./$TRAVIS_TAG/index.html
|
||||||
|
|
||||||
|
latest=$(echo * | tr " " "\n" | sort -V -r | head -n1)
|
||||||
|
if [ "$TRAVIS_TAG" == "$latest" ]; then
|
||||||
|
|
||||||
|
echo "<meta http-equiv=refresh content=0;url=$latest/lettre/index.html>" > index.html
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
git add -A .
|
||||||
|
git commit -m "Rebuild pages at ${TRAVIS_COMMIT}"
|
||||||
|
git push --quiet origin gh-pages
|
||||||
29
CHANGELOG.md
29
CHANGELOG.md
@@ -1,3 +1,32 @@
|
|||||||
|
### v0.6.3 (2022-1--21)
|
||||||
|
|
||||||
|
* **transport**: Allow using openssl 0.10
|
||||||
|
|
||||||
|
### v0.6.2 (2017-02-18)
|
||||||
|
|
||||||
|
#### Features
|
||||||
|
|
||||||
|
* **all**
|
||||||
|
* Update uuid crate to 0.4
|
||||||
|
* Update env-logger crate to 0.4
|
||||||
|
* Update openssl crate to 0.9
|
||||||
|
|
||||||
|
### v0.6.1 (2016-10-19)
|
||||||
|
|
||||||
|
#### Features
|
||||||
|
|
||||||
|
* **documentation**
|
||||||
|
* #91: Build seperate docs for each release
|
||||||
|
* #96: Add complete documentation information to README
|
||||||
|
|
||||||
|
#### Bugfixes
|
||||||
|
|
||||||
|
* **email**
|
||||||
|
* #85: Use address-list for "To", "From" etc.
|
||||||
|
|
||||||
|
* **tests**
|
||||||
|
* #93: Force building tests before coverage computing
|
||||||
|
|
||||||
### v0.6.0 (2016-05-05)
|
### v0.6.0 (2016-05-05)
|
||||||
|
|
||||||
#### Features
|
#### Features
|
||||||
|
|||||||
@@ -10,7 +10,9 @@ All code must be formatted using `rustfmt`.
|
|||||||
|
|
||||||
Each commit message consists of a header, a body and a footer. The header has a special format that includes a type, a scope and a subject:
|
Each commit message consists of a header, a body and a footer. The header has a special format that includes a type, a scope and a subject:
|
||||||
|
|
||||||
|
```text
|
||||||
<type>(<scope>): <subject> <BLANK LINE> <body> <BLANK LINE> <footer>
|
<type>(<scope>): <subject> <BLANK LINE> <body> <BLANK LINE> <footer>
|
||||||
|
```
|
||||||
|
|
||||||
Any line of the commit message cannot be longer 72 characters.
|
Any line of the commit message cannot be longer 72 characters.
|
||||||
|
|
||||||
|
|||||||
25
Cargo.toml
25
Cargo.toml
@@ -1,29 +1,28 @@
|
|||||||
[package]
|
[package]
|
||||||
|
|
||||||
name = "lettre"
|
name = "lettre"
|
||||||
version = "0.6.0"
|
version = "0.6.3"
|
||||||
description = "Email client"
|
description = "Email client"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
documentation = "http://lettre.github.io/lettre/"
|
documentation = "https://lettre.github.io/lettre/"
|
||||||
repository = "https://github.com/lettre/lettre"
|
repository = "https://github.com/lettre/lettre"
|
||||||
homepage = "http://lettre.github.io/"
|
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
authors = ["Alexis Mousset <contact@amousset.me>"]
|
authors = ["Alexis Mousset <contact@amousset.me>"]
|
||||||
keywords = ["email", "smtp", "mailer"]
|
keywords = ["email", "smtp", "mailer"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
bufstream = "0.1"
|
bufstream = "^0.1"
|
||||||
email = "0.0"
|
email = "^0.0"
|
||||||
log = "0.3"
|
log = "^0.3"
|
||||||
mime = "0.2"
|
mime = "^0.2"
|
||||||
openssl = "0.8"
|
openssl = "> 0.9, < 0.11"
|
||||||
rustc-serialize = "0.3"
|
rustc-serialize = "^0.3"
|
||||||
rust-crypto = "0.2"
|
rust-crypto = "^0.2"
|
||||||
time = "0.1"
|
time = "^0.1"
|
||||||
uuid = { version = "0.3", features = ["v4"] }
|
uuid = { version = "^0.4", features = ["v4"] }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "0.3"
|
env_logger = "^0.4"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
unstable = []
|
unstable = []
|
||||||
|
|||||||
35
README.md
35
README.md
@@ -1,13 +1,36 @@
|
|||||||
# lettre
|
# lettre
|
||||||
[](https://travis-ci.org/lettre/lettre)
|
[](https://travis-ci.org/lettre/lettre)
|
||||||
[](https://ci.appveyor.com/project/amousset/lettre/branch/master)
|
[](https://ci.appveyor.com/project/amousset/lettre/branch/master)
|
||||||
[](https://coveralls.io/github/lettre/lettre?branch=master)
|
[](https://coveralls.io/github/lettre/lettre?branch=master)
|
||||||
[](https://crates.io/crates/lettre)
|
[](https://crates.io/crates/lettre)
|
||||||
[](./LICENSE)
|
[](./LICENSE)
|
||||||
[](https://gitter.im/lettre/lettre?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
[](https://gitter.im/lettre/lettre?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge)
|
||||||
|
|
||||||
This is an email library written in Rust.
|
This is an email library written in Rust.
|
||||||
See the [documentation](http://lettre.github.io/lettre) for more information.
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
Lettre provides the following features:
|
||||||
|
|
||||||
|
* Multiple transport methods
|
||||||
|
* Unicode support (for email content and addresses)
|
||||||
|
* Secure delivery with SMTP using encryption and authentication
|
||||||
|
* Easy email builders
|
||||||
|
|
||||||
|
## Documentation
|
||||||
|
|
||||||
|
Released versions:
|
||||||
|
|
||||||
|
* [latest](https://lettre.github.io/lettre/)
|
||||||
|
* [v0.6.3](https://lettre.github.io/lettre/v0.6.3/lettre/)
|
||||||
|
* [v0.6.2](https://lettre.github.io/lettre/v0.6.2/lettre/)
|
||||||
|
* [v0.6.1](https://lettre.github.io/lettre/v0.6.1/lettre/)
|
||||||
|
* [v0.6.0](https://lettre.github.io/lettre/v0.6.0/lettre/)
|
||||||
|
* [v0.5.1](https://lettre.github.io/lettre/v0.5.1/lettre/)
|
||||||
|
|
||||||
|
Development version:
|
||||||
|
|
||||||
|
* [master](https://lettre.github.io/lettre/master/lettre/)
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
@@ -15,15 +38,15 @@ To use this library, add the following to your `Cargo.toml`:
|
|||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lettre = "0.5"
|
lettre = "0.6"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
The tests require a mail server listening locally on port 25.
|
The tests require an open mail server listening locally on port 25.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This program is distributed under the terms of the MIT license.
|
This program is distributed under the terms of the MIT license.
|
||||||
|
|
||||||
See LICENSE for details.
|
See [LICENSE](./LICENSE) for details.
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ pub mod error;
|
|||||||
|
|
||||||
use email::error::Error;
|
use email::error::Error;
|
||||||
|
|
||||||
use email_format::{Header, Mailbox, MimeMessage, MimeMultipartType};
|
use email_format::{Header, Mailbox, Address, MimeMessage, MimeMultipartType};
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
@@ -237,6 +237,16 @@ pub struct PartBuilder {
|
|||||||
pub struct EmailBuilder {
|
pub struct EmailBuilder {
|
||||||
/// Message
|
/// Message
|
||||||
message: PartBuilder,
|
message: PartBuilder,
|
||||||
|
/// The recipients' addresses for the mail header
|
||||||
|
to_header: Vec<Address>,
|
||||||
|
/// The sender addresses for the mail header
|
||||||
|
from_header: Vec<Address>,
|
||||||
|
/// The Cc addresses for the mail header
|
||||||
|
cc_header: Vec<Address>,
|
||||||
|
/// The Reply-To addresses for the mail header
|
||||||
|
reply_to_header: Vec<Address>,
|
||||||
|
/// The sender address for the mail header
|
||||||
|
sender_header: Option<Mailbox>,
|
||||||
/// The envelope recipients' addresses
|
/// The envelope recipients' addresses
|
||||||
to: Vec<String>,
|
to: Vec<String>,
|
||||||
/// The envelope sender address
|
/// The envelope sender address
|
||||||
@@ -345,6 +355,11 @@ impl EmailBuilder {
|
|||||||
pub fn new() -> EmailBuilder {
|
pub fn new() -> EmailBuilder {
|
||||||
EmailBuilder {
|
EmailBuilder {
|
||||||
message: PartBuilder::new(),
|
message: PartBuilder::new(),
|
||||||
|
to_header: vec![],
|
||||||
|
from_header: vec![],
|
||||||
|
cc_header: vec![],
|
||||||
|
reply_to_header: vec![],
|
||||||
|
sender_header: None,
|
||||||
to: vec![],
|
to: vec![],
|
||||||
from: None,
|
from: None,
|
||||||
date_issued: false,
|
date_issued: false,
|
||||||
@@ -382,8 +397,8 @@ impl EmailBuilder {
|
|||||||
/// Adds a `From` header and stores the sender address
|
/// Adds a `From` header and stores the sender address
|
||||||
pub fn add_from<A: ToMailbox>(&mut self, address: A) {
|
pub fn add_from<A: ToMailbox>(&mut self, address: A) {
|
||||||
let mailbox = address.to_mailbox();
|
let mailbox = address.to_mailbox();
|
||||||
self.message.add_header(("From", mailbox.to_string().as_ref()));
|
self.from = Some(mailbox.address.clone());
|
||||||
self.from = Some(mailbox.address);
|
self.from_header.push(Address::Mailbox(mailbox));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a `To` header and stores the recipient address
|
/// Adds a `To` header and stores the recipient address
|
||||||
@@ -395,8 +410,8 @@ impl EmailBuilder {
|
|||||||
/// Adds a `To` header and stores the recipient address
|
/// Adds a `To` header and stores the recipient address
|
||||||
pub fn add_to<A: ToMailbox>(&mut self, address: A) {
|
pub fn add_to<A: ToMailbox>(&mut self, address: A) {
|
||||||
let mailbox = address.to_mailbox();
|
let mailbox = address.to_mailbox();
|
||||||
self.message.add_header(("To", mailbox.to_string().as_ref()));
|
self.to.push(mailbox.address.clone());
|
||||||
self.to.push(mailbox.address);
|
self.to_header.push(Address::Mailbox(mailbox));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a `Cc` header and stores the recipient address
|
/// Adds a `Cc` header and stores the recipient address
|
||||||
@@ -408,8 +423,8 @@ impl EmailBuilder {
|
|||||||
/// Adds a `Cc` header and stores the recipient address
|
/// Adds a `Cc` header and stores the recipient address
|
||||||
pub fn add_cc<A: ToMailbox>(&mut self, address: A) {
|
pub fn add_cc<A: ToMailbox>(&mut self, address: A) {
|
||||||
let mailbox = address.to_mailbox();
|
let mailbox = address.to_mailbox();
|
||||||
self.message.add_header(("Cc", mailbox.to_string().as_ref()));
|
self.to.push(mailbox.address.clone());
|
||||||
self.to.push(mailbox.address);
|
self.cc_header.push(Address::Mailbox(mailbox));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a `Reply-To` header
|
/// Adds a `Reply-To` header
|
||||||
@@ -421,7 +436,7 @@ impl EmailBuilder {
|
|||||||
/// Adds a `Reply-To` header
|
/// Adds a `Reply-To` header
|
||||||
pub fn add_reply_to<A: ToMailbox>(&mut self, address: A) {
|
pub fn add_reply_to<A: ToMailbox>(&mut self, address: A) {
|
||||||
let mailbox = address.to_mailbox();
|
let mailbox = address.to_mailbox();
|
||||||
self.message.add_header(("Reply-To", mailbox.to_string().as_ref()));
|
self.reply_to_header.push(Address::Mailbox(mailbox));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a `Sender` header
|
/// Adds a `Sender` header
|
||||||
@@ -433,8 +448,8 @@ impl EmailBuilder {
|
|||||||
/// Adds a `Sender` header
|
/// Adds a `Sender` header
|
||||||
pub fn set_sender<A: ToMailbox>(&mut self, address: A) {
|
pub fn set_sender<A: ToMailbox>(&mut self, address: A) {
|
||||||
let mailbox = address.to_mailbox();
|
let mailbox = address.to_mailbox();
|
||||||
self.message.add_header(("Sender", mailbox.to_string().as_ref()));
|
self.from = Some(mailbox.address.clone());
|
||||||
self.from = Some(mailbox.address);
|
self.sender_header = Some(mailbox);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a `Subject` header
|
/// Adds a `Subject` header
|
||||||
@@ -544,6 +559,38 @@ impl EmailBuilder {
|
|||||||
if self.to.is_empty() {
|
if self.to.is_empty() {
|
||||||
return Err(Error::MissingTo);
|
return Err(Error::MissingTo);
|
||||||
}
|
}
|
||||||
|
// If there are multiple addresses in "From", the "Sender" is required.
|
||||||
|
if self.from_header.len() >= 2 && self.sender_header.is_none() {
|
||||||
|
// So, we must find something to put as Sender.
|
||||||
|
for possible_sender in self.from_header.iter() {
|
||||||
|
// Only a mailbox can be used as sender, not Address::Group.
|
||||||
|
if let &Address::Mailbox(ref mbx) = possible_sender {
|
||||||
|
self.sender_header = Some(mbx.clone());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Address::Group is not yet supported, so the line below will never panic.
|
||||||
|
// If groups are supported one day, add another Error for this case
|
||||||
|
// and return it here, if sender_header is still None at this point.
|
||||||
|
assert!(self.sender_header.is_some());
|
||||||
|
}
|
||||||
|
// Add the sender header, if any.
|
||||||
|
if let Some(v) = self.sender_header {
|
||||||
|
self.message.add_header(("Sender", v.to_string().as_ref()));
|
||||||
|
}
|
||||||
|
// Add the collected addresses as mailbox-list all at once.
|
||||||
|
// The unwraps are fine because the conversions for Vec<Address> never errs.
|
||||||
|
self.message.add_header(Header::new_with_value("To".into(), self.to_header).unwrap());
|
||||||
|
self.message.add_header(Header::new_with_value("From".into(), self.from_header).unwrap());
|
||||||
|
if !self.cc_header.is_empty() {
|
||||||
|
self.message.add_header(Header::new_with_value("Cc".into(), self.cc_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.date_issued {
|
if !self.date_issued {
|
||||||
self.message.add_header(("Date", Tm::rfc822z(&now()).to_string().as_ref()));
|
self.message.add_header(("Date", Tm::rfc822z(&now()).to_string().as_ref()));
|
||||||
@@ -678,6 +725,27 @@ mod test {
|
|||||||
assert_eq!(current_message.to_string(), email.message_id());
|
assert_eq!(current_message.to_string(), email.message_id());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_multiple_from() {
|
||||||
|
let email_builder = EmailBuilder::new();
|
||||||
|
let date_now = now();
|
||||||
|
let email = email_builder.to("anna@example.com")
|
||||||
|
.from("dieter@example.com")
|
||||||
|
.from("joachim@example.com")
|
||||||
|
.date(&date_now)
|
||||||
|
.subject("Invitation")
|
||||||
|
.body("We invite you!")
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
assert_eq!(format!("{}", email),
|
||||||
|
format!("Date: {}\r\nSubject: Invitation\r\nSender: \
|
||||||
|
<dieter@example.com>\r\nTo: <anna@example.com>\r\nFrom: \
|
||||||
|
<dieter@example.com>, <joachim@example.com>\r\nMIME-Version: \
|
||||||
|
1.0\r\nMessage-ID: <{}.lettre@localhost>\r\n\r\nWe invite you!\r\n",
|
||||||
|
date_now.rfc822z(),
|
||||||
|
email.message_id()));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_simple_email_builder() {
|
fn test_simple_email_builder() {
|
||||||
let email_builder = EmailBuilder::new();
|
let email_builder = EmailBuilder::new();
|
||||||
@@ -696,10 +764,10 @@ mod test {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(format!("{}", email),
|
assert_eq!(format!("{}", email),
|
||||||
format!("To: <user@localhost>\r\nFrom: <user@localhost>\r\nCc: \"Alias\" \
|
format!("Date: {}\r\nSubject: Hello\r\nX-test: value\r\nSender: \
|
||||||
<cc@localhost>\r\nReply-To: <reply@localhost>\r\nSender: \
|
<sender@localhost>\r\nTo: <user@localhost>\r\nFrom: \
|
||||||
<sender@localhost>\r\nDate: {}\r\nSubject: Hello\r\nX-test: \
|
<user@localhost>\r\nCc: \"Alias\" <cc@localhost>\r\nReply-To: \
|
||||||
value\r\nMIME-Version: 1.0\r\nMessage-ID: \
|
<reply@localhost>\r\nMIME-Version: 1.0\r\nMessage-ID: \
|
||||||
<{}.lettre@localhost>\r\n\r\nHello World!\r\n",
|
<{}.lettre@localhost>\r\n\r\nHello World!\r\n",
|
||||||
date_now.rfc822z(),
|
date_now.rfc822z(),
|
||||||
email.message_id()));
|
email.message_id()));
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
//! A trait to represent a stream
|
//! A trait to represent a stream
|
||||||
|
|
||||||
|
use openssl::ssl::{Ssl, SslContext, SslStream};
|
||||||
use openssl::ssl::{SslContext, SslStream};
|
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::{Debug, Formatter};
|
use std::fmt::{Debug, Formatter};
|
||||||
use std::io;
|
use std::io;
|
||||||
@@ -24,9 +23,13 @@ impl Connector for NetworkStream {
|
|||||||
|
|
||||||
match ssl_context {
|
match ssl_context {
|
||||||
Some(context) => {
|
Some(context) => {
|
||||||
match SslStream::connect(context, tcp_stream) {
|
match Ssl::new(context) {
|
||||||
Ok(stream) => Ok(NetworkStream::Ssl(stream)),
|
Ok(ssl) => {
|
||||||
Err(err) => Err(io::Error::new(ErrorKind::Other, err)),
|
ssl.connect(tcp_stream)
|
||||||
|
.map(|s| NetworkStream::Ssl(s))
|
||||||
|
.map_err(|e| io::Error::new(ErrorKind::Other, e))
|
||||||
|
}
|
||||||
|
Err(e) => Err(io::Error::new(ErrorKind::Other, e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => Ok(NetworkStream::Plain(tcp_stream)),
|
None => Ok(NetworkStream::Plain(tcp_stream)),
|
||||||
@@ -37,9 +40,14 @@ impl Connector for NetworkStream {
|
|||||||
|
|
||||||
*self = match *self {
|
*self = match *self {
|
||||||
NetworkStream::Plain(ref mut stream) => {
|
NetworkStream::Plain(ref mut stream) => {
|
||||||
match SslStream::connect(ssl_context, stream.try_clone().unwrap()) {
|
match Ssl::new(ssl_context) {
|
||||||
Ok(ssl_stream) => NetworkStream::Ssl(ssl_stream),
|
Ok(ssl) => {
|
||||||
Err(err) => return Err(io::Error::new(ErrorKind::Other, err)),
|
match ssl.connect(stream.try_clone().unwrap()) {
|
||||||
|
Ok(ssl_stream) => NetworkStream::Ssl(ssl_stream),
|
||||||
|
Err(err) => return Err(io::Error::new(ErrorKind::Other, err)),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => return Err(io::Error::new(ErrorKind::Other, e)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NetworkStream::Ssl(_) => return Ok(()),
|
NetworkStream::Ssl(_) => return Ok(()),
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ impl SmtpTransportBuilder {
|
|||||||
Some(addr) => {
|
Some(addr) => {
|
||||||
Ok(SmtpTransportBuilder {
|
Ok(SmtpTransportBuilder {
|
||||||
server_addr: addr,
|
server_addr: addr,
|
||||||
ssl_context: SslContext::new(SslMethod::Tlsv1).unwrap(),
|
ssl_context: SslContext::builder(SslMethod::tls()).unwrap().build(),
|
||||||
security_level: SecurityLevel::Opportunistic,
|
security_level: SecurityLevel::Opportunistic,
|
||||||
smtp_utf8: false,
|
smtp_utf8: false,
|
||||||
credentials: None,
|
credentials: None,
|
||||||
|
|||||||
Reference in New Issue
Block a user