Merge pull request #128 from amousset/split-crates-transport
Split crates
This commit is contained in:
21
.travis.yml
21
.travis.yml
@@ -4,6 +4,7 @@ rust:
|
||||
- stable
|
||||
- beta
|
||||
- nightly
|
||||
- 1.13.0
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
@@ -12,39 +13,25 @@ matrix:
|
||||
sudo: required
|
||||
|
||||
cache:
|
||||
apt: true
|
||||
pip: true
|
||||
directories:
|
||||
- target/debug/deps
|
||||
- target/debug/build
|
||||
- target/release/deps
|
||||
- target/release/build
|
||||
|
||||
install:
|
||||
- pip install 'travis-cargo<0.2' --user
|
||||
- export PATH=$HOME/.local/bin:$PATH
|
||||
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
- postfix
|
||||
- libcurl4-openssl-dev
|
||||
- libelf-dev
|
||||
- libdw-dev
|
||||
|
||||
before_script:
|
||||
- smtp-sink 2525 1000&
|
||||
- sudo chgrp -R postdrop /var/spool/postfix/maildrop
|
||||
|
||||
script:
|
||||
- travis-cargo build
|
||||
- travis-cargo test
|
||||
- travis-cargo doc
|
||||
|
||||
after_success:
|
||||
- ./.travis/doc.sh
|
||||
- ./.travis/coverage.sh
|
||||
- travis-cargo --only nightly bench
|
||||
- |
|
||||
cd lettre && cargo build && cargo test
|
||||
cd ../lettre_email && cargo build && cargo test
|
||||
|
||||
env:
|
||||
global:
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
#!/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-*
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/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
|
||||
34
Cargo.toml
34
Cargo.toml
@@ -1,29 +1,5 @@
|
||||
[package]
|
||||
|
||||
name = "lettre"
|
||||
version = "0.6.2"
|
||||
description = "Email client"
|
||||
readme = "README.md"
|
||||
documentation = "https://docs.rs/lettre/"
|
||||
repository = "https://github.com/lettre/lettre"
|
||||
license = "MIT"
|
||||
authors = ["Alexis Mousset <contact@amousset.me>"]
|
||||
keywords = ["email", "smtp", "mailer"]
|
||||
|
||||
[dependencies]
|
||||
bufstream = "^0.1"
|
||||
email = "^0.0"
|
||||
log = "^0.3"
|
||||
mime = "^0.2"
|
||||
openssl = "^0.9"
|
||||
base64 = "~0.5.0"
|
||||
hex = "^0.2.0"
|
||||
rust-crypto = "^0.2"
|
||||
time = "^0.1"
|
||||
uuid = { version = ">=0.4, <0.6", features = ["v4"] }
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "^0.4"
|
||||
|
||||
[features]
|
||||
unstable = []
|
||||
[workspace]
|
||||
members = [
|
||||
"lettre",
|
||||
"lettre_email",
|
||||
]
|
||||
@@ -1,44 +0,0 @@
|
||||
#![feature(test)]
|
||||
|
||||
extern crate lettre;
|
||||
extern crate test;
|
||||
|
||||
use lettre::transport::smtp::SmtpTransportBuilder;
|
||||
use lettre::transport::EmailTransport;
|
||||
use lettre::email::EmailBuilder;
|
||||
|
||||
#[bench]
|
||||
fn bench_simple_send(b: &mut test::Bencher) {
|
||||
let mut sender = SmtpTransportBuilder::new("127.0.0.1:2525").unwrap().build();
|
||||
b.iter(|| {
|
||||
let email = EmailBuilder::new()
|
||||
.to("root@localhost")
|
||||
.from("user@localhost")
|
||||
.body("Hello World!")
|
||||
.subject("Hello")
|
||||
.build()
|
||||
.unwrap();
|
||||
let result = sender.send(email);
|
||||
assert!(result.is_ok());
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_reuse_send(b: &mut test::Bencher) {
|
||||
let mut sender = SmtpTransportBuilder::new("127.0.0.1:2525")
|
||||
.unwrap()
|
||||
.connection_reuse(true)
|
||||
.build();
|
||||
b.iter(|| {
|
||||
let email = EmailBuilder::new()
|
||||
.to("root@localhost")
|
||||
.from("user@localhost")
|
||||
.body("Hello World!")
|
||||
.subject("Hello")
|
||||
.build()
|
||||
.unwrap();
|
||||
let result = sender.send(email);
|
||||
assert!(result.is_ok());
|
||||
});
|
||||
sender.close()
|
||||
}
|
||||
29
lettre/Cargo.toml
Normal file
29
lettre/Cargo.toml
Normal file
@@ -0,0 +1,29 @@
|
||||
[package]
|
||||
|
||||
name = "lettre"
|
||||
version = "0.7.0"
|
||||
description = "Email client"
|
||||
readme = "README.md"
|
||||
documentation = "https://docs.rs/lettre/"
|
||||
repository = "https://github.com/lettre/lettre"
|
||||
license = "MIT"
|
||||
authors = ["Alexis Mousset <contact@amousset.me>"]
|
||||
categories = ["email"]
|
||||
keywords = ["email", "smtp", "mailer"]
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "lettre/lettre" }
|
||||
|
||||
[dependencies]
|
||||
bufstream = "^0.1"
|
||||
log = "^0.3"
|
||||
openssl = "^0.9"
|
||||
base64 = "^0.5"
|
||||
hex = "^0.2"
|
||||
rust-crypto = "^0.2"
|
||||
|
||||
[dev-dependencies]
|
||||
env_logger = "^0.4"
|
||||
|
||||
[features]
|
||||
unstable = []
|
||||
1
lettre/LICENSE
Symbolic link
1
lettre/LICENSE
Symbolic link
@@ -0,0 +1 @@
|
||||
../LICENSE
|
||||
1
lettre/README.md
Symbolic link
1
lettre/README.md
Symbolic link
@@ -0,0 +1 @@
|
||||
../README.md
|
||||
37
lettre/benches/transport_smtp.rs
Normal file
37
lettre/benches/transport_smtp.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
#![feature(test)]
|
||||
|
||||
extern crate lettre;
|
||||
extern crate test;
|
||||
|
||||
use lettre::smtp::SmtpTransportBuilder;
|
||||
use lettre::{EmailTransport, SimpleSendableEmail};
|
||||
|
||||
#[bench]
|
||||
fn bench_simple_send(b: &mut test::Bencher) {
|
||||
let mut sender = SmtpTransportBuilder::new("127.0.0.1:2525").unwrap().build();
|
||||
b.iter(|| {
|
||||
let email = SimpleSendableEmail::new("user@localhost",
|
||||
vec!["root@localhost"],
|
||||
"id",
|
||||
"Hello world");
|
||||
let result = sender.send(email);
|
||||
assert!(result.is_ok());
|
||||
});
|
||||
}
|
||||
|
||||
#[bench]
|
||||
fn bench_reuse_send(b: &mut test::Bencher) {
|
||||
let mut sender = SmtpTransportBuilder::new("127.0.0.1:2525")
|
||||
.unwrap()
|
||||
.connection_reuse(true)
|
||||
.build();
|
||||
b.iter(|| {
|
||||
let email = SimpleSendableEmail::new("user@localhost",
|
||||
vec!["root@localhost"],
|
||||
"file_id",
|
||||
"Hello file");
|
||||
let result = sender.send(email);
|
||||
assert!(result.is_ok());
|
||||
});
|
||||
sender.close()
|
||||
}
|
||||
24
lettre/examples/smtp.rs
Normal file
24
lettre/examples/smtp.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
extern crate lettre;
|
||||
|
||||
use lettre::{EmailTransport, SimpleSendableEmail};
|
||||
use lettre::smtp::SmtpTransportBuilder;
|
||||
|
||||
fn main() {
|
||||
let email = SimpleSendableEmail::new("user@localhost",
|
||||
vec!["root@localhost"],
|
||||
"file_id",
|
||||
"Hello file");
|
||||
|
||||
// Open a local connection on port 25
|
||||
let mut mailer = SmtpTransportBuilder::localhost().unwrap().build();
|
||||
// Send the email
|
||||
let result = mailer.send(email);
|
||||
|
||||
if result.is_ok() {
|
||||
println!("Email sent");
|
||||
} else {
|
||||
println!("Could not send email: {:?}", result);
|
||||
}
|
||||
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
1
lettre/rustfmt.toml
Symbolic link
1
lettre/rustfmt.toml
Symbolic link
@@ -0,0 +1 @@
|
||||
../rustfmt.toml
|
||||
@@ -1,12 +1,12 @@
|
||||
//! This transport creates a file for each email, containing the envelope information and the email
|
||||
//! itself.
|
||||
|
||||
use email::SendableEmail;
|
||||
use EmailTransport;
|
||||
use SendableEmail;
|
||||
use file::error::FileResult;
|
||||
use std::fs::File;
|
||||
use std::io::prelude::*;
|
||||
use std::path::{Path, PathBuf};
|
||||
use transport::EmailTransport;
|
||||
use transport::file::error::FileResult;
|
||||
|
||||
pub mod error;
|
||||
|
||||
@@ -34,8 +34,8 @@ impl EmailTransport<FileResult> for FileEmailTransport {
|
||||
|
||||
let log_line = format!("{}: from=<{}> to=<{}>\n",
|
||||
email.message_id(),
|
||||
email.envelope().from,
|
||||
email.envelope().to.join("> to=<"));
|
||||
email.from(),
|
||||
email.to().join("> to=<"));
|
||||
|
||||
try!(f.write_all(log_line.as_bytes()));
|
||||
try!(f.write_all(email.message().as_bytes()));
|
||||
@@ -2,65 +2,9 @@
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! This mailer is divided into:
|
||||
//!
|
||||
//! * An `email` part: builds the email message
|
||||
//! * A `transport` part: contains the available transports for your emails. To be sendable, the
|
||||
//! This mailer contains the available transports for your emails. To be sendable, the
|
||||
//! emails have to implement `SendableEmail`.
|
||||
//!
|
||||
//! ## Creating messages
|
||||
//!
|
||||
//! The `email` part builds email messages. For now, it does not support attachments.
|
||||
//! An email is built using an `EmailBuilder`. The simplest email could be:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use lettre::email::EmailBuilder;
|
||||
//!
|
||||
//! // Create an email
|
||||
//! let email = EmailBuilder::new()
|
||||
//! // Addresses can be specified by the tuple (email, alias)
|
||||
//! .to(("user@example.org", "Firstname Lastname"))
|
||||
//! // ... or by an address only
|
||||
//! .from("user@example.com")
|
||||
//! .subject("Hi, Hello world")
|
||||
//! .text("Hello world.")
|
||||
//! .build();
|
||||
//!
|
||||
//! assert!(email.is_ok());
|
||||
//! ```
|
||||
//!
|
||||
//! When the `build` method is called, the `EmailBuilder` will add the missing headers (like
|
||||
//! `Message-ID` or `Date`) and check for missing necessary ones (like `From` or `To`). It will
|
||||
//! then generate an `Email` that can be sent.
|
||||
//!
|
||||
//! The `text()` method will create a plain text email, while the `html()` method will create an
|
||||
//! HTML email. You can use the `alternative()` method to provide both versions, using plain text
|
||||
//! as fallback for the HTML version.
|
||||
//!
|
||||
//! Below is a more complete example, not using method chaining:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use lettre::email::EmailBuilder;
|
||||
//!
|
||||
//! let mut builder = EmailBuilder::new();
|
||||
//! builder.add_to(("user@example.org", "Alias name"));
|
||||
//! builder.add_cc(("user@example.net", "Alias name"));
|
||||
//! builder.add_from("no-reply@example.com");
|
||||
//! builder.add_from("no-reply@example.eu");
|
||||
//! builder.set_sender("no-reply@example.com");
|
||||
//! builder.set_subject("Hello world");
|
||||
//! builder.set_alternative("<h2>Hi, Hello world.</h2>", "Hi, Hello world.");
|
||||
//! builder.add_reply_to("contact@example.com");
|
||||
//! builder.add_header(("X-Custom-Header", "my header"));
|
||||
//!
|
||||
//! let email = builder.build();
|
||||
//! assert!(email.is_ok());
|
||||
//! ```
|
||||
//!
|
||||
//! See the `EmailBuilder` documentation for a complete list of methods.
|
||||
//!
|
||||
//! ## Sending messages
|
||||
//!
|
||||
//! The following sections describe the available transport methods to handle emails.
|
||||
//!
|
||||
//! * The `SmtpTransport` uses the SMTP protocol to send the message over the network. It is
|
||||
@@ -93,18 +37,16 @@
|
||||
//! This is the most basic example of usage:
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use lettre::transport::smtp::SmtpTransportBuilder;
|
||||
//! use lettre::email::EmailBuilder;
|
||||
//! use lettre::transport::EmailTransport;
|
||||
//! use lettre::transport::smtp::SecurityLevel;
|
||||
//! use lettre::{SimpleSendableEmail, EmailTransport};
|
||||
//! use lettre::smtp::SmtpTransportBuilder;
|
||||
//! use lettre::smtp::SecurityLevel;
|
||||
//!
|
||||
//! let email = EmailBuilder::new()
|
||||
//! .to("root@localhost")
|
||||
//! .from("user@localhost")
|
||||
//! .body("Hello World!")
|
||||
//! .subject("Hello")
|
||||
//! .build()
|
||||
//! .unwrap();
|
||||
//! let email = SimpleSendableEmail::new(
|
||||
//! "user@localhost",
|
||||
//! vec!["root@localhost"],
|
||||
//! "message_id",
|
||||
//! "Hello world"
|
||||
//! );
|
||||
//!
|
||||
//! // Open a local connection on port 25
|
||||
//! let mut mailer =
|
||||
@@ -118,20 +60,18 @@
|
||||
//! #### Complete example
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! use lettre::email::EmailBuilder;
|
||||
//! use lettre::transport::smtp::{SecurityLevel, SmtpTransport,
|
||||
//! use lettre::smtp::{SecurityLevel, SmtpTransport,
|
||||
//! SmtpTransportBuilder};
|
||||
//! use lettre::transport::smtp::authentication::Mechanism;
|
||||
//! use lettre::transport::smtp::SUBMISSION_PORT;
|
||||
//! use lettre::transport::EmailTransport;
|
||||
//! use lettre::smtp::authentication::Mechanism;
|
||||
//! use lettre::smtp::SUBMISSION_PORT;
|
||||
//! use lettre::{SimpleSendableEmail, EmailTransport};
|
||||
//!
|
||||
//! let email = EmailBuilder::new()
|
||||
//! .to("root@localhost")
|
||||
//! .from("user@localhost")
|
||||
//! .body("Hello World!")
|
||||
//! .subject("Hello")
|
||||
//! .build()
|
||||
//! .unwrap();
|
||||
//! let email = SimpleSendableEmail::new(
|
||||
//! "user@localhost",
|
||||
//! vec!["root@localhost"],
|
||||
//! "message_id",
|
||||
//! "Hello world"
|
||||
//! );
|
||||
//!
|
||||
//! // Connect to a remote server on a custom port
|
||||
//! let mut mailer = SmtpTransportBuilder::new(("server.tld",
|
||||
@@ -167,9 +107,9 @@
|
||||
//! error handling:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use lettre::transport::smtp::SMTP_PORT;
|
||||
//! use lettre::transport::smtp::client::Client;
|
||||
//! use lettre::transport::smtp::client::net::NetworkStream;
|
||||
//! use lettre::smtp::SMTP_PORT;
|
||||
//! use lettre::smtp::client::Client;
|
||||
//! use lettre::smtp::client::net::NetworkStream;
|
||||
//!
|
||||
//! let mut email_client: Client<NetworkStream> = Client::new();
|
||||
//! let _ = email_client.connect(&("localhost", SMTP_PORT), None);
|
||||
@@ -186,17 +126,15 @@
|
||||
//! The sendmail transport sends the email using the local sendmail command.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use lettre::transport::sendmail::SendmailTransport;
|
||||
//! use lettre::transport::EmailTransport;
|
||||
//! use lettre::email::EmailBuilder;
|
||||
//! use lettre::sendmail::SendmailTransport;
|
||||
//! use lettre::{SimpleSendableEmail, EmailTransport};
|
||||
//!
|
||||
//! let email = EmailBuilder::new()
|
||||
//! .to("root@localhost")
|
||||
//! .from("user@localhost")
|
||||
//! .body("Hello World!")
|
||||
//! .subject("Hello")
|
||||
//! .build()
|
||||
//! .unwrap();
|
||||
//! let email = SimpleSendableEmail::new(
|
||||
//! "user@localhost",
|
||||
//! vec!["root@localhost"],
|
||||
//! "message_id",
|
||||
//! "Hello world"
|
||||
//! );
|
||||
//!
|
||||
//! let mut sender = SendmailTransport::new();
|
||||
//! let result = sender.send(email);
|
||||
@@ -209,17 +147,15 @@
|
||||
//! testing purposes.
|
||||
//!
|
||||
//! ```rust
|
||||
//! use lettre::transport::stub::StubEmailTransport;
|
||||
//! use lettre::transport::EmailTransport;
|
||||
//! use lettre::email::EmailBuilder;
|
||||
//! use lettre::stub::StubEmailTransport;
|
||||
//! use lettre::{SimpleSendableEmail, EmailTransport};
|
||||
//!
|
||||
//! let email = EmailBuilder::new()
|
||||
//! .to("root@localhost")
|
||||
//! .from("user@localhost")
|
||||
//! .body("Hello World!")
|
||||
//! .subject("Hello")
|
||||
//! .build()
|
||||
//! .unwrap();
|
||||
//! let email = SimpleSendableEmail::new(
|
||||
//! "user@localhost",
|
||||
//! vec!["root@localhost"],
|
||||
//! "message_id",
|
||||
//! "Hello world"
|
||||
//! );
|
||||
//!
|
||||
//! let mut sender = StubEmailTransport;
|
||||
//! let result = sender.send(email);
|
||||
@@ -241,19 +177,17 @@
|
||||
//! ```rust
|
||||
//! use std::env::temp_dir;
|
||||
//!
|
||||
//! use lettre::transport::file::FileEmailTransport;
|
||||
//! use lettre::transport::EmailTransport;
|
||||
//! use lettre::email::{EmailBuilder, SendableEmail};
|
||||
//! use lettre::file::FileEmailTransport;
|
||||
//! use lettre::{SimpleSendableEmail, EmailTransport};
|
||||
//!
|
||||
//! // Write to the local temp directory
|
||||
//! let mut sender = FileEmailTransport::new(temp_dir());
|
||||
//! let email = EmailBuilder::new()
|
||||
//! .to("root@localhost")
|
||||
//! .from("user@localhost")
|
||||
//! .body("Hello World!")
|
||||
//! .subject("Hello")
|
||||
//! .build()
|
||||
//! .unwrap();
|
||||
//! let email = SimpleSendableEmail::new(
|
||||
//! "user@localhost",
|
||||
//! vec!["root@localhost"],
|
||||
//! "message_id",
|
||||
//! "Hello world"
|
||||
//! );
|
||||
//!
|
||||
//! let result = sender.send(email);
|
||||
//! assert!(result.is_ok());
|
||||
@@ -275,16 +209,80 @@
|
||||
|
||||
#[macro_use]
|
||||
extern crate log;
|
||||
#[macro_use]
|
||||
extern crate mime;
|
||||
extern crate base64;
|
||||
extern crate hex;
|
||||
extern crate crypto;
|
||||
extern crate time;
|
||||
extern crate uuid;
|
||||
extern crate email as email_format;
|
||||
extern crate bufstream;
|
||||
extern crate openssl;
|
||||
|
||||
pub mod transport;
|
||||
pub mod email;
|
||||
pub mod smtp;
|
||||
pub mod sendmail;
|
||||
pub mod stub;
|
||||
pub mod file;
|
||||
|
||||
/// Email sendable by an SMTP client
|
||||
pub trait SendableEmail {
|
||||
/// To
|
||||
fn to(&self) -> Vec<String>;
|
||||
/// From
|
||||
fn from(&self) -> String;
|
||||
/// Message ID, used for logging
|
||||
fn message_id(&self) -> String;
|
||||
/// Message content
|
||||
fn message(self) -> String;
|
||||
}
|
||||
|
||||
/// Transport method for emails
|
||||
pub trait EmailTransport<U> {
|
||||
/// Sends the email
|
||||
fn send<T: SendableEmail>(&mut self, email: T) -> U;
|
||||
/// Close the transport explicitly
|
||||
fn close(&mut self);
|
||||
}
|
||||
|
||||
/// Minimal email structure
|
||||
#[derive(Debug,Clone)]
|
||||
pub struct SimpleSendableEmail {
|
||||
/// To
|
||||
to: Vec<String>,
|
||||
/// From
|
||||
from: String,
|
||||
/// Message ID
|
||||
message_id: String,
|
||||
/// Message content
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl SimpleSendableEmail {
|
||||
/// Returns a new email
|
||||
pub fn new(from_address: &str,
|
||||
to_addresses: Vec<&str>,
|
||||
message_id: &str,
|
||||
message: &str)
|
||||
-> SimpleSendableEmail {
|
||||
SimpleSendableEmail {
|
||||
from: from_address.to_string(),
|
||||
to: to_addresses.iter().map(|s| s.to_string()).collect(),
|
||||
message_id: message_id.to_string(),
|
||||
message: message.to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SendableEmail for SimpleSendableEmail {
|
||||
fn to(&self) -> Vec<String> {
|
||||
self.to.clone()
|
||||
}
|
||||
|
||||
fn from(&self) -> String {
|
||||
self.from.clone()
|
||||
}
|
||||
|
||||
fn message_id(&self) -> String {
|
||||
self.message_id.clone()
|
||||
}
|
||||
|
||||
fn message(self) -> String {
|
||||
self.message
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
//! This transport uilizes the sendmail executable for each email.
|
||||
|
||||
use email::SendableEmail;
|
||||
|
||||
use EmailTransport;
|
||||
use SendableEmail;
|
||||
use sendmail::error::SendmailResult;
|
||||
use std::io::prelude::*;
|
||||
use std::process::{Command, Stdio};
|
||||
|
||||
use transport::EmailTransport;
|
||||
use transport::sendmail::error::SendmailResult;
|
||||
|
||||
pub mod error;
|
||||
|
||||
/// Sends an email using the `sendmail` command
|
||||
@@ -31,10 +31,7 @@ impl EmailTransport<SendmailResult> for SendmailTransport {
|
||||
fn send<T: SendableEmail>(&mut self, email: T) -> SendmailResult {
|
||||
// Spawn the sendmail command
|
||||
let mut process = try!(Command::new(&self.command)
|
||||
.args(&["-i",
|
||||
"-f",
|
||||
&email.envelope().from,
|
||||
&email.envelope().to.join(" ")])
|
||||
.args(&["-i", "-f", &email.from(), &email.to().join(" ")])
|
||||
.stdin(Stdio::piped())
|
||||
.stdout(Stdio::piped())
|
||||
.spawn());
|
||||
@@ -4,10 +4,10 @@ use crypto::hmac::Hmac;
|
||||
use crypto::mac::Mac;
|
||||
use crypto::md5::Md5;
|
||||
use hex::ToHex;
|
||||
use smtp::NUL;
|
||||
use smtp::error::Error;
|
||||
use std::fmt;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use transport::smtp::NUL;
|
||||
use transport::smtp::error::Error;
|
||||
|
||||
/// Represents authentication mechanisms
|
||||
#[derive(PartialEq,Eq,Copy,Clone,Hash,Debug)]
|
||||
@@ -26,9 +26,7 @@ pub enum Mechanism {
|
||||
|
||||
impl Display for Mechanism {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f,
|
||||
"{}",
|
||||
match *self {
|
||||
write!(f, "{}", match *self {
|
||||
Mechanism::Plain => "PLAIN",
|
||||
Mechanism::Login => "LOGIN",
|
||||
Mechanism::CramMd5 => "CRAM-MD5",
|
||||
@@ -1,20 +1,20 @@
|
||||
//! SMTP client
|
||||
|
||||
use bufstream::BufStream;
|
||||
use openssl::ssl::SslContext;
|
||||
|
||||
use base64;
|
||||
use bufstream::BufStream;
|
||||
use openssl::ssl::SslContext;
|
||||
use smtp::{CRLF, MESSAGE_ENDING};
|
||||
use smtp::authentication::Mechanism;
|
||||
use smtp::client::net::{Connector, NetworkStream, Timeout};
|
||||
use smtp::error::{Error, SmtpResult};
|
||||
use smtp::response::ResponseParser;
|
||||
use std::fmt::Debug;
|
||||
use std::io;
|
||||
use std::io::{BufRead, Read, Write};
|
||||
use std::net::ToSocketAddrs;
|
||||
use std::string::String;
|
||||
use std::time::Duration;
|
||||
use transport::smtp::{CRLF, MESSAGE_ENDING};
|
||||
use transport::smtp::authentication::Mechanism;
|
||||
use transport::smtp::client::net::{Connector, NetworkStream, Timeout};
|
||||
use transport::smtp::error::{Error, SmtpResult};
|
||||
use transport::smtp::response::ResponseParser;
|
||||
|
||||
pub mod net;
|
||||
|
||||
@@ -204,7 +204,11 @@ impl<S: Connector + Timeout + Write + Read + Debug> Client<S> {
|
||||
if mechanism.supports_initial_response() {
|
||||
self.command(&format!("AUTH {} {}",
|
||||
mechanism,
|
||||
base64::encode_config(try!(mechanism.response(username, password, None)).as_bytes(), base64::STANDARD)))
|
||||
base64::encode_config(try!(mechanism.response(username,
|
||||
password,
|
||||
None))
|
||||
.as_bytes(),
|
||||
base64::STANDARD)))
|
||||
} else {
|
||||
let encoded_challenge = match try!(self.command(&format!("AUTH {}", mechanism)))
|
||||
.first_word() {
|
||||
@@ -232,7 +236,8 @@ impl<S: Connector + Timeout + Write + Read + Debug> Client<S> {
|
||||
let response = try!(self.command(&base64::encode_config(&try!(mechanism.response(username,
|
||||
password,
|
||||
Some(&decoded_challenge)))
|
||||
.as_bytes(), base64::STANDARD)));
|
||||
.as_bytes(),
|
||||
base64::STANDARD)));
|
||||
|
||||
if !response.has_code(334) {
|
||||
return Ok(response);
|
||||
@@ -2,12 +2,12 @@
|
||||
|
||||
use self::Error::*;
|
||||
use base64::DecodeError;
|
||||
use smtp::response::{Response, Severity};
|
||||
use std::error::Error as StdError;
|
||||
use std::fmt;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::io;
|
||||
use std::string::FromUtf8Error;
|
||||
use transport::smtp::response::{Response, Severity};
|
||||
|
||||
/// An enum of all error kinds.
|
||||
#[derive(Debug)]
|
||||
@@ -1,12 +1,12 @@
|
||||
//! ESMTP features
|
||||
|
||||
use smtp::authentication::Mechanism;
|
||||
use smtp::error::Error;
|
||||
use smtp::response::Response;
|
||||
use std::collections::HashSet;
|
||||
use std::fmt;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use std::result::Result;
|
||||
use transport::smtp::authentication::Mechanism;
|
||||
use transport::smtp::error::Error;
|
||||
use transport::smtp::response::Response;
|
||||
|
||||
/// Supported ESMTP keywords
|
||||
#[derive(PartialEq,Eq,Hash,Clone,Debug)]
|
||||
@@ -53,10 +53,7 @@ pub struct ServerInfo {
|
||||
|
||||
impl Display for ServerInfo {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f,
|
||||
"{} with {}",
|
||||
self.name,
|
||||
match self.features.is_empty() {
|
||||
write!(f, "{} with {}", self.name, match self.features.is_empty() {
|
||||
true => "no supported features".to_string(),
|
||||
false => format!("{:?}", self.features),
|
||||
})
|
||||
@@ -125,9 +122,9 @@ impl ServerInfo {
|
||||
mod test {
|
||||
|
||||
use super::{Extension, ServerInfo};
|
||||
use smtp::authentication::Mechanism;
|
||||
use smtp::response::{Category, Code, Response, Severity};
|
||||
use std::collections::HashSet;
|
||||
use transport::smtp::authentication::Mechanism;
|
||||
use transport::smtp::response::{Category, Code, Response, Severity};
|
||||
|
||||
#[test]
|
||||
fn test_extension_fmt() {
|
||||
@@ -1,15 +1,15 @@
|
||||
//! This transport sends emails using the SMTP protocol
|
||||
|
||||
use email::SendableEmail;
|
||||
use EmailTransport;
|
||||
use SendableEmail;
|
||||
use openssl::ssl::{SslContext, SslMethod};
|
||||
use smtp::authentication::Mechanism;
|
||||
use smtp::client::Client;
|
||||
use smtp::error::{Error, SmtpResult};
|
||||
use smtp::extension::{Extension, ServerInfo};
|
||||
use std::net::{SocketAddr, ToSocketAddrs};
|
||||
use std::string::String;
|
||||
use std::time::Duration;
|
||||
use transport::EmailTransport;
|
||||
use transport::smtp::authentication::Mechanism;
|
||||
use transport::smtp::client::Client;
|
||||
use transport::smtp::error::{Error, SmtpResult};
|
||||
use transport::smtp::extension::{Extension, ServerInfo};
|
||||
|
||||
pub mod extension;
|
||||
pub mod authentication;
|
||||
@@ -318,7 +318,9 @@ impl EmailTransport<SmtpResult> for SmtpTransport {
|
||||
.as_ref()
|
||||
.unwrap()
|
||||
.supports_feature(&Extension::StartTls)) {
|
||||
(&SecurityLevel::AlwaysEncrypt, false) => return Err(From::from("Could not encrypt connection, aborting")),
|
||||
(&SecurityLevel::AlwaysEncrypt, false) => {
|
||||
return Err(From::from("Could not encrypt connection, aborting"))
|
||||
}
|
||||
(&SecurityLevel::Opportunistic, false) => (),
|
||||
(&SecurityLevel::NeverEncrypt, _) => (),
|
||||
(&SecurityLevel::EncryptedWrapper, _) => (),
|
||||
@@ -387,13 +389,13 @@ impl EmailTransport<SmtpResult> for SmtpTransport {
|
||||
(false, _) => None,
|
||||
};
|
||||
|
||||
try_smtp!(self.client.mail(&email.envelope().from, mail_options), self);
|
||||
try_smtp!(self.client.mail(&email.from(), mail_options), self);
|
||||
|
||||
// Log the mail command
|
||||
info!("{}: from=<{}>", message_id, email.envelope().from);
|
||||
info!("{}: from=<{}>", message_id, email.from());
|
||||
|
||||
// Recipient
|
||||
for to_address in &email.envelope().to {
|
||||
for to_address in &email.to() {
|
||||
try_smtp!(self.client.rcpt(&to_address), self);
|
||||
// Log the rcpt command
|
||||
info!("{}: to=<{}>", message_id, to_address);
|
||||
@@ -3,10 +3,10 @@
|
||||
|
||||
use self::Category::*;
|
||||
use self::Severity::*;
|
||||
use smtp::error::{Error, SmtpResult};
|
||||
use std::fmt::{Display, Formatter, Result};
|
||||
use std::result;
|
||||
use std::str::FromStr;
|
||||
use transport::smtp::error::{Error, SmtpResult};
|
||||
|
||||
/// First digit indicates severity
|
||||
#[derive(PartialEq,Eq,Copy,Clone,Debug)]
|
||||
@@ -36,9 +36,7 @@ impl FromStr for Severity {
|
||||
|
||||
impl Display for Severity {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
write!(f,
|
||||
"{}",
|
||||
match *self {
|
||||
write!(f, "{}", match *self {
|
||||
PositiveCompletion => 2,
|
||||
PositiveIntermediate => 3,
|
||||
TransientNegativeCompletion => 4,
|
||||
@@ -81,9 +79,7 @@ impl FromStr for Category {
|
||||
|
||||
impl Display for Category {
|
||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||
write!(f,
|
||||
"{}",
|
||||
match *self {
|
||||
write!(f, "{}", match *self {
|
||||
Syntax => 0,
|
||||
Information => 1,
|
||||
Connections => 2,
|
||||
@@ -1,8 +1,8 @@
|
||||
//! This transport is a stub that only logs the message, and always returns
|
||||
//! success
|
||||
|
||||
use email::SendableEmail;
|
||||
use transport::EmailTransport;
|
||||
use EmailTransport;
|
||||
use SendableEmail;
|
||||
|
||||
pub mod error;
|
||||
|
||||
@@ -18,8 +18,8 @@ impl EmailTransport<StubResult> for StubEmailTransport {
|
||||
|
||||
info!("{}: from=<{}> to=<{:?}>",
|
||||
email.message_id(),
|
||||
email.envelope().from,
|
||||
email.envelope().to);
|
||||
email.from(),
|
||||
email.to());
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
extern crate lettre;
|
||||
|
||||
use lettre::email::{EmailBuilder, SendableEmail};
|
||||
use lettre::transport::EmailTransport;
|
||||
use lettre::{EmailTransport, SendableEmail, SimpleSendableEmail};
|
||||
|
||||
use lettre::transport::file::FileEmailTransport;
|
||||
use lettre::file::FileEmailTransport;
|
||||
use std::env::temp_dir;
|
||||
use std::fs::File;
|
||||
use std::fs::remove_file;
|
||||
@@ -12,13 +11,10 @@ use std::io::Read;
|
||||
#[test]
|
||||
fn file_transport() {
|
||||
let mut sender = FileEmailTransport::new(temp_dir());
|
||||
let email = EmailBuilder::new()
|
||||
.to("root@localhost")
|
||||
.from("user@localhost")
|
||||
.body("Hello World!")
|
||||
.subject("Hello file")
|
||||
.build()
|
||||
.unwrap();
|
||||
let email = SimpleSendableEmail::new("user@localhost",
|
||||
vec!["root@localhost"],
|
||||
"file_id",
|
||||
"Hello file");
|
||||
let result = sender.send(email.clone());
|
||||
assert!(result.is_ok());
|
||||
|
||||
17
lettre/tests/transport_sendmail.rs
Normal file
17
lettre/tests/transport_sendmail.rs
Normal file
@@ -0,0 +1,17 @@
|
||||
extern crate lettre;
|
||||
|
||||
use lettre::{EmailTransport, SimpleSendableEmail};
|
||||
use lettre::sendmail::SendmailTransport;
|
||||
|
||||
#[test]
|
||||
fn sendmail_transport_simple() {
|
||||
let mut sender = SendmailTransport::new();
|
||||
let email = SimpleSendableEmail::new("user@localhost",
|
||||
vec!["root@localhost"],
|
||||
"sendmail_id",
|
||||
"Hello sendmail");
|
||||
|
||||
let result = sender.send(email);
|
||||
println!("{:?}", result);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
20
lettre/tests/transport_smtp.rs
Normal file
20
lettre/tests/transport_smtp.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
extern crate lettre;
|
||||
|
||||
use lettre::{EmailTransport, SimpleSendableEmail};
|
||||
use lettre::smtp::SecurityLevel;
|
||||
use lettre::smtp::SmtpTransportBuilder;
|
||||
|
||||
#[test]
|
||||
fn smtp_transport_simple() {
|
||||
let mut sender = SmtpTransportBuilder::new("127.0.0.1:2525")
|
||||
.unwrap()
|
||||
.security_level(SecurityLevel::Opportunistic)
|
||||
.build();
|
||||
let email = SimpleSendableEmail::new("user@localhost",
|
||||
vec!["root@localhost"],
|
||||
"smtp_id",
|
||||
"Hello smtp");
|
||||
|
||||
let result = sender.send(email);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
16
lettre/tests/transport_stub.rs
Normal file
16
lettre/tests/transport_stub.rs
Normal file
@@ -0,0 +1,16 @@
|
||||
extern crate lettre;
|
||||
|
||||
use lettre::{EmailTransport, SimpleSendableEmail};
|
||||
use lettre::stub::StubEmailTransport;
|
||||
|
||||
#[test]
|
||||
fn stub_transport() {
|
||||
let mut sender = StubEmailTransport;
|
||||
let email = SimpleSendableEmail::new("user@localhost",
|
||||
vec!["root@localhost"],
|
||||
"stub_id",
|
||||
"Hello stub");
|
||||
|
||||
let result = sender.send(email);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
39
lettre_email/CHANGELOG.md
Normal file
39
lettre_email/CHANGELOG.md
Normal file
@@ -0,0 +1,39 @@
|
||||
### 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)
|
||||
|
||||
#### Features
|
||||
|
||||
* **email**
|
||||
* multipart support
|
||||
* add non-consuming methods for Email builders
|
||||
|
||||
#### Beaking Change
|
||||
|
||||
* **email**
|
||||
* `add_header` does not return the builder anymore,
|
||||
for consistency with other methods. Use the `header`
|
||||
method instead
|
||||
22
lettre_email/Cargo.toml
Normal file
22
lettre_email/Cargo.toml
Normal file
@@ -0,0 +1,22 @@
|
||||
[package]
|
||||
|
||||
name = "lettre_email"
|
||||
version = "0.7.0"
|
||||
description = "Email builder"
|
||||
readme = "README.md"
|
||||
documentation = "https://docs.rs/lettre_email/"
|
||||
repository = "https://github.com/lettre/lettre"
|
||||
license = "MIT"
|
||||
authors = ["Alexis Mousset <contact@amousset.me>"]
|
||||
categories = ["email"]
|
||||
keywords = ["email", "mailer"]
|
||||
|
||||
[badges]
|
||||
travis-ci = { repository = "lettre/lettre_email" }
|
||||
|
||||
[dependencies]
|
||||
email = "^0.0"
|
||||
mime = "^0.2"
|
||||
time = "^0.1"
|
||||
uuid = { version = ">=0.4, <0.6", features = ["v4"] }
|
||||
lettre = { path = "../lettre" }
|
||||
1
lettre_email/LICENSE
Symbolic link
1
lettre_email/LICENSE
Symbolic link
@@ -0,0 +1 @@
|
||||
../LICENSE
|
||||
1
lettre_email/README.md
Symbolic link
1
lettre_email/README.md
Symbolic link
@@ -0,0 +1 @@
|
||||
../README.md
|
||||
31
lettre_email/examples/smtp.rs
Normal file
31
lettre_email/examples/smtp.rs
Normal file
@@ -0,0 +1,31 @@
|
||||
extern crate lettre;
|
||||
extern crate lettre_email;
|
||||
|
||||
use lettre_email::email::EmailBuilder;
|
||||
use lettre::EmailTransport;
|
||||
use lettre::smtp::SmtpTransportBuilder;
|
||||
|
||||
fn main() {
|
||||
let email = EmailBuilder::new()
|
||||
// Addresses can be specified by the tuple (email, alias)
|
||||
.to(("user@example.org", "Firstname Lastname"))
|
||||
// ... or by an address only
|
||||
.from("user@example.com")
|
||||
.subject("Hi, Hello world")
|
||||
.text("Hello world.")
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
// Open a local connection on port 25
|
||||
let mut mailer = SmtpTransportBuilder::localhost().unwrap().build();
|
||||
// Send the email
|
||||
let result = mailer.send(email);
|
||||
|
||||
if result.is_ok() {
|
||||
println!("Email sent");
|
||||
} else {
|
||||
println!("Could not send email: {:?}", result);
|
||||
}
|
||||
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
1
lettre_email/rustfmt.toml
Symbolic link
1
lettre_email/rustfmt.toml
Symbolic link
@@ -0,0 +1 @@
|
||||
../rustfmt.toml
|
||||
@@ -1,14 +1,13 @@
|
||||
//! Simple email representation
|
||||
|
||||
pub mod error;
|
||||
|
||||
use email::error::Error;
|
||||
use error::Error;
|
||||
use email_format::{Address, Header, Mailbox, MimeMessage, MimeMultipartType};
|
||||
use mime::Mime;
|
||||
use std::fmt;
|
||||
use std::fmt::{Display, Formatter};
|
||||
use time::{Tm, now};
|
||||
use uuid::Uuid;
|
||||
use lettre::SendableEmail;
|
||||
|
||||
/// Converts an address or an address with an alias to a `Header`
|
||||
pub trait IntoHeader {
|
||||
@@ -638,8 +637,7 @@ impl EmailBuilder {
|
||||
}
|
||||
// Add the sender header, if any.
|
||||
if let Some(ref v) = self.sender_header {
|
||||
self.message
|
||||
.add_header(("Sender", v.to_string().as_ref()));
|
||||
self.message.add_header(("Sender", v.to_string().as_ref()));
|
||||
}
|
||||
// Calculate the envelope
|
||||
let envelope = match self.envelope {
|
||||
@@ -732,58 +730,13 @@ impl EmailBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
/// Email sendable by an SMTP client
|
||||
pub trait SendableEmail {
|
||||
/// Envelope
|
||||
fn envelope(&self) -> &Envelope;
|
||||
/// Message ID
|
||||
fn message_id(&self) -> String;
|
||||
/// Message content
|
||||
fn message(self) -> String;
|
||||
}
|
||||
|
||||
/// Minimal email structure
|
||||
#[derive(Debug)]
|
||||
pub struct SimpleSendableEmail {
|
||||
/// Message envelope
|
||||
envelope: Envelope,
|
||||
/// Message content
|
||||
message: String,
|
||||
}
|
||||
|
||||
impl SimpleSendableEmail {
|
||||
/// Returns a new email
|
||||
pub fn new(from_address: String,
|
||||
to_addresses: Vec<String>,
|
||||
message: String)
|
||||
-> SimpleSendableEmail {
|
||||
SimpleSendableEmail {
|
||||
envelope: Envelope {
|
||||
from: from_address,
|
||||
to: to_addresses,
|
||||
},
|
||||
message: message,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl SendableEmail for SimpleSendableEmail {
|
||||
fn envelope(&self) -> &Envelope {
|
||||
&self.envelope
|
||||
}
|
||||
|
||||
fn message_id(&self) -> String {
|
||||
format!("{}", Uuid::new_v4())
|
||||
}
|
||||
|
||||
fn message(self) -> String {
|
||||
self.message
|
||||
}
|
||||
}
|
||||
|
||||
impl SendableEmail for Email {
|
||||
fn envelope(&self) -> &Envelope {
|
||||
&self.envelope
|
||||
fn to(&self) -> Vec<String> {
|
||||
self.envelope.to.clone()
|
||||
}
|
||||
|
||||
fn from(&self) -> String {
|
||||
self.envelope.from.clone()
|
||||
}
|
||||
|
||||
fn message_id(&self) -> String {
|
||||
@@ -823,7 +776,8 @@ pub trait ExtractableEmail {
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
|
||||
use super::{Email, EmailBuilder, Envelope, IntoEmail, SendableEmail, SimpleEmail};
|
||||
use lettre::SendableEmail;
|
||||
use super::{Email, EmailBuilder, Envelope, IntoEmail, SimpleEmail};
|
||||
use email_format::{Header, MimeMessage};
|
||||
use time::now;
|
||||
|
||||
@@ -959,8 +913,8 @@ mod test {
|
||||
.build()
|
||||
.unwrap();
|
||||
|
||||
assert_eq!(email.envelope().from, "sender@localhost".to_string());
|
||||
assert_eq!(email.envelope().to,
|
||||
assert_eq!(email.from(), "sender@localhost".to_string());
|
||||
assert_eq!(email.to(),
|
||||
vec!["user@localhost".to_string(),
|
||||
"cc@localhost".to_string(),
|
||||
"bcc@localhost".to_string()]);
|
||||
65
lettre_email/src/lib.rs
Normal file
65
lettre_email/src/lib.rs
Normal file
@@ -0,0 +1,65 @@
|
||||
//! Lettre is a mailer written in Rust. It provides a simple email builder and several transports.
|
||||
//!
|
||||
//! ## Overview
|
||||
//!
|
||||
//! The `email` part builds email messages. For now, it does not support attachments.
|
||||
//! An email is built using an `EmailBuilder`. The simplest email could be:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use lettre_email::email::EmailBuilder;
|
||||
//!
|
||||
//! // Create an email
|
||||
//! let email = EmailBuilder::new()
|
||||
//! // Addresses can be specified by the tuple (email, alias)
|
||||
//! .to(("user@example.org", "Firstname Lastname"))
|
||||
//! // ... or by an address only
|
||||
//! .from("user@example.com")
|
||||
//! .subject("Hi, Hello world")
|
||||
//! .text("Hello world.")
|
||||
//! .build();
|
||||
//!
|
||||
//! assert!(email.is_ok());
|
||||
//! ```
|
||||
//!
|
||||
//! When the `build` method is called, the `EmailBuilder` will add the missing headers (like
|
||||
//! `Message-ID` or `Date`) and check for missing necessary ones (like `From` or `To`). It will
|
||||
//! then generate an `Email` that can be sent.
|
||||
//!
|
||||
//! The `text()` method will create a plain text email, while the `html()` method will create an
|
||||
//! HTML email. You can use the `alternative()` method to provide both versions, using plain text
|
||||
//! as fallback for the HTML version.
|
||||
//!
|
||||
//! Below is a more complete example, not using method chaining:
|
||||
//!
|
||||
//! ```rust
|
||||
//! use lettre_email::email::EmailBuilder;
|
||||
//!
|
||||
//! let mut builder = EmailBuilder::new();
|
||||
//! builder.add_to(("user@example.org", "Alias name"));
|
||||
//! builder.add_cc(("user@example.net", "Alias name"));
|
||||
//! builder.add_from("no-reply@example.com");
|
||||
//! builder.add_from("no-reply@example.eu");
|
||||
//! builder.set_sender("no-reply@example.com");
|
||||
//! builder.set_subject("Hello world");
|
||||
//! builder.set_alternative("<h2>Hi, Hello world.</h2>", "Hi, Hello world.");
|
||||
//! builder.add_reply_to("contact@example.com");
|
||||
//! builder.add_header(("X-Custom-Header", "my header"));
|
||||
//!
|
||||
//! let email = builder.build();
|
||||
//! assert!(email.is_ok());
|
||||
//! ```
|
||||
//!
|
||||
//! See the `EmailBuilder` documentation for a complete list of methods.
|
||||
//!
|
||||
|
||||
#![deny(missing_docs, unsafe_code, unstable_features, warnings, missing_debug_implementations)]
|
||||
|
||||
#[macro_use]
|
||||
extern crate mime;
|
||||
extern crate time;
|
||||
extern crate uuid;
|
||||
extern crate email as email_format;
|
||||
extern crate lettre;
|
||||
|
||||
pub mod error;
|
||||
pub mod email;
|
||||
@@ -1,2 +0,0 @@
|
||||
reorder_imports = true
|
||||
reorder_imported_names = true
|
||||
@@ -1,16 +0,0 @@
|
||||
//! Represents an Email transport
|
||||
|
||||
pub mod smtp;
|
||||
pub mod sendmail;
|
||||
pub mod stub;
|
||||
pub mod file;
|
||||
|
||||
use email::SendableEmail;
|
||||
|
||||
/// Transport method for emails
|
||||
pub trait EmailTransport<U> {
|
||||
/// Sends the email
|
||||
fn send<T: SendableEmail>(&mut self, email: T) -> U;
|
||||
/// Close the transport explicitly
|
||||
fn close(&mut self);
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
extern crate lettre;
|
||||
|
||||
use lettre::email::EmailBuilder;
|
||||
use lettre::transport::EmailTransport;
|
||||
use lettre::transport::sendmail::SendmailTransport;
|
||||
|
||||
#[test]
|
||||
fn sendmail_transport_simple() {
|
||||
let mut sender = SendmailTransport::new();
|
||||
let email = EmailBuilder::new()
|
||||
.to("root@localhost")
|
||||
.from("user@localhost")
|
||||
.body("Hello World!")
|
||||
.subject("Hello sendmail")
|
||||
.build()
|
||||
.unwrap();
|
||||
let result = sender.send(email);
|
||||
println!("{:?}", result);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
extern crate lettre;
|
||||
|
||||
use lettre::email::EmailBuilder;
|
||||
use lettre::transport::EmailTransport;
|
||||
use lettre::transport::smtp::SecurityLevel;
|
||||
use lettre::transport::smtp::SmtpTransportBuilder;
|
||||
|
||||
#[test]
|
||||
fn smtp_transport_simple() {
|
||||
let mut sender = SmtpTransportBuilder::new("127.0.0.1:2525")
|
||||
.unwrap()
|
||||
.security_level(SecurityLevel::Opportunistic)
|
||||
.build();
|
||||
let email = EmailBuilder::new()
|
||||
.to("root@localhost")
|
||||
.from("user@localhost")
|
||||
.body("Hello World!")
|
||||
.subject("Hello smtp")
|
||||
.build()
|
||||
.unwrap();
|
||||
let result = sender.send(email);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
extern crate lettre;
|
||||
|
||||
use lettre::email::EmailBuilder;
|
||||
use lettre::transport::EmailTransport;
|
||||
use lettre::transport::stub::StubEmailTransport;
|
||||
|
||||
#[test]
|
||||
fn stub_transport() {
|
||||
let mut sender = StubEmailTransport;
|
||||
let email = EmailBuilder::new()
|
||||
.to("root@localhost")
|
||||
.from("user@localhost")
|
||||
.body("Hello World!")
|
||||
.subject("Hello stub")
|
||||
.build()
|
||||
.unwrap();
|
||||
let result = sender.send(email);
|
||||
assert!(result.is_ok());
|
||||
}
|
||||
Reference in New Issue
Block a user