Compare commits
83 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
73d823c8ca | ||
|
|
d45ee40f4a | ||
|
|
e295c5db5e | ||
|
|
a3d6722e7e | ||
|
|
fd56ec8877 | ||
|
|
81bad13175 | ||
|
|
27c8e206cf | ||
|
|
b4d03ead8c | ||
|
|
d692a9488f | ||
|
|
f3271715ec | ||
|
|
ee51cf7454 | ||
|
|
8981a7758c | ||
|
|
b91cb0770d | ||
|
|
0cff889ace | ||
|
|
d00568cbd6 | ||
|
|
32cace1252 | ||
|
|
a86cc3328e | ||
|
|
b51b2843f4 | ||
|
|
91a17ae281 | ||
|
|
bd752daf85 | ||
|
|
ed01efd890 | ||
|
|
088db45e41 | ||
|
|
955a453df9 | ||
|
|
71eda4b174 | ||
|
|
d283254b1a | ||
|
|
f3f963c6a5 | ||
|
|
bef45c48f7 | ||
|
|
e024806402 | ||
|
|
d7a8574464 | ||
|
|
9b22f5867e | ||
|
|
17abeb3957 | ||
|
|
e6a5c158da | ||
|
|
f4fc427a03 | ||
|
|
662072e692 | ||
|
|
4f16d9ee69 | ||
|
|
9d68629bb6 | ||
|
|
96e4f845ec | ||
|
|
4dc95281ad | ||
|
|
f3311456ad | ||
|
|
98a250f015 | ||
|
|
f2f2f98905 | ||
|
|
53e79d9620 | ||
|
|
4f11ae61ef | ||
|
|
9344ff7e5c | ||
|
|
36d20bc7b6 | ||
|
|
620c3e96dc | ||
|
|
7cab860cde | ||
|
|
f10e4e81d0 | ||
|
|
5face8614b | ||
|
|
480ed11785 | ||
|
|
a082da6ea4 | ||
|
|
2a847c1b3b | ||
|
|
f6c07f0720 | ||
|
|
bff687f55c | ||
|
|
66cd6fe3ac | ||
|
|
bc4714a2c8 | ||
|
|
547be305c5 | ||
|
|
ba719f7255 | ||
|
|
4005fc88bc | ||
|
|
173f8aa2dd | ||
|
|
aa9e9dd96e | ||
|
|
dd6601b9e5 | ||
|
|
78d8f9afb7 | ||
|
|
487bee0769 | ||
|
|
ab35bac204 | ||
|
|
30ea70edab | ||
|
|
eb4e7f9829 | ||
|
|
104935b443 | ||
|
|
1936211f8e | ||
|
|
87d0dbdf70 | ||
|
|
7bc28caf27 | ||
|
|
7498bed378 | ||
|
|
d2475ae1aa | ||
|
|
12174676d3 | ||
|
|
1850d56ec1 | ||
|
|
92134e22a4 | ||
|
|
01fde07a48 | ||
|
|
16223ee9c3 | ||
|
|
b010126c19 | ||
|
|
166178b011 | ||
|
|
aecbce50e3 | ||
|
|
cc324b4705 | ||
|
|
2785f14f31 |
@@ -1,12 +1,7 @@
|
|||||||
environment:
|
environment:
|
||||||
matrix:
|
matrix:
|
||||||
- TARGET: x86_64-pc-windows-msvc
|
- TARGET: x86_64-pc-windows-msvc
|
||||||
BITS: 64
|
|
||||||
OPENSSL_VERSION: 1_1_0f
|
|
||||||
OPENSSL_DIR: C:\OpenSSL
|
|
||||||
install:
|
install:
|
||||||
- ps: Start-FileDownload "http://slproweb.com/download/Win${env:BITS}OpenSSL-${env:OPENSSL_VERSION}.exe"
|
|
||||||
- Win%BITS%OpenSSL-%OPENSSL_VERSION%.exe /SILENT /VERYSILENT /SP- /DIR="C:\OpenSSL"
|
|
||||||
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
|
- curl -sSf -o rustup-init.exe https://win.rustup.rs/
|
||||||
- rustup-init.exe -y --default-host %TARGET%
|
- rustup-init.exe -y --default-host %TARGET%
|
||||||
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
|
- set PATH=%PATH%;C:\Users\appveyor\.cargo\bin
|
||||||
|
|||||||
7
.clog.toml
Normal file
7
.clog.toml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
[clog]
|
||||||
|
repository = "https://github.com/lettre/lettre"
|
||||||
|
changelog = "CHANGELOG.md"
|
||||||
|
|
||||||
|
[sections]
|
||||||
|
Style = ["style"]
|
||||||
|
Documentation = ["docs"]
|
||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,4 +1,6 @@
|
|||||||
.vscode/
|
.vscode/
|
||||||
.project
|
.project/
|
||||||
|
.idea/
|
||||||
|
lettre.iml
|
||||||
target/
|
target/
|
||||||
/Cargo.lock
|
/Cargo.lock
|
||||||
|
|||||||
14
.travis.yml
14
.travis.yml
@@ -12,13 +12,6 @@ matrix:
|
|||||||
|
|
||||||
sudo: required
|
sudo: required
|
||||||
|
|
||||||
cache:
|
|
||||||
directories:
|
|
||||||
- target/debug/deps
|
|
||||||
- target/debug/build
|
|
||||||
- target/release/deps
|
|
||||||
- target/release/build
|
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
@@ -29,10 +22,5 @@ before_script:
|
|||||||
- sudo chgrp -R postdrop /var/spool/postfix/maildrop
|
- sudo chgrp -R postdrop /var/spool/postfix/maildrop
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- cargo test --verbose --manifest-path lettre/Cargo.toml --no-default-features
|
- cargo test --verbose --all
|
||||||
- cargo test --verbose --manifest-path lettre/Cargo.toml
|
|
||||||
- cargo test --verbose --manifest-path lettre_email/Cargo.toml
|
|
||||||
|
|
||||||
env:
|
|
||||||
global:
|
|
||||||
secure: "MaZ3TzuaAHuxmxQkfJdqRfkh7/ieScJRk0T/2yjysZhDMTYyRmp5wh/zkfW1ADuG0uc4Pqsxrsh1J9SVO7O0U5NJA8NKZi/pgiL+FHh0g4YtlHxy2xmFNB5am3Kyc+E7B4XylwTbA9S8ublVM0nvX7yX/a5fbwEUInVk2bA8fpc="
|
|
||||||
|
|||||||
97
CHANGELOG.md
Normal file
97
CHANGELOG.md
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
<a name="v0.8.1"></a>
|
||||||
|
### v0.8.1 (2018-04-11)
|
||||||
|
|
||||||
|
#### Fix
|
||||||
|
|
||||||
|
* **all:**
|
||||||
|
* Replace skeptic by some custom rustdoc invocations ([81bad131](https://github.com/lettre/lettre/commit/81bad1317519d330c46ea02f2b7a266b97cc00dd))
|
||||||
|
|
||||||
|
#### Documentation
|
||||||
|
|
||||||
|
* **all:**
|
||||||
|
* Add changelog sections for style and docs ([b4d03ead](https://github.com/lettre/lettre/commit/b4d03ead8cce04e0c3d65a30e7a07acca9530f30))
|
||||||
|
* Use clog to generate changelogs ([8981a775](https://github.com/lettre/lettre/commit/8981a7758c89be69974ef204c4390744aea94e4f), closes [#233](https://github.com/lettre/lettre/issues/233))
|
||||||
|
|
||||||
|
#### Style
|
||||||
|
|
||||||
|
* **transport-smtp:** Avoid useless empty format strings ([f3271715](https://github.com/lettre/lettre/commit/f3271715ecaf2793c9064462184867e4f22b0ead))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a name="v0.8.0"></a>
|
||||||
|
### v0.8.0 (2018-03-31)
|
||||||
|
|
||||||
|
#### Added
|
||||||
|
|
||||||
|
* Support binary files as attachment
|
||||||
|
* Move doc to a dedicated website
|
||||||
|
* Add tests for the doc using skeptic
|
||||||
|
* Added a code of conduct
|
||||||
|
* Use hostname as `ClientId` when available
|
||||||
|
|
||||||
|
#### Changed
|
||||||
|
|
||||||
|
* Detail in SMTP Response is now an enum
|
||||||
|
* Use nom for parsing smtp responses
|
||||||
|
* `Envelope` was moved from `lettre_email` to `lettre`
|
||||||
|
* `EmailAddress::new()` now returns a `Result`
|
||||||
|
* `SendableEmail` replaces `from` and `to` by `envelope` that returns an `Envelope`
|
||||||
|
* `File` transport storage format has changed
|
||||||
|
|
||||||
|
#### Fixed
|
||||||
|
|
||||||
|
* Add missing "Bcc" headers when building the email
|
||||||
|
* Specify utf-8 charset for html
|
||||||
|
* Use parts for text and html methods to work with attachments
|
||||||
|
|
||||||
|
#### Removed
|
||||||
|
|
||||||
|
* `get_ehlo` and `reset` in SmtpTransport are now private
|
||||||
|
|
||||||
|
<a name="v0.7.0"></a>
|
||||||
|
### v0.7.0 (2017-10-08)
|
||||||
|
|
||||||
|
#### Added
|
||||||
|
|
||||||
|
* Allow validating server certificate
|
||||||
|
* Initial (incomplete) attachments support
|
||||||
|
|
||||||
|
#### Changed
|
||||||
|
|
||||||
|
* Split into the *lettre* and *lettre_email* crates
|
||||||
|
* A lot of small improvements
|
||||||
|
* Use *tls-native* instead of *openssl* in smtp transport
|
||||||
|
|
||||||
|
<a name="v0.6.2"></a>
|
||||||
|
### v0.6.2 (2017-02-18)
|
||||||
|
|
||||||
|
#### Changed
|
||||||
|
|
||||||
|
* Update env-logger crate to 0.4
|
||||||
|
* Update openssl crate to 0.9
|
||||||
|
* Update uuid crate to 0.4
|
||||||
|
|
||||||
|
<a name="v0.6.1"></a>
|
||||||
|
### v0.6.1 (2016-10-19)
|
||||||
|
|
||||||
|
#### Changes
|
||||||
|
|
||||||
|
* **documentation**
|
||||||
|
* #91: Build seperate docs for each release
|
||||||
|
* #96: Add complete documentation information to README
|
||||||
|
|
||||||
|
#### Fixed
|
||||||
|
|
||||||
|
* #85: Use address-list for "To", "From" etc.
|
||||||
|
* #93: Force building tests before coverage computing
|
||||||
|
|
||||||
|
<a name="v0.6.0"></a>
|
||||||
|
### v0.6.0 (2016-05-05)
|
||||||
|
|
||||||
|
#### Changes
|
||||||
|
|
||||||
|
* multipart support
|
||||||
|
* add non-consuming methods for Email builders
|
||||||
|
* `add_header` does not return the builder anymore,
|
||||||
|
for consistency with other methods. Use the `header`
|
||||||
|
method instead
|
||||||
46
CODE_OF_CONDUCT.md
Normal file
46
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
# Contributor Covenant Code of Conduct
|
||||||
|
|
||||||
|
## Our Pledge
|
||||||
|
|
||||||
|
In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, gender identity and expression, level of experience, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
||||||
|
|
||||||
|
## Our Standards
|
||||||
|
|
||||||
|
Examples of behavior that contributes to creating a positive environment include:
|
||||||
|
|
||||||
|
* Using welcoming and inclusive language
|
||||||
|
* Being respectful of differing viewpoints and experiences
|
||||||
|
* Gracefully accepting constructive criticism
|
||||||
|
* Focusing on what is best for the community
|
||||||
|
* Showing empathy towards other community members
|
||||||
|
|
||||||
|
Examples of unacceptable behavior by participants include:
|
||||||
|
|
||||||
|
* The use of sexualized language or imagery and unwelcome sexual attention or advances
|
||||||
|
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||||
|
* Public or private harassment
|
||||||
|
* Publishing others' private information, such as a physical or electronic address, without explicit permission
|
||||||
|
* Other conduct which could reasonably be considered inappropriate in a professional setting
|
||||||
|
|
||||||
|
## Our Responsibilities
|
||||||
|
|
||||||
|
Project maintainers are responsible for clarifying the standards of acceptable behavior and are expected to take appropriate and fair corrective action in response to any instances of unacceptable behavior.
|
||||||
|
|
||||||
|
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, or to ban temporarily or permanently any contributor for other behaviors that they deem inappropriate, threatening, offensive, or harmful.
|
||||||
|
|
||||||
|
## Scope
|
||||||
|
|
||||||
|
This Code of Conduct applies both within project spaces and in public spaces when an individual is representing the project or its community. Examples of representing a project or community include using an official project e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event. Representation of a project may be further defined and clarified by project maintainers.
|
||||||
|
|
||||||
|
## Enforcement
|
||||||
|
|
||||||
|
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by contacting the project team at contact@lettre.at. The project team will review and investigate all complaints, and will respond in a way that it deems appropriate to the circumstances. The project team is obligated to maintain confidentiality with regard to the reporter of an incident. Further details of specific enforcement policies may be posted separately.
|
||||||
|
|
||||||
|
Project maintainers who do not follow or enforce the Code of Conduct in good faith may face temporary or permanent repercussions as determined by other members of the project's leadership.
|
||||||
|
|
||||||
|
## Attribution
|
||||||
|
|
||||||
|
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][version]
|
||||||
|
|
||||||
|
[homepage]: http://contributor-covenant.org
|
||||||
|
[version]: http://contributor-covenant.org/version/1/4/
|
||||||
@@ -22,10 +22,7 @@ Any line of the commit message cannot be longer 72 characters.
|
|||||||
fix: A bug fix
|
fix: A bug fix
|
||||||
docs: Documentation only changes
|
docs: Documentation only changes
|
||||||
style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
style: Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)
|
||||||
refactor: A code change that neither fixes a bug or adds a feature
|
|
||||||
perf: A code change that improves performance
|
perf: A code change that improves performance
|
||||||
test: Adding missing tests
|
|
||||||
chore: Changes to the build process or auxiliary tools and libraries such as documentation generation
|
|
||||||
|
|
||||||
**scope** is the lettre part that is being touched. Examples:
|
**scope** is the lettre part that is being touched. Examples:
|
||||||
|
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@@ -1,4 +1,4 @@
|
|||||||
Copyright (c) 2014 Alexis Mousset
|
Copyright (c) 2014-2018 Alexis Mousset
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any
|
Permission is hereby granted, free of charge, to any
|
||||||
person obtaining a copy of this software and associated
|
person obtaining a copy of this software and associated
|
||||||
|
|||||||
62
README.md
62
README.md
@@ -1,4 +1,5 @@
|
|||||||
# 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://crates.io/crates/lettre)
|
[](https://crates.io/crates/lettre)
|
||||||
@@ -6,7 +7,7 @@
|
|||||||
[](./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.
|
An email library written in Rust.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
@@ -17,16 +18,49 @@ Lettre provides the following features:
|
|||||||
* Secure delivery with SMTP using encryption and authentication
|
* Secure delivery with SMTP using encryption and authentication
|
||||||
* Easy email builders
|
* Easy email builders
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
```rust,no_run
|
||||||
|
extern crate lettre;
|
||||||
|
extern crate lettre_email;
|
||||||
|
extern crate mime;
|
||||||
|
|
||||||
|
use lettre::{EmailTransport, SmtpTransport};
|
||||||
|
use lettre_email::EmailBuilder;
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
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.")
|
||||||
|
.attachment(Path::new("Cargo.toml"), None, &mime::TEXT_PLAIN).unwrap()
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Open a local connection on port 25
|
||||||
|
let mut mailer = SmtpTransport::builder_unencrypted_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());
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|
||||||
Released versions:
|
* [User documentation](http://docs.lettre.at/)
|
||||||
|
* [API reference](https://docs.rs/lettre/)
|
||||||
* [latest](https://docs.rs/lettre/)
|
|
||||||
* [v0.7.0](https://docs.rs/lettre/0.7.0/lettre/)
|
|
||||||
* [v0.6.2](https://docs.rs/lettre/0.6.2/lettre/)
|
|
||||||
* [v0.6.1](https://docs.rs/lettre/0.6.1/lettre/)
|
|
||||||
* [v0.6.0](https://docs.rs/lettre/0.6.0/lettre/)
|
|
||||||
* [v0.5.1](https://docs.rs/lettre/0.5.1/lettre/)
|
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
@@ -35,12 +69,18 @@ To use this library, add the following to your `Cargo.toml`:
|
|||||||
|
|
||||||
```toml
|
```toml
|
||||||
[dependencies]
|
[dependencies]
|
||||||
lettre = "0.7"
|
lettre = "0.8"
|
||||||
|
lettre_email = "0.8"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Testing
|
## Testing
|
||||||
|
|
||||||
The tests require an open mail server listening locally on port 2525 and the `sendmail` command.
|
The `lettre` tests require an open mail server listening locally on port 2525 and the `sendmail` command.
|
||||||
|
|
||||||
|
## Code of conduct
|
||||||
|
|
||||||
|
Anyone who interacts with Lettre in any space, including but not limited to
|
||||||
|
this GitHub repository, must follow our [code of conduct](https://github.com/lettre/lettre/blob/master/CODE_OF_CONDUCT.md).
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
|||||||
@@ -4,18 +4,20 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8"> <meta name="description" content="Documentation for the Lettre mailer in Rust">
|
<meta charset="utf-8"> <meta name="description" content="Documentation for the Lettre mailer in Rust">
|
||||||
<meta name="author" content="Alexis Mousset">
|
<meta name="author" content="Alexis Mousset">
|
||||||
<link rel="shortcut icon" href="https://lettre.github.io/lettre//images/favicon.png" type="image/x-icon" />
|
<link rel="shortcut icon" href="http://docs.lettre.at//images/favicon.png" type="image/x-icon" />
|
||||||
|
|
||||||
<title>404 Page not found</title>
|
<title>404 Page not found</title>
|
||||||
|
|
||||||
|
|
||||||
<link href="https://lettre.github.io/lettre//css/nucleus.css" rel="stylesheet">
|
<link href="/css/nucleus.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/font-awesome.min.css" rel="stylesheet">
|
<link href="/css/font-awesome.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hybrid.css" rel="stylesheet">
|
<link href="/css/hybrid.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/featherlight.min.css" rel="stylesheet">
|
<link href="/css/featherlight.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/perfect-scrollbar.min.css" rel="stylesheet">
|
<link href="/css/perfect-scrollbar.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/theme.css" rel="stylesheet">
|
<link href="/css/horsey.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hugo-theme.css" rel="stylesheet">
|
<link href="/css/theme.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/hugo-theme.css?1522603726" rel="stylesheet">
|
||||||
|
|
||||||
<style type="text/css">
|
<style type="text/css">
|
||||||
:root #header + #content > #left > #rlblock_left {
|
:root #header + #content > #left > #rlblock_left {
|
||||||
display: none !important;
|
display: none !important;
|
||||||
@@ -31,6 +33,7 @@
|
|||||||
list-style-type: none;
|
list-style-type: none;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
@@ -44,10 +47,10 @@
|
|||||||
<h1>Error</h1>
|
<h1>Error</h1>
|
||||||
<p>
|
<p>
|
||||||
</p>
|
</p>
|
||||||
<p>Woops. Looks like this page doesn't exist.</p>
|
<p>Woops. Looks like this page doesn't exist ¯\_(ツ)_/¯.</p>
|
||||||
<p></p>
|
<p></p>
|
||||||
<p><a href="https://lettre.github.io/lettre/">Go to homepage</a></p>
|
<p><a href="http://docs.lettre.at/">Go to homepage</a></p>
|
||||||
<p><img src="https://lettre.github.io/lettre//images/gopher-404.jpg" style="width:50%"></img></p>
|
<p><img src="http://docs.lettre.at//images/gopher-404.jpg" style="width:50%"></img></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
1
docs/CNAME
Normal file
1
docs/CNAME
Normal file
@@ -0,0 +1 @@
|
|||||||
|
docs.lettre.at
|
||||||
593
docs/categories/index.html
Normal file
593
docs/categories/index.html
Normal file
@@ -0,0 +1,593 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" class="js csstransforms3d">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
|
<meta name="generator" content="Hugo 0.37.1" />
|
||||||
|
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
||||||
|
<meta name="author" content="Alexis Mousset">
|
||||||
|
|
||||||
|
<link rel="shortcut icon" href="http://docs.lettre.at//images/favicon.png" type="image/x-icon" />
|
||||||
|
|
||||||
|
<title>Categories :: Lettre site</title>
|
||||||
|
|
||||||
|
|
||||||
|
<link href="/css/nucleus.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/font-awesome.min.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/hybrid.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/featherlight.min.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/perfect-scrollbar.min.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/auto-complete.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/theme.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/hugo-theme.css?1522603726" rel="stylesheet">
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/jquery-2.x.min.js?1522603726"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
:root #header + #content > #left > #rlblock_left{
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="" data-url="/categories/">
|
||||||
|
<nav id="sidebar" class="">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="header-wrapper">
|
||||||
|
<div id="header">
|
||||||
|
<a href="http://docs.lettre.at//getting-started/intro/"><img src="http://docs.lettre.at//images/logo50.png" /></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="searchbox">
|
||||||
|
<label for="search-by"><i class="fa fa-search"></i></label>
|
||||||
|
<input data-search-input id="search-by" type="text" placeholder="Search...">
|
||||||
|
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/js/lunr.min.js?1522603726"></script>
|
||||||
|
<script type="text/javascript" src="/js/auto-complete.js?1522603726"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var baseurl = "http:\/\/docs.lettre.at\/";
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript" src="/js/search.js?1522603726"></script>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="highlightable">
|
||||||
|
<ul class="topics">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/" title="Getting started" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/getting-started/">
|
||||||
|
Getting started
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/getting-started/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/" title="Creating messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/creating-messages/">
|
||||||
|
Creating messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/email/" title="Email creation" class="dd-item ">
|
||||||
|
<a href="/creating-messages/email/">
|
||||||
|
Email creation
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/" title="Sending messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/sending-messages/">
|
||||||
|
Sending messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/sending-messages/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/smtp/" title="SMTP transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/smtp/">
|
||||||
|
SMTP transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/sendmail/" title="Sendmail transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/sendmail/">
|
||||||
|
Sendmail transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/file/" title="File transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/file/">
|
||||||
|
File transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/stub/" title="Stub transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/stub/">
|
||||||
|
Stub transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section id="footer">
|
||||||
|
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section id="body">
|
||||||
|
<div id="overlay"></div>
|
||||||
|
<div class="padding highlightable sticky-parent">
|
||||||
|
|
||||||
|
<div class="sticky-spacer">
|
||||||
|
<div id="top-bar">
|
||||||
|
|
||||||
|
|
||||||
|
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
|
<span id="sidebar-toggle-span">
|
||||||
|
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
||||||
|
<i class="fa fa-bars"></i>
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span id="toc-menu"><i class="fa fa-list-alt"></i></span>
|
||||||
|
|
||||||
|
<span class="links">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Categories
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="progress">
|
||||||
|
<div class="wrapper">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="body-inner">
|
||||||
|
|
||||||
|
<h1>Categories</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<footer class=" footline" >
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="navigation">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-next" href="/getting-started/" title="Getting started" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
||||||
|
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
||||||
|
</div>
|
||||||
|
<script src="/js/clipboard.min.js?1522603726"></script>
|
||||||
|
<script src="/js/perfect-scrollbar.min.js?1522603726"></script>
|
||||||
|
<script src="/js/perfect-scrollbar.jquery.min.js?1522603726"></script>
|
||||||
|
<script src="/js/jquery.sticky-kit.min.js?1522603726"></script>
|
||||||
|
<script src="/js/featherlight.min.js?1522603726"></script>
|
||||||
|
<script src="/js/html5shiv-printshiv.min.js?1522603726"></script>
|
||||||
|
<script src="/js/highlight.pack.js?1522603726"></script>
|
||||||
|
<script>hljs.initHighlightingOnLoad();</script>
|
||||||
|
<script src="/js/modernizr.custom.71422.js?1522603726"></script>
|
||||||
|
<script src="/js/learn.js?1522603726"></script>
|
||||||
|
<script src="/js/hugo-learn.js?1522603726"></script>
|
||||||
|
|
||||||
|
<link href="/mermaid/mermaid.css?1522603726" type="text/css" rel="stylesheet" />
|
||||||
|
<script src="/mermaid/mermaid.js?1522603726"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({ startOnLoad: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -2,12 +2,12 @@
|
|||||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
<channel>
|
<channel>
|
||||||
<title>Categories on Lettre site</title>
|
<title>Categories on Lettre site</title>
|
||||||
<link>https://lettre.github.io/lettre/categories/</link>
|
<link>http://docs.lettre.at/categories/</link>
|
||||||
<description>Recent content in Categories on Lettre site</description>
|
<description>Recent content in Categories on Lettre site</description>
|
||||||
<generator>Hugo -- gohugo.io</generator>
|
<generator>Hugo -- gohugo.io</generator>
|
||||||
<language>en-us</language>
|
<language>en-us</language>
|
||||||
|
|
||||||
<atom:link href="https://lettre.github.io/lettre/categories/index.xml" rel="self" type="application/rss+xml" />
|
<atom:link href="http://docs.lettre.at/categories/index.xml" rel="self" type="application/rss+xml" />
|
||||||
|
|
||||||
|
|
||||||
</channel>
|
</channel>
|
||||||
|
|||||||
731
docs/creating-messages/email/index.html
Normal file
731
docs/creating-messages/email/index.html
Normal file
@@ -0,0 +1,731 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" class="js csstransforms3d">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
|
<meta name="generator" content="Hugo 0.37.1" />
|
||||||
|
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
||||||
|
<meta name="author" content="Alexis Mousset">
|
||||||
|
|
||||||
|
<link rel="shortcut icon" href="http://docs.lettre.at//images/favicon.png" type="image/x-icon" />
|
||||||
|
|
||||||
|
<title>Email creation :: Lettre site</title>
|
||||||
|
|
||||||
|
|
||||||
|
<link href="/css/nucleus.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/font-awesome.min.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/hybrid.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/featherlight.min.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/perfect-scrollbar.min.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/auto-complete.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/theme.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/hugo-theme.css?1522603726" rel="stylesheet">
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/jquery-2.x.min.js?1522603726"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
:root #header + #content > #left > #rlblock_left{
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="" data-url="/creating-messages/email/">
|
||||||
|
<nav id="sidebar" class="">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="header-wrapper">
|
||||||
|
<div id="header">
|
||||||
|
<a href="http://docs.lettre.at//getting-started/intro/"><img src="http://docs.lettre.at//images/logo50.png" /></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="searchbox">
|
||||||
|
<label for="search-by"><i class="fa fa-search"></i></label>
|
||||||
|
<input data-search-input id="search-by" type="text" placeholder="Search...">
|
||||||
|
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/js/lunr.min.js?1522603726"></script>
|
||||||
|
<script type="text/javascript" src="/js/auto-complete.js?1522603726"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var baseurl = "http:\/\/docs.lettre.at\/";
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript" src="/js/search.js?1522603726"></script>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="highlightable">
|
||||||
|
<ul class="topics">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/" title="Getting started" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/getting-started/">
|
||||||
|
Getting started
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/getting-started/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/" title="Creating messages" class="dd-item
|
||||||
|
parent
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/creating-messages/">
|
||||||
|
Creating messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/email/" title="Email creation" class="dd-item active">
|
||||||
|
<a href="/creating-messages/email/">
|
||||||
|
Email creation
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/" title="Sending messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/sending-messages/">
|
||||||
|
Sending messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/getting-started/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/sending-messages/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/smtp/" title="SMTP transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/smtp/">
|
||||||
|
SMTP transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/sendmail/" title="Sendmail transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/sendmail/">
|
||||||
|
Sendmail transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/email/" title="Email creation" class="dd-item active">
|
||||||
|
<a href="/creating-messages/email/">
|
||||||
|
Email creation
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/file/" title="File transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/file/">
|
||||||
|
File transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/stub/" title="Stub transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/stub/">
|
||||||
|
Stub transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section id="footer">
|
||||||
|
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section id="body">
|
||||||
|
<div id="overlay"></div>
|
||||||
|
<div class="padding highlightable sticky-parent">
|
||||||
|
|
||||||
|
<div class="sticky-spacer">
|
||||||
|
<div id="top-bar">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="top-github-link">
|
||||||
|
<a class="github-link" href="https://github.com/lettre/lettre/edit/master/website/content/creating-messages/email.md" target="blank">
|
||||||
|
<i class="fa fa-code-fork"></i>
|
||||||
|
Edit this page
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
|
<span id="sidebar-toggle-span">
|
||||||
|
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
||||||
|
<i class="fa fa-bars"></i>
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span id="toc-menu"><i class="fa fa-list-alt"></i></span>
|
||||||
|
|
||||||
|
<span class="links">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a href='/'>Lettre site</a> > <a href='/creating-messages/'>Creating messages</a> > Email creation
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="progress">
|
||||||
|
<div class="wrapper">
|
||||||
|
<nav id="TableOfContents">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#simple-example">Simple example</a></li>
|
||||||
|
<li><a href="#complete-example">Complete example</a></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="body-inner">
|
||||||
|
|
||||||
|
<h1>Email creation</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<h4 id="simple-example">Simple example</h4>
|
||||||
|
|
||||||
|
<p>The <code>email</code> part builds email messages. For now, it does not support attachments.
|
||||||
|
An email is built using an <code>EmailBuilder</code>. The simplest email could be:</p>
|
||||||
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust" data-lang="rust"><span style="color:#66d9ef">extern</span> <span style="color:#66d9ef">crate</span> lettre_email;
|
||||||
|
|
||||||
|
<span style="color:#66d9ef">use</span> lettre_email::EmailBuilder;
|
||||||
|
|
||||||
|
<span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">main</span>() {
|
||||||
|
<span style="color:#75715e">// Create an email
|
||||||
|
</span><span style="color:#75715e"></span> <span style="color:#66d9ef">let</span> email <span style="color:#f92672">=</span> EmailBuilder::new()
|
||||||
|
<span style="color:#75715e">// Addresses can be specified by the tuple (email, alias)
|
||||||
|
</span><span style="color:#75715e"></span> .to((<span style="color:#e6db74">"user@example.org"</span>, <span style="color:#e6db74">"Firstname Lastname"</span>))
|
||||||
|
<span style="color:#75715e">// ... or by an address only
|
||||||
|
</span><span style="color:#75715e"></span> .from(<span style="color:#e6db74">"user@example.com"</span>)
|
||||||
|
.subject(<span style="color:#e6db74">"Hi, Hello world"</span>)
|
||||||
|
.text(<span style="color:#e6db74">"Hello world."</span>)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
assert<span style="color:#f92672">!</span>(email.is_ok());
|
||||||
|
}</code></pre></div>
|
||||||
|
<p>When the <code>build</code> method is called, the <code>EmailBuilder</code> will add the missing headers (like
|
||||||
|
<code>Message-ID</code> or <code>Date</code>) and check for missing necessary ones (like <code>From</code> or <code>To</code>). It will
|
||||||
|
then generate an <code>Email</code> that can be sent.</p>
|
||||||
|
|
||||||
|
<p>The <code>text()</code> method will create a plain text email, while the <code>html()</code> method will create an
|
||||||
|
HTML email. You can use the <code>alternative()</code> method to provide both versions, using plain text
|
||||||
|
as fallback for the HTML version.</p>
|
||||||
|
|
||||||
|
<h4 id="complete-example">Complete example</h4>
|
||||||
|
|
||||||
|
<p>Below is a more complete example, not using method chaining:</p>
|
||||||
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust" data-lang="rust"><span style="color:#66d9ef">extern</span> <span style="color:#66d9ef">crate</span> lettre_email;
|
||||||
|
|
||||||
|
<span style="color:#66d9ef">use</span> lettre_email::EmailBuilder;
|
||||||
|
|
||||||
|
<span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">main</span>() {
|
||||||
|
<span style="color:#66d9ef">let</span> <span style="color:#66d9ef">mut</span> builder <span style="color:#f92672">=</span> EmailBuilder::new();
|
||||||
|
builder.add_to((<span style="color:#e6db74">"user@example.org"</span>, <span style="color:#e6db74">"Alias name"</span>));
|
||||||
|
builder.add_cc((<span style="color:#e6db74">"user@example.net"</span>, <span style="color:#e6db74">"Alias name"</span>));
|
||||||
|
builder.add_from(<span style="color:#e6db74">"no-reply@example.com"</span>);
|
||||||
|
builder.add_from(<span style="color:#e6db74">"no-reply@example.eu"</span>);
|
||||||
|
builder.set_sender(<span style="color:#e6db74">"no-reply@example.com"</span>);
|
||||||
|
builder.set_subject(<span style="color:#e6db74">"Hello world"</span>);
|
||||||
|
builder.set_alternative(<span style="color:#e6db74">"<h2>Hi, Hello world.</h2>"</span>, <span style="color:#e6db74">"Hi, Hello world."</span>);
|
||||||
|
builder.add_reply_to(<span style="color:#e6db74">"contact@example.com"</span>);
|
||||||
|
builder.add_header((<span style="color:#e6db74">"X-Custom-Header"</span>, <span style="color:#e6db74">"my header"</span>));
|
||||||
|
|
||||||
|
<span style="color:#66d9ef">let</span> email <span style="color:#f92672">=</span> builder.build();
|
||||||
|
assert<span style="color:#f92672">!</span>(email.is_ok());
|
||||||
|
}</code></pre></div>
|
||||||
|
<p>See the <code>EmailBuilder</code> documentation for a complete list of methods.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<footer class=" footline" >
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="navigation">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-prev" href="/creating-messages/" title="Creating messages"> <i class="fa fa-chevron-left"></i></a>
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-next" href="/sending-messages/" title="Sending messages" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
||||||
|
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
||||||
|
</div>
|
||||||
|
<script src="/js/clipboard.min.js?1522603726"></script>
|
||||||
|
<script src="/js/perfect-scrollbar.min.js?1522603726"></script>
|
||||||
|
<script src="/js/perfect-scrollbar.jquery.min.js?1522603726"></script>
|
||||||
|
<script src="/js/jquery.sticky-kit.min.js?1522603726"></script>
|
||||||
|
<script src="/js/featherlight.min.js?1522603726"></script>
|
||||||
|
<script src="/js/html5shiv-printshiv.min.js?1522603726"></script>
|
||||||
|
<script src="/js/highlight.pack.js?1522603726"></script>
|
||||||
|
<script>hljs.initHighlightingOnLoad();</script>
|
||||||
|
<script src="/js/modernizr.custom.71422.js?1522603726"></script>
|
||||||
|
<script src="/js/learn.js?1522603726"></script>
|
||||||
|
<script src="/js/hugo-learn.js?1522603726"></script>
|
||||||
|
|
||||||
|
<link href="/mermaid/mermaid.css?1522603726" type="text/css" rel="stylesheet" />
|
||||||
|
<script src="/mermaid/mermaid.js?1522603726"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({ startOnLoad: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
|
||||||
@@ -1,56 +1,66 @@
|
|||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="js csstransforms3d">
|
<html lang="en" class="js csstransforms3d">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
<meta name="generator" content="Hugo 0.20.7" />
|
<meta name="generator" content="Hugo 0.37.1" />
|
||||||
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
||||||
<meta name="author" content="Alexis Mousset">
|
<meta name="author" content="Alexis Mousset">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="https://lettre.github.io/lettre//images/favicon.png" type="image/x-icon" />
|
<link rel="shortcut icon" href="http://docs.lettre.at//images/favicon.png" type="image/x-icon" />
|
||||||
|
|
||||||
|
<title>Creating messages :: Lettre site</title>
|
||||||
|
|
||||||
|
|
||||||
<title>Creating messages</title>
|
<link href="/css/nucleus.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/nucleus.css" rel="stylesheet">
|
<link href="/css/font-awesome.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/font-awesome.min.css" rel="stylesheet">
|
<link href="/css/hybrid.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hybrid.css" rel="stylesheet">
|
<link href="/css/featherlight.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/featherlight.min.css" rel="stylesheet">
|
<link href="/css/perfect-scrollbar.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/perfect-scrollbar.min.css" rel="stylesheet">
|
<link href="/css/auto-complete.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/horsey.css" rel="stylesheet">
|
<link href="/css/theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/theme.css" rel="stylesheet">
|
<link href="/css/hugo-theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hugo-theme.css" rel="stylesheet">
|
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery-2.x.min.js"></script>
|
|
||||||
<style type="text/css">:root #header + #content > #left > #rlblock_left
|
|
||||||
{display:none !important;}</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/jquery-2.x.min.js?1522603726"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
:root #header + #content > #left > #rlblock_left{
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="" data-url="/lettre/creating-messages/">
|
<body class="" data-url="/creating-messages/">
|
||||||
|
<nav id="sidebar" class="">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<nav id="sidebar">
|
|
||||||
<div id="header-wrapper">
|
<div id="header-wrapper">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<a href="https://lettre.github.io/lettre//getting-started/intro/"><img src="https://lettre.github.io/lettre//images/logo50.png" /></a>
|
<a href="http://docs.lettre.at//getting-started/intro/"><img src="http://docs.lettre.at//images/logo50.png" /></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="searchbox">
|
<div class="searchbox">
|
||||||
<label for="search-by"><i class="fa fa-search"></i></label>
|
<label for="search-by"><i class="fa fa-search"></i></label>
|
||||||
<input data-search-input id="search-by" type="text" placeholder="Search">
|
<input data-search-input id="search-by" type="text" placeholder="Search...">
|
||||||
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/lunr.min.js"></script>
|
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/horsey.js"></script>
|
<script type="text/javascript" src="/js/lunr.min.js?1522603726"></script>
|
||||||
|
<script type="text/javascript" src="/js/auto-complete.js?1522603726"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var baseurl = "https:\/\/lettre.github.io\/lettre\/";
|
|
||||||
|
var baseurl = "http:\/\/docs.lettre.at\/";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/search.js"></script>
|
<script type="text/javascript" src="/js/search.js?1522603726"></script>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="highlightable">
|
<div class="highlightable">
|
||||||
<ul class="topics">
|
<ul class="topics">
|
||||||
|
|
||||||
@@ -62,57 +72,44 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/" title="Getting started" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/getting-started/">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/">
|
|
||||||
<a href="/lettre/getting-started/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>1. </b>
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/intro/">
|
|
||||||
<a href="/lettre/getting-started/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/getting-started/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
@@ -126,86 +123,184 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/" title="Creating messages" class="dd-item
|
||||||
|
parent
|
||||||
|
active
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/creating-messages/">
|
||||||
|
|
||||||
<li class="dd-item active parent" data-nav-id="/lettre/creating-messages/">
|
|
||||||
<a href="/lettre/creating-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>2. </b>
|
|
||||||
|
|
||||||
Creating messages
|
Creating messages
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/">
|
|
||||||
<a href="/lettre/sending-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>3. </b>
|
|
||||||
|
|
||||||
Sending messages
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/intro/">
|
|
||||||
<a href="/lettre/sending-messages/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/email/" title="Email creation" class="dd-item ">
|
||||||
|
<a href="/creating-messages/email/">
|
||||||
|
Email creation
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/smtp/">
|
|
||||||
<a href="/lettre/sending-messages/smtp/">
|
|
||||||
<span>SMTP transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/sendmail/">
|
|
||||||
<a href="/lettre/sending-messages/sendmail/">
|
|
||||||
<span>Sendmail transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/file/">
|
|
||||||
<a href="/lettre/sending-messages/file/">
|
|
||||||
<span>File transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/stub/">
|
|
||||||
<a href="/lettre/sending-messages/stub/">
|
|
||||||
<span>Stub transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/" title="Sending messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/sending-messages/">
|
||||||
|
Sending messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/sending-messages/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/smtp/" title="SMTP transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/smtp/">
|
||||||
|
SMTP transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/sendmail/" title="Sendmail transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/sendmail/">
|
||||||
|
Sendmail transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/file/" title="File transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/file/">
|
||||||
|
File transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/stub/" title="Stub transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/stub/">
|
||||||
|
Stub transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="footer">
|
<section id="footer">
|
||||||
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
||||||
@@ -214,13 +309,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="body">
|
<section id="body">
|
||||||
<div id="overlay"></div>
|
<div id="overlay"></div>
|
||||||
|
<div class="padding highlightable sticky-parent">
|
||||||
|
|
||||||
<div class="padding highlightable">
|
<div class="sticky-spacer">
|
||||||
|
|
||||||
<div id="top-bar">
|
<div id="top-bar">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="top-github-link">
|
||||||
|
<a class="github-link" href="https://github.com/lettre/lettre/edit/master/website/content/creating-messages/_index.md" target="blank">
|
||||||
|
<i class="fa fa-code-fork"></i>
|
||||||
|
Edit this page
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
<span id="sidebar-toggle-span">
|
<span id="sidebar-toggle-span">
|
||||||
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
||||||
@@ -228,6 +339,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<span id="toc-menu"><i class="fa fa-list-alt"></i></span>
|
||||||
|
|
||||||
|
<span class="links">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -235,72 +349,58 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a href='/'>Lettre site</a> > Creating messages
|
||||||
|
|
||||||
<span itemprop="title"> Creating messages</span>
|
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="progress">
|
||||||
|
<div class="wrapper">
|
||||||
|
<nav id="TableOfContents">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#creating-messages">Creating messages</a></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div id="chapter">
|
|
||||||
|
|
||||||
<div id="body-inner">
|
<div id="body-inner">
|
||||||
|
|
||||||
|
<h1>Creating messages</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<h3 id="creating-messages">Creating messages</h3>
|
<h3 id="creating-messages">Creating messages</h3>
|
||||||
|
|
||||||
|
<p>This section explains how to create emails.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<footer class=" footline" >
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="navigation">
|
<div id="navigation">
|
||||||
|
|
||||||
@@ -313,12 +413,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-prev" href="/lettre/getting-started/intro/"> <i class="fa fa-chevron-left"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-next" href="/lettre/sending-messages/" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -338,26 +432,200 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-prev" href="/getting-started/intro/" title="Introduction"> <i class="fa fa-chevron-left"></i></a>
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-next" href="/creating-messages/email/" title="Email creation" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
||||||
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://lettre.github.io/lettre//js/clipboard.min.js"></script>
|
<script src="/js/clipboard.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.min.js"></script>
|
<script src="/js/perfect-scrollbar.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.jquery.min.js"></script>
|
<script src="/js/perfect-scrollbar.jquery.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery.sticky-kit.min.js"></script>
|
<script src="/js/jquery.sticky-kit.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/featherlight.min.js"></script>
|
<script src="/js/featherlight.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/html5shiv-printshiv.min.js"></script>
|
<script src="/js/html5shiv-printshiv.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/highlight.pack.js"></script>
|
<script src="/js/highlight.pack.js?1522603726"></script>
|
||||||
<script>hljs.initHighlightingOnLoad();</script>
|
<script>hljs.initHighlightingOnLoad();</script>
|
||||||
<script src="https://lettre.github.io/lettre//js/modernizr.custom.71422.js"></script>
|
<script src="/js/modernizr.custom.71422.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/learn.js"></script>
|
<script src="/js/learn.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/hugo-learn.js"></script>
|
<script src="/js/hugo-learn.js?1522603726"></script>
|
||||||
|
|
||||||
|
<link href="/mermaid/mermaid.css?1522603726" type="text/css" rel="stylesheet" />
|
||||||
|
<script src="/mermaid/mermaid.js?1522603726"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({ startOnLoad: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,14 +2,24 @@
|
|||||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
<channel>
|
<channel>
|
||||||
<title>Creating messages on Lettre site</title>
|
<title>Creating messages on Lettre site</title>
|
||||||
<link>https://lettre.github.io/lettre/creating-messages/</link>
|
<link>http://docs.lettre.at/creating-messages/</link>
|
||||||
<description>Recent content in Creating messages on Lettre site</description>
|
<description>Recent content in Creating messages on Lettre site</description>
|
||||||
<generator>Hugo -- gohugo.io</generator>
|
<generator>Hugo -- gohugo.io</generator>
|
||||||
<language>en-us</language>
|
<language>en-us</language>
|
||||||
<lastBuildDate>Sun, 21 May 2017 23:46:01 +0200</lastBuildDate>
|
<lastBuildDate>Sun, 21 May 2017 23:46:01 +0200</lastBuildDate>
|
||||||
|
|
||||||
<atom:link href="https://lettre.github.io/lettre/creating-messages/index.xml" rel="self" type="application/rss+xml" />
|
<atom:link href="http://docs.lettre.at/creating-messages/index.xml" rel="self" type="application/rss+xml" />
|
||||||
|
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<title>Email creation</title>
|
||||||
|
<link>http://docs.lettre.at/creating-messages/email/</link>
|
||||||
|
<pubDate>Sun, 21 Jan 2018 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
|
<guid>http://docs.lettre.at/creating-messages/email/</guid>
|
||||||
|
<description>Simple example 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:
|
||||||
|
extern crate lettre_email; use lettre_email::EmailBuilder; fn main() { // Create an email let email = EmailBuilder::new() // Addresses can be specified by the tuple (email, alias) .to((&#34;user@example.org&#34;, &#34;Firstname Lastname&#34;)) // ... or by an address only .from(&#34;user@example.com&#34;) .subject(&#34;Hi, Hello world&#34;) .</description>
|
||||||
|
</item>
|
||||||
|
|
||||||
</channel>
|
</channel>
|
||||||
</rss>
|
</rss>
|
||||||
47
docs/css/auto-complete.css
Normal file
47
docs/css/auto-complete.css
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
.autocomplete-suggestions {
|
||||||
|
text-align: left;
|
||||||
|
cursor: default;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
border-top: 0;
|
||||||
|
background: #fff;
|
||||||
|
box-shadow: -1px 1px 3px rgba(0,0,0,.1);
|
||||||
|
|
||||||
|
/* core styles should not be changed */
|
||||||
|
position: absolute;
|
||||||
|
display: none;
|
||||||
|
z-index: 9999;
|
||||||
|
max-height: 254px;
|
||||||
|
overflow: hidden;
|
||||||
|
overflow-y: auto;
|
||||||
|
box-sizing: border-box;
|
||||||
|
|
||||||
|
}
|
||||||
|
.autocomplete-suggestion {
|
||||||
|
position: relative;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 7px;
|
||||||
|
line-height: 23px;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-suggestion b {
|
||||||
|
font-weight: normal;
|
||||||
|
color: #1f8dd6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-suggestion.selected {
|
||||||
|
background: #333;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-suggestion:hover {
|
||||||
|
background: #444;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.autocomplete-suggestion > .context {
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
4
docs/css/font-awesome.min.css
vendored
4
docs/css/font-awesome.min.css
vendored
File diff suppressed because one or more lines are too long
@@ -172,7 +172,6 @@ h2 {
|
|||||||
font-size: 2.5rem;
|
font-size: 2.5rem;
|
||||||
line-height: 110% !important;
|
line-height: 110% !important;
|
||||||
margin: 2.5rem 0 1.5rem 0;
|
margin: 2.5rem 0 1.5rem 0;
|
||||||
text-transform: capitalize;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h3 {
|
h3 {
|
||||||
@@ -210,3 +209,44 @@ figcaption h4 {
|
|||||||
text-align: center;
|
text-align: center;
|
||||||
margin-top: -1.5em;
|
margin-top: -1.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.select-style {
|
||||||
|
border: 0;
|
||||||
|
width: 150px;
|
||||||
|
border-radius: 0px;
|
||||||
|
overflow: hidden;
|
||||||
|
display: inline-flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-style svg {
|
||||||
|
fill: #ccc;
|
||||||
|
width: 14px;
|
||||||
|
height: 14px;
|
||||||
|
pointer-events: none;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-style svg:hover {
|
||||||
|
fill: #e6e6e6;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-style select {
|
||||||
|
padding: 0;
|
||||||
|
width: 130%;
|
||||||
|
border: none;
|
||||||
|
box-shadow: none;
|
||||||
|
background: transparent;
|
||||||
|
background-image: none;
|
||||||
|
-webkit-appearance: none;
|
||||||
|
margin: auto;
|
||||||
|
margin-left: 0px;
|
||||||
|
margin-right: -20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-style select:focus {
|
||||||
|
outline: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.select-style :hover {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
104
docs/css/theme-blue.css
Normal file
104
docs/css/theme-blue.css
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
|
||||||
|
:root{
|
||||||
|
|
||||||
|
--MAIN-TEXT-color:#323232; /* Color of text by default */
|
||||||
|
--MAIN-TITLES-TEXT-color: #5e5e5e; /* Color of titles h2-h3-h4-h5 */
|
||||||
|
--MAIN-LINK-color:#1C90F3; /* Color of links */
|
||||||
|
--MAIN-LINK-HOVER-color:#167ad0; /* Color of hovered links */
|
||||||
|
--MAIN-ANCHOR-color: #1C90F3; /* color of anchors on titles */
|
||||||
|
|
||||||
|
--MENU-HEADER-BG-color:#1C90F3; /* Background color of menu header */
|
||||||
|
--MENU-HEADER-BORDER-color:#33a1ff; /*Color of menu header border */
|
||||||
|
|
||||||
|
--MENU-SEARCH-BG-color:#167ad0; /* Search field background color (by default borders + icons) */
|
||||||
|
--MENU-SEARCH-BOX-color: #33a1ff; /* Override search field border color */
|
||||||
|
--MENU-SEARCH-BOX-ICONS-color: #a1d2fd; /* Override search field icons color */
|
||||||
|
|
||||||
|
--MENU-SECTIONS-ACTIVE-BG-color:#20272b; /* Background color of the active section and its childs */
|
||||||
|
--MENU-SECTIONS-BG-color:#252c31; /* Background color of other sections */
|
||||||
|
--MENU-SECTIONS-LINK-color: #ccc; /* Color of links in menu */
|
||||||
|
--MENU-SECTIONS-LINK-HOVER-color: #e6e6e6; /* Color of links in menu, when hovered */
|
||||||
|
--MENU-SECTION-ACTIVE-CATEGORY-color: #777; /* Color of active category text */
|
||||||
|
--MENU-SECTION-ACTIVE-CATEGORY-BG-color: #fff; /* Color of background for the active category (only) */
|
||||||
|
|
||||||
|
--MENU-VISITED-color: #33a1ff; /* Color of 'page visited' icons in menu */
|
||||||
|
--MENU-SECTION-HR-color: #20272b; /* Color of <hr> separator in menu */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: var(--MAIN-TEXT-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus {
|
||||||
|
border-color: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2, h3, h4, h5 {
|
||||||
|
color: var(--MAIN-TITLES-TEXT-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--MAIN-LINK-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.anchor {
|
||||||
|
color: var(--MAIN-ANCHOR-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: var(--MAIN-LINK-HOVER-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar ul li.visited > a .read-icon {
|
||||||
|
color: var(--MENU-VISITED-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#body a.highlight:after {
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
height: 1px;
|
||||||
|
width: 0%;
|
||||||
|
-webkit-transition: width 0.5s ease;
|
||||||
|
-moz-transition: width 0.5s ease;
|
||||||
|
-ms-transition: width 0.5s ease;
|
||||||
|
transition: width 0.5s ease;
|
||||||
|
background-color: var(--MAIN-HOVER-color);
|
||||||
|
}
|
||||||
|
#sidebar {
|
||||||
|
background-color: var(--MENU-SECTIONS-BG-color);
|
||||||
|
}
|
||||||
|
#sidebar #header-wrapper {
|
||||||
|
background: var(--MENU-HEADER-BG-color);
|
||||||
|
color: var(--MENU-SEARCH-BOX-color);
|
||||||
|
border-color: var(--MENU-HEADER-BORDER-color);
|
||||||
|
}
|
||||||
|
#sidebar .searchbox {
|
||||||
|
border-color: var(--MENU-SEARCH-BOX-color);
|
||||||
|
background: var(--MENU-SEARCH-BG-color);
|
||||||
|
}
|
||||||
|
#sidebar ul.topics > li.parent, #sidebar ul.topics > li.active {
|
||||||
|
background: var(--MENU-SECTIONS-ACTIVE-BG-color);
|
||||||
|
}
|
||||||
|
#sidebar .searchbox * {
|
||||||
|
color: var(--MENU-SEARCH-BOX-ICONS-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a {
|
||||||
|
color: var(--MENU-SECTIONS-LINK-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a:hover {
|
||||||
|
color: var(--MENU-SECTIONS-LINK-HOVER-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar ul li.active > a {
|
||||||
|
background: var(--MENU-SECTION-ACTIVE-CATEGORY-BG-color);
|
||||||
|
color: var(--MENU-SECTION-ACTIVE-CATEGORY-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar hr {
|
||||||
|
border-color: var(--MENU-SECTION-HR-color);
|
||||||
|
}
|
||||||
|
|
||||||
104
docs/css/theme-green.css
Normal file
104
docs/css/theme-green.css
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
|
||||||
|
:root{
|
||||||
|
|
||||||
|
--MAIN-TEXT-color:#323232; /* Color of text by default */
|
||||||
|
--MAIN-TITLES-TEXT-color: #5e5e5e; /* Color of titles h2-h3-h4-h5 */
|
||||||
|
--MAIN-LINK-color:#599a3e; /* Color of links */
|
||||||
|
--MAIN-LINK-HOVER-color:#3f6d2c; /* Color of hovered links */
|
||||||
|
--MAIN-ANCHOR-color: #599a3e; /* color of anchors on titles */
|
||||||
|
|
||||||
|
--MENU-HEADER-BG-color:#74b559; /* Background color of menu header */
|
||||||
|
--MENU-HEADER-BORDER-color:#9cd484; /*Color of menu header border */
|
||||||
|
|
||||||
|
--MENU-SEARCH-BG-color:#599a3e; /* Search field background color (by default borders + icons) */
|
||||||
|
--MENU-SEARCH-BOX-color: #84c767; /* Override search field border color */
|
||||||
|
--MENU-SEARCH-BOX-ICONS-color: #c7f7c4; /* Override search field icons color */
|
||||||
|
|
||||||
|
--MENU-SECTIONS-ACTIVE-BG-color:#1b211c; /* Background color of the active section and its childs */
|
||||||
|
--MENU-SECTIONS-BG-color:#222723; /* Background color of other sections */
|
||||||
|
--MENU-SECTIONS-LINK-color: #ccc; /* Color of links in menu */
|
||||||
|
--MENU-SECTIONS-LINK-HOVER-color: #e6e6e6; /* Color of links in menu, when hovered */
|
||||||
|
--MENU-SECTION-ACTIVE-CATEGORY-color: #777; /* Color of active category text */
|
||||||
|
--MENU-SECTION-ACTIVE-CATEGORY-BG-color: #fff; /* Color of background for the active category (only) */
|
||||||
|
|
||||||
|
--MENU-VISITED-color: #599a3e; /* Color of 'page visited' icons in menu */
|
||||||
|
--MENU-SECTION-HR-color: #18211c; /* Color of <hr> separator in menu */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: var(--MAIN-TEXT-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus {
|
||||||
|
border-color: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2, h3, h4, h5 {
|
||||||
|
color: var(--MAIN-TITLES-TEXT-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--MAIN-LINK-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.anchor {
|
||||||
|
color: var(--MAIN-ANCHOR-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: var(--MAIN-LINK-HOVER-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar ul li.visited > a .read-icon {
|
||||||
|
color: var(--MENU-VISITED-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#body a.highlight:after {
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
height: 1px;
|
||||||
|
width: 0%;
|
||||||
|
-webkit-transition: width 0.5s ease;
|
||||||
|
-moz-transition: width 0.5s ease;
|
||||||
|
-ms-transition: width 0.5s ease;
|
||||||
|
transition: width 0.5s ease;
|
||||||
|
background-color: var(--MAIN-HOVER-color);
|
||||||
|
}
|
||||||
|
#sidebar {
|
||||||
|
background-color: var(--MENU-SECTIONS-BG-color);
|
||||||
|
}
|
||||||
|
#sidebar #header-wrapper {
|
||||||
|
background: var(--MENU-HEADER-BG-color);
|
||||||
|
color: var(--MENU-SEARCH-BOX-color);
|
||||||
|
border-color: var(--MENU-HEADER-BORDER-color);
|
||||||
|
}
|
||||||
|
#sidebar .searchbox {
|
||||||
|
border-color: var(--MENU-SEARCH-BOX-color);
|
||||||
|
background: var(--MENU-SEARCH-BG-color);
|
||||||
|
}
|
||||||
|
#sidebar ul.topics > li.parent, #sidebar ul.topics > li.active {
|
||||||
|
background: var(--MENU-SECTIONS-ACTIVE-BG-color);
|
||||||
|
}
|
||||||
|
#sidebar .searchbox * {
|
||||||
|
color: var(--MENU-SEARCH-BOX-ICONS-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a {
|
||||||
|
color: var(--MENU-SECTIONS-LINK-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a:hover {
|
||||||
|
color: var(--MENU-SECTIONS-LINK-HOVER-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar ul li.active > a {
|
||||||
|
background: var(--MENU-SECTION-ACTIVE-CATEGORY-BG-color);
|
||||||
|
color: var(--MENU-SECTION-ACTIVE-CATEGORY-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar hr {
|
||||||
|
border-color: var(--MENU-SECTION-HR-color);
|
||||||
|
}
|
||||||
|
|
||||||
104
docs/css/theme-red.css
Normal file
104
docs/css/theme-red.css
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
|
||||||
|
:root{
|
||||||
|
|
||||||
|
--MAIN-TEXT-color:#323232; /* Color of text by default */
|
||||||
|
--MAIN-TITLES-TEXT-color: #5e5e5e; /* Color of titles h2-h3-h4-h5 */
|
||||||
|
--MAIN-LINK-color:#f31c1c; /* Color of links */
|
||||||
|
--MAIN-LINK-HOVER-color:#d01616; /* Color of hovered links */
|
||||||
|
--MAIN-ANCHOR-color: #f31c1c; /* color of anchors on titles */
|
||||||
|
|
||||||
|
--MENU-HEADER-BG-color:#dc1010; /* Background color of menu header */
|
||||||
|
--MENU-HEADER-BORDER-color:#e23131; /*Color of menu header border */
|
||||||
|
|
||||||
|
--MENU-SEARCH-BG-color:#b90000; /* Search field background color (by default borders + icons) */
|
||||||
|
--MENU-SEARCH-BOX-color: #ef2020; /* Override search field border color */
|
||||||
|
--MENU-SEARCH-BOX-ICONS-color: #fda1a1; /* Override search field icons color */
|
||||||
|
|
||||||
|
--MENU-SECTIONS-ACTIVE-BG-color:#2b2020; /* Background color of the active section and its childs */
|
||||||
|
--MENU-SECTIONS-BG-color:#312525; /* Background color of other sections */
|
||||||
|
--MENU-SECTIONS-LINK-color: #ccc; /* Color of links in menu */
|
||||||
|
--MENU-SECTIONS-LINK-HOVER-color: #e6e6e6; /* Color of links in menu, when hovered */
|
||||||
|
--MENU-SECTION-ACTIVE-CATEGORY-color: #777; /* Color of active category text */
|
||||||
|
--MENU-SECTION-ACTIVE-CATEGORY-BG-color: #fff; /* Color of background for the active category (only) */
|
||||||
|
|
||||||
|
--MENU-VISITED-color: #ff3333; /* Color of 'page visited' icons in menu */
|
||||||
|
--MENU-SECTION-HR-color: #2b2020; /* Color of <hr> separator in menu */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
color: var(--MAIN-TEXT-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
textarea:focus, input[type="email"]:focus, input[type="number"]:focus, input[type="password"]:focus, input[type="search"]:focus, input[type="tel"]:focus, input[type="text"]:focus, input[type="url"]:focus, input[type="color"]:focus, input[type="date"]:focus, input[type="datetime"]:focus, input[type="datetime-local"]:focus, input[type="month"]:focus, input[type="time"]:focus, input[type="week"]:focus, select[multiple=multiple]:focus {
|
||||||
|
border-color: none;
|
||||||
|
box-shadow: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2, h3, h4, h5 {
|
||||||
|
color: var(--MAIN-TITLES-TEXT-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: var(--MAIN-LINK-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
.anchor {
|
||||||
|
color: var(--MAIN-ANCHOR-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: var(--MAIN-LINK-HOVER-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar ul li.visited > a .read-icon {
|
||||||
|
color: var(--MENU-VISITED-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#body a.highlight:after {
|
||||||
|
display: block;
|
||||||
|
content: "";
|
||||||
|
height: 1px;
|
||||||
|
width: 0%;
|
||||||
|
-webkit-transition: width 0.5s ease;
|
||||||
|
-moz-transition: width 0.5s ease;
|
||||||
|
-ms-transition: width 0.5s ease;
|
||||||
|
transition: width 0.5s ease;
|
||||||
|
background-color: var(--MAIN-HOVER-color);
|
||||||
|
}
|
||||||
|
#sidebar {
|
||||||
|
background-color: var(--MENU-SECTIONS-BG-color);
|
||||||
|
}
|
||||||
|
#sidebar #header-wrapper {
|
||||||
|
background: var(--MENU-HEADER-BG-color);
|
||||||
|
color: var(--MENU-SEARCH-BOX-color);
|
||||||
|
border-color: var(--MENU-HEADER-BORDER-color);
|
||||||
|
}
|
||||||
|
#sidebar .searchbox {
|
||||||
|
border-color: var(--MENU-SEARCH-BOX-color);
|
||||||
|
background: var(--MENU-SEARCH-BG-color);
|
||||||
|
}
|
||||||
|
#sidebar ul.topics > li.parent, #sidebar ul.topics > li.active {
|
||||||
|
background: var(--MENU-SECTIONS-ACTIVE-BG-color);
|
||||||
|
}
|
||||||
|
#sidebar .searchbox * {
|
||||||
|
color: var(--MENU-SEARCH-BOX-ICONS-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a {
|
||||||
|
color: var(--MENU-SECTIONS-LINK-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar a:hover {
|
||||||
|
color: var(--MENU-SECTIONS-LINK-HOVER-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar ul li.active > a {
|
||||||
|
background: var(--MENU-SECTION-ACTIVE-CATEGORY-BG-color);
|
||||||
|
color: var(--MENU-SECTION-ACTIVE-CATEGORY-color) !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar hr {
|
||||||
|
border-color: var(--MENU-SECTION-HR-color);
|
||||||
|
}
|
||||||
|
|
||||||
@@ -59,6 +59,7 @@ a:hover {
|
|||||||
}
|
}
|
||||||
pre {
|
pre {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
color: #ffffff;
|
||||||
}
|
}
|
||||||
.bg {
|
.bg {
|
||||||
background: #fff;
|
background: #fff;
|
||||||
@@ -529,6 +530,94 @@ div.notices.tip p {
|
|||||||
div.notices.tip p:first-child:after {
|
div.notices.tip p:first-child:after {
|
||||||
content: 'Tip';
|
content: 'Tip';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* attachments shortcode */
|
||||||
|
|
||||||
|
section.attachments {
|
||||||
|
margin: 2rem 0;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.attachments label {
|
||||||
|
font-weight: 400;
|
||||||
|
padding-left: 0.5em;
|
||||||
|
padding-top: 0.2em;
|
||||||
|
padding-bottom: 0.2em;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.attachments .attachments-files {
|
||||||
|
padding: 15px;
|
||||||
|
display: block;
|
||||||
|
font-size: 1rem;
|
||||||
|
margin-top: 0rem;
|
||||||
|
margin-bottom: 0rem;
|
||||||
|
color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.attachments.orange label {
|
||||||
|
color: #fff;
|
||||||
|
background: #F0B37E;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.attachments.orange .attachments-files {
|
||||||
|
background: #FFF2DB;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.attachments.green label {
|
||||||
|
color: #fff;
|
||||||
|
background: rgba(92, 184, 92, 0.8);
|
||||||
|
}
|
||||||
|
|
||||||
|
section.attachments.green .attachments-files {
|
||||||
|
background: #E6F9E6;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.attachments.blue label {
|
||||||
|
color: #fff;
|
||||||
|
background: #6AB0DE;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.attachments.blue .attachments-files {
|
||||||
|
background: #E7F2FA;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.attachments.grey label {
|
||||||
|
color: #fff;
|
||||||
|
background: #505d65;
|
||||||
|
}
|
||||||
|
|
||||||
|
section.attachments.grey .attachments-files {
|
||||||
|
background: #f4f4f4;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Children shortcode */
|
||||||
|
|
||||||
|
/* Children shortcode */
|
||||||
|
.children p {
|
||||||
|
font-size: small;
|
||||||
|
margin-top: 0px;
|
||||||
|
padding-top: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
.children-li p {
|
||||||
|
font-size: small;
|
||||||
|
font-style: italic;
|
||||||
|
|
||||||
|
}
|
||||||
|
.children-h2 p, .children-h3 p {
|
||||||
|
font-size: small;
|
||||||
|
margin-top: 0px;
|
||||||
|
padding-top: 0px;
|
||||||
|
margin-bottom: 0px;
|
||||||
|
padding-bottom: 0px;
|
||||||
|
}
|
||||||
|
.children h3,.children h2 {
|
||||||
|
margin-bottom: 0px;
|
||||||
|
margin-top: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
code, kbd, pre, samp {
|
code, kbd, pre, samp {
|
||||||
font-family: "Consolas", menlo, monospace;
|
font-family: "Consolas", menlo, monospace;
|
||||||
font-size: 92%;
|
font-size: 92%;
|
||||||
@@ -812,6 +901,9 @@ td {
|
|||||||
overflow: auto;
|
overflow: auto;
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
.hljs::selection, .hljs span::selection {
|
||||||
|
background: #b7b7b7;
|
||||||
|
}
|
||||||
.lightbox-active #body {
|
.lightbox-active #body {
|
||||||
overflow: visible;
|
overflow: visible;
|
||||||
}
|
}
|
||||||
@@ -999,6 +1091,18 @@ pre .copy-to-clipboard:hover {
|
|||||||
#sidebar ul.topics > li > a .read-icon {
|
#sidebar ul.topics > li > a .read-icon {
|
||||||
margin-top: 9px;
|
margin-top: 9px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#sidebar ul {
|
||||||
|
list-style: none;
|
||||||
|
padding: 0;
|
||||||
|
margin: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#sidebar #shortcuts li {
|
||||||
|
padding: 2px 0;
|
||||||
|
list-style: none;
|
||||||
|
}
|
||||||
|
|
||||||
#sidebar ul li .read-icon {
|
#sidebar ul li .read-icon {
|
||||||
display: none;
|
display: none;
|
||||||
float: right;
|
float: right;
|
||||||
@@ -1012,6 +1116,13 @@ pre .copy-to-clipboard:hover {
|
|||||||
display: inline;
|
display: inline;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#sidebar #shortcuts h3 {
|
||||||
|
font-family: "Novacento Sans Wide", "Helvetica", "Tahoma", "Geneva", "Arial", sans-serif;
|
||||||
|
color: white ;
|
||||||
|
margin-top:1rem;
|
||||||
|
padding-left: 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
#searchResults {
|
#searchResults {
|
||||||
text-align: left;
|
text-align: left;
|
||||||
}
|
}
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 357 KiB After Width: | Height: | Size: 434 KiB |
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,56 +1,66 @@
|
|||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="js csstransforms3d">
|
<html lang="en" class="js csstransforms3d">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
<meta name="generator" content="Hugo 0.20.7" />
|
<meta name="generator" content="Hugo 0.37.1" />
|
||||||
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
||||||
<meta name="author" content="Alexis Mousset">
|
<meta name="author" content="Alexis Mousset">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="https://lettre.github.io/lettre//images/favicon.png" type="image/x-icon" />
|
<link rel="shortcut icon" href="http://docs.lettre.at//images/favicon.png" type="image/x-icon" />
|
||||||
|
|
||||||
|
<title>Getting started :: Lettre site</title>
|
||||||
|
|
||||||
|
|
||||||
<title>Getting started</title>
|
<link href="/css/nucleus.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/nucleus.css" rel="stylesheet">
|
<link href="/css/font-awesome.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/font-awesome.min.css" rel="stylesheet">
|
<link href="/css/hybrid.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hybrid.css" rel="stylesheet">
|
<link href="/css/featherlight.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/featherlight.min.css" rel="stylesheet">
|
<link href="/css/perfect-scrollbar.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/perfect-scrollbar.min.css" rel="stylesheet">
|
<link href="/css/auto-complete.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/horsey.css" rel="stylesheet">
|
<link href="/css/theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/theme.css" rel="stylesheet">
|
<link href="/css/hugo-theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hugo-theme.css" rel="stylesheet">
|
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery-2.x.min.js"></script>
|
|
||||||
<style type="text/css">:root #header + #content > #left > #rlblock_left
|
|
||||||
{display:none !important;}</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/jquery-2.x.min.js?1522603726"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
:root #header + #content > #left > #rlblock_left{
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="" data-url="/lettre/getting-started/">
|
<body class="" data-url="/getting-started/">
|
||||||
|
<nav id="sidebar" class="">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<nav id="sidebar">
|
|
||||||
<div id="header-wrapper">
|
<div id="header-wrapper">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<a href="https://lettre.github.io/lettre//getting-started/intro/"><img src="https://lettre.github.io/lettre//images/logo50.png" /></a>
|
<a href="http://docs.lettre.at//getting-started/intro/"><img src="http://docs.lettre.at//images/logo50.png" /></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="searchbox">
|
<div class="searchbox">
|
||||||
<label for="search-by"><i class="fa fa-search"></i></label>
|
<label for="search-by"><i class="fa fa-search"></i></label>
|
||||||
<input data-search-input id="search-by" type="text" placeholder="Search">
|
<input data-search-input id="search-by" type="text" placeholder="Search...">
|
||||||
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/lunr.min.js"></script>
|
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/horsey.js"></script>
|
<script type="text/javascript" src="/js/lunr.min.js?1522603726"></script>
|
||||||
|
<script type="text/javascript" src="/js/auto-complete.js?1522603726"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var baseurl = "https:\/\/lettre.github.io\/lettre\/";
|
|
||||||
|
var baseurl = "http:\/\/docs.lettre.at\/";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/search.js"></script>
|
<script type="text/javascript" src="/js/search.js?1522603726"></script>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="highlightable">
|
<div class="highlightable">
|
||||||
<ul class="topics">
|
<ul class="topics">
|
||||||
|
|
||||||
@@ -62,57 +72,44 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/" title="Getting started" class="dd-item
|
||||||
|
parent
|
||||||
|
active
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/getting-started/">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item active parent" data-nav-id="/lettre/getting-started/">
|
|
||||||
<a href="/lettre/getting-started/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>1. </b>
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/intro/">
|
|
||||||
<a href="/lettre/getting-started/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/getting-started/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
@@ -126,86 +123,184 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/" title="Creating messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
<li class="dd-item " data-nav-id="/lettre/creating-messages/">
|
<a href="/creating-messages/">
|
||||||
<a href="/lettre/creating-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>2. </b>
|
|
||||||
|
|
||||||
Creating messages
|
Creating messages
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/">
|
|
||||||
<a href="/lettre/sending-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>3. </b>
|
|
||||||
|
|
||||||
Sending messages
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/intro/">
|
|
||||||
<a href="/lettre/sending-messages/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/email/" title="Email creation" class="dd-item ">
|
||||||
|
<a href="/creating-messages/email/">
|
||||||
|
Email creation
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/smtp/">
|
|
||||||
<a href="/lettre/sending-messages/smtp/">
|
|
||||||
<span>SMTP transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/sendmail/">
|
|
||||||
<a href="/lettre/sending-messages/sendmail/">
|
|
||||||
<span>Sendmail transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/file/">
|
|
||||||
<a href="/lettre/sending-messages/file/">
|
|
||||||
<span>File transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/stub/">
|
|
||||||
<a href="/lettre/sending-messages/stub/">
|
|
||||||
<span>Stub transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/" title="Sending messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/sending-messages/">
|
||||||
|
Sending messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/sending-messages/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/smtp/" title="SMTP transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/smtp/">
|
||||||
|
SMTP transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/sendmail/" title="Sendmail transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/sendmail/">
|
||||||
|
Sendmail transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/file/" title="File transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/file/">
|
||||||
|
File transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/stub/" title="Stub transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/stub/">
|
||||||
|
Stub transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="footer">
|
<section id="footer">
|
||||||
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
||||||
@@ -214,13 +309,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="body">
|
<section id="body">
|
||||||
<div id="overlay"></div>
|
<div id="overlay"></div>
|
||||||
|
<div class="padding highlightable sticky-parent">
|
||||||
|
|
||||||
<div class="padding highlightable">
|
<div class="sticky-spacer">
|
||||||
|
|
||||||
<div id="top-bar">
|
<div id="top-bar">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="top-github-link">
|
||||||
|
<a class="github-link" href="https://github.com/lettre/lettre/edit/master/website/content/getting-started/_index.md" target="blank">
|
||||||
|
<i class="fa fa-code-fork"></i>
|
||||||
|
Edit this page
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
<span id="sidebar-toggle-span">
|
<span id="sidebar-toggle-span">
|
||||||
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
||||||
@@ -228,6 +339,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<span id="toc-menu"><i class="fa fa-list-alt"></i></span>
|
||||||
|
|
||||||
|
<span class="links">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -235,17 +349,43 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a href='/'>Lettre site</a> > Getting started
|
||||||
|
|
||||||
<span itemprop="title"> Getting started</span>
|
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="progress">
|
||||||
|
<div class="wrapper">
|
||||||
|
<nav id="TableOfContents">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#getting-started">Getting started</a></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div id="chapter">
|
|
||||||
|
|
||||||
<div id="body-inner">
|
<div id="body-inner">
|
||||||
|
|
||||||
|
<h1>Getting started</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -254,55 +394,13 @@
|
|||||||
<p>This section explains how to manipulate emails you have created.</p>
|
<p>This section explains how to manipulate emails you have created.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<footer class=" footline" >
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="navigation">
|
<div id="navigation">
|
||||||
|
|
||||||
@@ -314,7 +412,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-next" href="/lettre/getting-started/intro/" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -338,26 +435,194 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-prev" href="/" title="Lettre site"> <i class="fa fa-chevron-left"></i></a>
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-next" href="/getting-started/intro/" title="Introduction" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
||||||
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://lettre.github.io/lettre//js/clipboard.min.js"></script>
|
<script src="/js/clipboard.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.min.js"></script>
|
<script src="/js/perfect-scrollbar.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.jquery.min.js"></script>
|
<script src="/js/perfect-scrollbar.jquery.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery.sticky-kit.min.js"></script>
|
<script src="/js/jquery.sticky-kit.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/featherlight.min.js"></script>
|
<script src="/js/featherlight.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/html5shiv-printshiv.min.js"></script>
|
<script src="/js/html5shiv-printshiv.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/highlight.pack.js"></script>
|
<script src="/js/highlight.pack.js?1522603726"></script>
|
||||||
<script>hljs.initHighlightingOnLoad();</script>
|
<script>hljs.initHighlightingOnLoad();</script>
|
||||||
<script src="https://lettre.github.io/lettre//js/modernizr.custom.71422.js"></script>
|
<script src="/js/modernizr.custom.71422.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/learn.js"></script>
|
<script src="/js/learn.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/hugo-learn.js"></script>
|
<script src="/js/hugo-learn.js?1522603726"></script>
|
||||||
|
|
||||||
|
<link href="/mermaid/mermaid.css?1522603726" type="text/css" rel="stylesheet" />
|
||||||
|
<script src="/mermaid/mermaid.js?1522603726"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({ startOnLoad: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,22 +2,22 @@
|
|||||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
<channel>
|
<channel>
|
||||||
<title>Getting started on Lettre site</title>
|
<title>Getting started on Lettre site</title>
|
||||||
<link>https://lettre.github.io/lettre/getting-started/</link>
|
<link>http://docs.lettre.at/getting-started/</link>
|
||||||
<description>Recent content in Getting started on Lettre site</description>
|
<description>Recent content in Getting started on Lettre site</description>
|
||||||
<generator>Hugo -- gohugo.io</generator>
|
<generator>Hugo -- gohugo.io</generator>
|
||||||
<language>en-us</language>
|
<language>en-us</language>
|
||||||
<lastBuildDate>Sun, 21 May 2017 23:46:01 +0200</lastBuildDate>
|
<lastBuildDate>Sun, 21 May 2017 23:46:01 +0200</lastBuildDate>
|
||||||
|
|
||||||
<atom:link href="https://lettre.github.io/lettre/getting-started/index.xml" rel="self" type="application/rss+xml" />
|
<atom:link href="http://docs.lettre.at/getting-started/index.xml" rel="self" type="application/rss+xml" />
|
||||||
|
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>Introduction</title>
|
<title>Introduction</title>
|
||||||
<link>https://lettre.github.io/lettre/getting-started/intro/</link>
|
<link>http://docs.lettre.at/getting-started/intro/</link>
|
||||||
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
<guid>https://lettre.github.io/lettre/getting-started/intro/</guid>
|
<guid>http://docs.lettre.at/getting-started/intro/</guid>
|
||||||
<description>This documentation is written for lettre 0.7. Please use https://docs.rs/lettre/0.6.2/lettre/ for lettre 0.6.
|
<description>This documentation is written for lettre 0.8. Please use https://docs.rs/lettre/0.7.0/lettre/ for lettre 0.7.
|
||||||
Lettre is an email library that allows creating and sending messages. It provides:
|
Lettre is an email library that allows creating and sending messages. It provides:
|
||||||
An easy to use email builder Pluggable email transports Unicode support (for emails and transports, including for sender et recipient addresses when compatible) Secure defaults (emails are only sent encrypted by default) </description>
|
An easy to use email builder Pluggable email transports Unicode support (for emails and transports, including for sender et recipient addresses when compatible) Secure defaults (emails are only sent encrypted by default) </description>
|
||||||
</item>
|
</item>
|
||||||
|
|||||||
@@ -3,53 +3,64 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
<meta name="generator" content="Hugo 0.20.7" />
|
<meta name="generator" content="Hugo 0.37.1" />
|
||||||
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
||||||
<meta name="author" content="Alexis Mousset">
|
<meta name="author" content="Alexis Mousset">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="https://lettre.github.io/lettre//images/favicon.png" type="image/x-icon" />
|
<link rel="shortcut icon" href="http://docs.lettre.at//images/favicon.png" type="image/x-icon" />
|
||||||
|
|
||||||
|
<title>Introduction :: Lettre site</title>
|
||||||
|
|
||||||
|
|
||||||
<title>Introduction</title>
|
<link href="/css/nucleus.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/nucleus.css" rel="stylesheet">
|
<link href="/css/font-awesome.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/font-awesome.min.css" rel="stylesheet">
|
<link href="/css/hybrid.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hybrid.css" rel="stylesheet">
|
<link href="/css/featherlight.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/featherlight.min.css" rel="stylesheet">
|
<link href="/css/perfect-scrollbar.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/perfect-scrollbar.min.css" rel="stylesheet">
|
<link href="/css/auto-complete.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/horsey.css" rel="stylesheet">
|
<link href="/css/theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/theme.css" rel="stylesheet">
|
<link href="/css/hugo-theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hugo-theme.css" rel="stylesheet">
|
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery-2.x.min.js"></script>
|
|
||||||
<style type="text/css">:root #header + #content > #left > #rlblock_left
|
|
||||||
{display:none !important;}</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/jquery-2.x.min.js?1522603726"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
:root #header + #content > #left > #rlblock_left{
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="" data-url="/lettre/getting-started/intro/">
|
<body class="" data-url="/getting-started/intro/">
|
||||||
|
<nav id="sidebar" class="">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<nav id="sidebar">
|
|
||||||
<div id="header-wrapper">
|
<div id="header-wrapper">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<a href="https://lettre.github.io/lettre//getting-started/intro/"><img src="https://lettre.github.io/lettre//images/logo50.png" /></a>
|
<a href="http://docs.lettre.at//getting-started/intro/"><img src="http://docs.lettre.at//images/logo50.png" /></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="searchbox">
|
<div class="searchbox">
|
||||||
<label for="search-by"><i class="fa fa-search"></i></label>
|
<label for="search-by"><i class="fa fa-search"></i></label>
|
||||||
<input data-search-input id="search-by" type="text" placeholder="Search">
|
<input data-search-input id="search-by" type="text" placeholder="Search...">
|
||||||
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/lunr.min.js"></script>
|
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/horsey.js"></script>
|
<script type="text/javascript" src="/js/lunr.min.js?1522603726"></script>
|
||||||
|
<script type="text/javascript" src="/js/auto-complete.js?1522603726"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var baseurl = "https:\/\/lettre.github.io\/lettre\/";
|
|
||||||
|
var baseurl = "http:\/\/docs.lettre.at\/";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/search.js"></script>
|
<script type="text/javascript" src="/js/search.js?1522603726"></script>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="highlightable">
|
<div class="highlightable">
|
||||||
<ul class="topics">
|
<ul class="topics">
|
||||||
|
|
||||||
@@ -61,57 +72,44 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/" title="Getting started" class="dd-item
|
||||||
|
parent
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/getting-started/">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item parent" data-nav-id="/lettre/getting-started/">
|
|
||||||
<a href="/lettre/getting-started/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>1. </b>
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item active" data-nav-id="/lettre/getting-started/intro/">
|
|
||||||
<a href="/lettre/getting-started/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/intro/" title="Introduction" class="dd-item active">
|
||||||
|
<a href="/getting-started/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
@@ -125,86 +123,184 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/" title="Creating messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
<li class="dd-item " data-nav-id="/lettre/creating-messages/">
|
<a href="/creating-messages/">
|
||||||
<a href="/lettre/creating-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>2. </b>
|
|
||||||
|
|
||||||
Creating messages
|
Creating messages
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/">
|
|
||||||
<a href="/lettre/sending-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>3. </b>
|
|
||||||
|
|
||||||
Sending messages
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/intro/">
|
|
||||||
<a href="/lettre/sending-messages/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/email/" title="Email creation" class="dd-item ">
|
||||||
|
<a href="/creating-messages/email/">
|
||||||
|
Email creation
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/smtp/">
|
|
||||||
<a href="/lettre/sending-messages/smtp/">
|
|
||||||
<span>SMTP transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/sendmail/">
|
|
||||||
<a href="/lettre/sending-messages/sendmail/">
|
|
||||||
<span>Sendmail transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/file/">
|
|
||||||
<a href="/lettre/sending-messages/file/">
|
|
||||||
<span>File transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/stub/">
|
|
||||||
<a href="/lettre/sending-messages/stub/">
|
|
||||||
<span>Stub transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/" title="Sending messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/sending-messages/">
|
||||||
|
Sending messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/sending-messages/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/smtp/" title="SMTP transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/smtp/">
|
||||||
|
SMTP transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/sendmail/" title="Sendmail transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/sendmail/">
|
||||||
|
Sendmail transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/file/" title="File transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/file/">
|
||||||
|
File transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/stub/" title="Stub transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/stub/">
|
||||||
|
Stub transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="footer">
|
<section id="footer">
|
||||||
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
||||||
@@ -213,11 +309,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="body">
|
<section id="body">
|
||||||
<div id="overlay"></div>
|
<div id="overlay"></div>
|
||||||
|
<div class="padding highlightable sticky-parent">
|
||||||
|
|
||||||
<div class="padding highlightable">
|
<div class="sticky-spacer">
|
||||||
|
|
||||||
<div id="top-bar">
|
<div id="top-bar">
|
||||||
|
|
||||||
|
|
||||||
@@ -231,6 +331,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
<span id="sidebar-toggle-span">
|
<span id="sidebar-toggle-span">
|
||||||
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
||||||
@@ -238,7 +339,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span id="toc-menu"><a href=""><i class="fa fa-list-alt"></i></a></span>
|
<span id="toc-menu"><i class="fa fa-list-alt"></i></span>
|
||||||
|
|
||||||
|
<span class="links">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -246,11 +349,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="/lettre/getting-started/" itemprop="url"><span itemprop="title">Getting started</span></a> <i class="fa fa-angle-right"></i>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<span itemprop="title"> Introduction</span>
|
|
||||||
|
<a href='/'>Lettre site</a> > <a href='/getting-started/'>Getting started</a> > Introduction
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="progress">
|
<div class="progress">
|
||||||
@@ -260,16 +370,21 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="body-inner">
|
<div id="body-inner">
|
||||||
|
|
||||||
<h1>Introduction</h1>
|
<h1>Introduction</h1>
|
||||||
|
|
||||||
|
|
||||||
<div class="notices note" ><p>This documentation is written for lettre 0.7.
|
|
||||||
Please use <a href="https://docs.rs/lettre/0.6.2/lettre/">https://docs.rs/lettre/0.6.2/lettre/</a> for lettre 0.6.</p>
|
|
||||||
|
|
||||||
|
<div class="notices note" ><p>This documentation is written for lettre 0.8.
|
||||||
|
Please use <a href="https://docs.rs/lettre/0.7.0/lettre/">https://docs.rs/lettre/0.7.0/lettre/</a> for lettre 0.7.</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
@@ -283,54 +398,15 @@ Please use <a href="https://docs.rs/lettre/0.6.2/lettre/">https://docs.rs/lettre
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<footer class=" footline" >
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="navigation">
|
<div id="navigation">
|
||||||
|
|
||||||
|
|
||||||
@@ -340,12 +416,6 @@ Please use <a href="https://docs.rs/lettre/0.6.2/lettre/">https://docs.rs/lettre
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-prev" href="/lettre/getting-started/"> <i class="fa fa-chevron-left"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-next" href="/lettre/creating-messages/" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -367,23 +437,197 @@ Please use <a href="https://docs.rs/lettre/0.6.2/lettre/">https://docs.rs/lettre
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-prev" href="/getting-started/" title="Getting started"> <i class="fa fa-chevron-left"></i></a>
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-next" href="/creating-messages/" title="Creating messages" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
||||||
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://lettre.github.io/lettre//js/clipboard.min.js"></script>
|
<script src="/js/clipboard.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.min.js"></script>
|
<script src="/js/perfect-scrollbar.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.jquery.min.js"></script>
|
<script src="/js/perfect-scrollbar.jquery.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery.sticky-kit.min.js"></script>
|
<script src="/js/jquery.sticky-kit.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/featherlight.min.js"></script>
|
<script src="/js/featherlight.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/html5shiv-printshiv.min.js"></script>
|
<script src="/js/html5shiv-printshiv.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/highlight.pack.js"></script>
|
<script src="/js/highlight.pack.js?1522603726"></script>
|
||||||
<script>hljs.initHighlightingOnLoad();</script>
|
<script>hljs.initHighlightingOnLoad();</script>
|
||||||
<script src="https://lettre.github.io/lettre//js/modernizr.custom.71422.js"></script>
|
<script src="/js/modernizr.custom.71422.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/learn.js"></script>
|
<script src="/js/learn.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/hugo-learn.js"></script>
|
<script src="/js/hugo-learn.js?1522603726"></script>
|
||||||
|
|
||||||
|
<link href="/mermaid/mermaid.css?1522603726" type="text/css" rel="stylesheet" />
|
||||||
|
<script src="/mermaid/mermaid.js?1522603726"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({ startOnLoad: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
<meta http-equiv="refresh" content="0; url=https://lettre.github.io/lettre//getting-started/intro/"/>
|
<meta http-equiv="refresh" content="0; url=http://docs.lettre.at//getting-started/intro/"/>
|
||||||
|
|||||||
62
docs/index.json
Normal file
62
docs/index.json
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"uri": "/content/creating-messages/_index",
|
||||||
|
"title": "Creating messages",
|
||||||
|
"content": "\nCreating messages\n\nThis section explains how to create emails.",
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "/content/creating-messages/email",
|
||||||
|
"title": "Email creation",
|
||||||
|
"content": "\nSimple example\n\nThe email part builds email messages. For now, it does not support attachments.\nAn email is built using an EmailBuilder. The simplest email could be:\n\nextern crate lettre_email;\n\nuse lettre_email::EmailBuilder;\n\nfn main() {\n // Create an email\n let email = EmailBuilder::new()\n // Addresses can be specified by the tuple (email, alias)\n .to((\"user@example.org\", \"Firstname Lastname\"))\n // ... or by an address only\n .from(\"user@example.com\")\n .subject(\"Hi, Hello world\")\n .text(\"Hello world.\")\n .build();\n \n assert!(email.is_ok());\n}\n\nWhen the build method is called, the EmailBuilder will add the missing headers (like\nMessage-ID or Date) and check for missing necessary ones (like From or To). It will\nthen generate an Email that can be sent.\n\nThe text() method will create a plain text email, while the html() method will create an\nHTML email. You can use the alternative() method to provide both versions, using plain text\nas fallback for the HTML version.\n\n Complete example\n\nBelow is a more complete example, not using method chaining:\n\nextern crate lettre_email;\n\nuse lettre_email::EmailBuilder;\n\nfn main() {\n let mut builder = EmailBuilder::new();\n builder.add_to((\"user@example.org\", \"Alias name\"));\n builder.add_cc((\"user@example.net\", \"Alias name\"));\n builder.add_from(\"no-reply@example.com\");\n builder.add_from(\"no-reply@example.eu\");\n builder.set_sender(\"no-reply@example.com\");\n builder.set_subject(\"Hello world\");\n builder.set_alternative(\"h2Hi, Hello world./h2\", \"Hi, Hello world.\");\n builder.addreplyto(\"contact@example.com\");\n builder.add_header((\"X-Custom-Header\", \"my header\"));\n \n let email = builder.build();\n assert!(email.is_ok());\n}\n\nSee the EmailBuilder documentation for a complete list of methods.\n\n",
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "/content/getting-started/_index",
|
||||||
|
"title": "Getting started",
|
||||||
|
"content": "\nGetting started\n\nThis section explains how to manipulate emails you have created.",
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "/content/getting-started/intro",
|
||||||
|
"title": "Introduction",
|
||||||
|
"content": "\n{{% notice note %}}\nThis documentation is written for lettre 0.8.\nPlease use https://docs.rs/lettre/0.7.0/lettre/ for lettre 0.7.\n{{% /notice%}}\n\nLettre is an email library that allows creating and sending messages. It provides:\n\nAn easy to use email builder\nPluggable email transports\nUnicode support (for emails and transports, including for sender et recipient addresses when compatible)\nSecure defaults (emails are only sent encrypted by default)\n",
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "/content/sending-messages/_index",
|
||||||
|
"title": "Sending messages",
|
||||||
|
"content": "\nSending Messages\n\nThis section explains how to manipulate emails you have created.",
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "/content/sending-messages/file",
|
||||||
|
"title": "File transport",
|
||||||
|
"content": "\nThe file transport writes the emails to the given directory. The name of the file will be\nmessage_id.txt.\nIt can be useful for testing purposes, or if you want to keep track of sent messages.\n\nextern crate lettre;\n\nuse std::env::temp_dir;\n\nuse lettre::file::FileEmailTransport;\nuse lettre::{SimpleSendableEmail, EmailTransport};\n\nfn main() {\n // Write to the local temp directory\n let mut sender = FileEmailTransport::new(temp_dir());\n let email = SimpleSendableEmail::new(\n \"user@localhost\".to_string(),\n &[\"root@localhost\".to_string()],\n \"messageid\".tostring(),\n \"Hello world\".to_string(),\n ).unwrap();\n \n let result = sender.send(&email);\n assert!(result.is_ok());\n}\n\nExample result in /tmp/b7c211bc-9811-45ce-8cd9-68eab575d695.txt:\n\nb7c211bc-9811-45ce-8cd9-68eab575d695: from=user@localhost to=root@localhost\nTo: root@localhost\nFrom: user@localhost\nSubject: Hello\nDate: Sat, 31 Oct 2015 13:42:19 +0100\nMessage-ID: b7c211bc-9811-45ce-8cd9-68eab575d695.lettre@localhost\n\nHello World!\n",
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "/content/sending-messages/intro",
|
||||||
|
"title": "Introduction",
|
||||||
|
"content": "\nThis mailer contains several different transports for your emails. To be sendable, the\nemails have to implement SendableEmail, which is the case for emails created with lettre_email.\n\nThe following transports are available:\n\nThe SmtpTransport uses the SMTP protocol to send the message over the network. It is\n the preferred way of sending emails.\nThe SendmailTransport uses the sendmail command to send messages. It is an alternative to\n the SMTP transport.\nThe FileTransport creates a file containing the email content to be sent. It can be used\n for debugging or if you want to keep all sent emails.\nThe StubTransport is useful for debugging, and only prints the content of the email in the\n logs.\n",
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "/content/sending-messages/sendmail",
|
||||||
|
"title": "Sendmail transport",
|
||||||
|
"content": "\nThe sendmail transport sends the email using the local sendmail command.\n\nextern crate lettre;\n\nuse lettre::sendmail::SendmailTransport;\nuse lettre::{SimpleSendableEmail, EmailTransport};\n\nfn main() {\n let email = SimpleSendableEmail::new(\n \"user@localhost\".to_string(),\n &[\"root@localhost\".to_string()],\n \"messageid\".tostring(),\n \"Hello world\".to_string(),\n ).unwrap();\n \n let mut sender = SendmailTransport::new();\n let result = sender.send(&email);\n assert!(result.is_ok());\n}\n",
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "/content/sending-messages/smtp",
|
||||||
|
"title": "SMTP transport",
|
||||||
|
"content": "\nThis transport uses the SMTP protocol to send emails over the network (locally or remotely).\n\nIt is designed to be:\n\nSecured: email are encrypted by default\nModern: Unicode support for email content and sender/recipient addresses when compatible\nFast: supports tcp connection reuse\n\nThis client is designed to send emails to a relay server, and should not be used to send\nemails directly to the destination.\n\nThe relay server can be the local email server, a specific host or a third-party service.\n\nSimple example\n\nThis is the most basic example of usage:\n\nextern crate lettre;\n\nuse lettre::{SimpleSendableEmail, EmailTransport, SmtpTransport};\n\nfn main() {\n let email = SimpleSendableEmail::new(\n \"user@localhost\".to_string(),\n &[\"root@localhost\".to_string()],\n \"messageid\".tostring(),\n \"Hello world\".to_string(),\n ).unwrap();\n \n // Open a local connection on port 25\n let mut mailer =\n SmtpTransport::builderunencryptedlocalhost().unwrap().build();\n // Send the email\n let result = mailer.send(&email);\n \n assert!(result.is_ok());\n}\n\n Complete example\n\nextern crate lettre;\n\nuse lettre::smtp::authentication::{Credentials, Mechanism};\nuse lettre::{SimpleSendableEmail, EmailTransport, SmtpTransport};\nuse lettre::smtp::extension::ClientId;\nuse lettre::smtp::ConnectionReuseParameters;\n\nfn main() {\n let email = SimpleSendableEmail::new(\n \"user@localhost\".to_string(),\n &[\"root@localhost\".to_string()],\n \"messageid\".tostring(),\n \"Hello world\".to_string(),\n ).unwrap();\n \n // Connect to a remote server on a custom port\n let mut mailer = SmtpTransport::simple_builder(\"server.tld\").unwrap()\n // Set the name sent during EHLO/HELO, default is localhost\n .helloname(ClientId::Domain(\"my.hostname.tld\".tostring()))\n // Add credentials for authentication\n .credentials(Credentials::new(\"username\".tostring(), \"password\".tostring()))\n // Enable SMTPUTF8 if the server supports it\n .smtp_utf8(true)\n // Configure expected authentication mechanism\n .authentication_mechanism(Mechanism::Plain)\n // Enable connection reuse\n .connection_reuse(ConnectionReuseParameters::ReuseUnlimited).build();\n \n let result_1 = mailer.send(&email);\n assert!(result1.isok());\n \n // The second email will use the same connection\n let result_2 = mailer.send(&email);\n assert!(result2.isok());\n \n // Explicitly close the SMTP transaction as we enabled connection reuse\n mailer.close();\n}\n\nLower level\n\nYou can also send commands, here is a simple email transaction without\nerror handling:\n\nextern crate lettre;\n\nuse lettre::EmailAddress;\nuse lettre::smtp::SMTP_PORT;\nuse lettre::smtp::client::Client;\nuse lettre::smtp::client::net::NetworkStream;\nuse lettre::smtp::extension::ClientId;\nuse lettre::smtp::commands::*;\n\nfn main() {\n let mut email_client: ClientNetworkStream = Client::new();\n let _ = emailclient.connect(&(\"localhost\", SMTPPORT), None);\n let _ = emailclient.command(EhloCommand::new(ClientId::new(\"myhostname\".to_string())));\n let _ = email_client.command(\n MailCommand::new(Some(EmailAddress::new(\"user@example.com\".to_string()).unwrap()), vec![])\n );\n let _ = email_client.command(\n RcptCommand::new(EmailAddress::new(\"user@example.org\".to_string()).unwrap(), vec![])\n );\n let _ = email_client.command(DataCommand);\n let _ = emailclient.message(Box::new(\"Test email\".asbytes()));\n let _ = email_client.command(QuitCommand);\n}\n\n",
|
||||||
|
"tags": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "/content/sending-messages/stub",
|
||||||
|
"title": "Stub transport",
|
||||||
|
"content": "\nThe stub transport only logs message envelope and drops the content. It can be useful for\ntesting purposes.\n\nextern crate lettre;\n\nuse lettre::stub::StubEmailTransport;\nuse lettre::{SimpleSendableEmail, EmailTransport};\n\nfn main() {\n let email = SimpleSendableEmail::new(\n \"user@localhost\".to_string(),\n &[\"root@localhost\".to_string()],\n \"messageid\".tostring(),\n \"Hello world\".to_string(),\n ).unwrap();\n \n let mut sender = StubEmailTransport::new_positive();\n let result = sender.send(&email);\n assert!(result.is_ok());\n}\n\nWill log (when using a logger like env_logger):\n\nb7c211bc-9811-45ce-8cd9-68eab575d695: from=user@localhost to=root@localhost\n",
|
||||||
|
"tags": []
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -2,78 +2,88 @@
|
|||||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
<channel>
|
<channel>
|
||||||
<title>Lettre site</title>
|
<title>Lettre site</title>
|
||||||
<link>https://lettre.github.io/lettre/</link>
|
<link>http://docs.lettre.at/</link>
|
||||||
<description>Recent content on Lettre site</description>
|
<description>Recent content on Lettre site</description>
|
||||||
<generator>Hugo -- gohugo.io</generator>
|
<generator>Hugo -- gohugo.io</generator>
|
||||||
<language>en-us</language>
|
<language>en-us</language>
|
||||||
<lastBuildDate>Sun, 21 May 2017 23:46:17 +0200</lastBuildDate>
|
<lastBuildDate>Sun, 21 May 2017 23:46:17 +0200</lastBuildDate>
|
||||||
|
|
||||||
<atom:link href="https://lettre.github.io/lettre/index.xml" rel="self" type="application/rss+xml" />
|
<atom:link href="http://docs.lettre.at/index.xml" rel="self" type="application/rss+xml" />
|
||||||
|
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>Introduction</title>
|
<title>Introduction</title>
|
||||||
<link>https://lettre.github.io/lettre/getting-started/intro/</link>
|
<link>http://docs.lettre.at/getting-started/intro/</link>
|
||||||
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
<guid>https://lettre.github.io/lettre/getting-started/intro/</guid>
|
<guid>http://docs.lettre.at/getting-started/intro/</guid>
|
||||||
<description>This documentation is written for lettre 0.7. Please use https://docs.rs/lettre/0.6.2/lettre/ for lettre 0.6.
|
<description>This documentation is written for lettre 0.8. Please use https://docs.rs/lettre/0.7.0/lettre/ for lettre 0.7.
|
||||||
Lettre is an email library that allows creating and sending messages. It provides:
|
Lettre is an email library that allows creating and sending messages. It provides:
|
||||||
An easy to use email builder Pluggable email transports Unicode support (for emails and transports, including for sender et recipient addresses when compatible) Secure defaults (emails are only sent encrypted by default) </description>
|
An easy to use email builder Pluggable email transports Unicode support (for emails and transports, including for sender et recipient addresses when compatible) Secure defaults (emails are only sent encrypted by default) </description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>Introduction</title>
|
<title>Introduction</title>
|
||||||
<link>https://lettre.github.io/lettre/sending-messages/intro/</link>
|
<link>http://docs.lettre.at/sending-messages/intro/</link>
|
||||||
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
<guid>https://lettre.github.io/lettre/sending-messages/intro/</guid>
|
<guid>http://docs.lettre.at/sending-messages/intro/</guid>
|
||||||
<description>This mailer contains several different transports for your emails. To be sendable, the emails have to implement SendableEmail, which is the case for emails created with lettre_email.
|
<description>This mailer contains several different transports for your emails. To be sendable, the emails have to implement SendableEmail, which is the case for emails created with lettre_email.
|
||||||
The following transports are available:
|
The following transports are available:
|
||||||
The SmtpTransport uses the SMTP protocol to send the message over the network. It is the prefered way of sending emails. The SendmailTransport uses the sendmail command to send messages. It is an alternative to the SMTP transport.</description>
|
The SmtpTransport uses the SMTP protocol to send the message over the network. It is the preferred way of sending emails. The SendmailTransport uses the sendmail command to send messages. It is an alternative to the SMTP transport.</description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>SMTP transport</title>
|
<title>SMTP transport</title>
|
||||||
<link>https://lettre.github.io/lettre/sending-messages/smtp/</link>
|
<link>http://docs.lettre.at/sending-messages/smtp/</link>
|
||||||
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
<guid>https://lettre.github.io/lettre/sending-messages/smtp/</guid>
|
<guid>http://docs.lettre.at/sending-messages/smtp/</guid>
|
||||||
<description>This transport uses the SMTP protocol to send emails over the network (locally or remotely).
|
<description>This transport uses the SMTP protocol to send emails over the network (locally or remotely).
|
||||||
It is desinged to be:
|
It is designed to be:
|
||||||
Secured: email are encrypted by default Modern: Unicode support for email content and sender/recipient adresses when compatible Fast: supports tcp connection reuse This client is designed to send emails to a relay server, and should not be used to send emails directly to the destination.
|
Secured: email are encrypted by default Modern: Unicode support for email content and sender/recipient addresses when compatible Fast: supports tcp connection reuse This client is designed to send emails to a relay server, and should not be used to send emails directly to the destination.
|
||||||
The relay server can be the local email server, a specific host or a third-party service.</description>
|
The relay server can be the local email server, a specific host or a third-party service.</description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>Sendmail transport</title>
|
<title>Sendmail transport</title>
|
||||||
<link>https://lettre.github.io/lettre/sending-messages/sendmail/</link>
|
<link>http://docs.lettre.at/sending-messages/sendmail/</link>
|
||||||
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
<guid>https://lettre.github.io/lettre/sending-messages/sendmail/</guid>
|
<guid>http://docs.lettre.at/sending-messages/sendmail/</guid>
|
||||||
<description>The sendmail transport sends the email using the local sendmail command.
|
<description>The sendmail transport sends the email using the local sendmail command.
|
||||||
use lettre::sendmail::SendmailTransport; use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress}; let email = SimpleSendableEmail::new( EmailAddress::new("user@localhost".to_string()), vec![EmailAddress::new("root@localhost".to_string())], "message_id".to_string(), "Hello world".to_string(), ); let mut sender = SendmailTransport::new(); let result = sender.send(&email); assert!(result.is_ok()); </description>
|
extern crate lettre; use lettre::sendmail::SendmailTransport; use lettre::{SimpleSendableEmail, EmailTransport}; fn main() { let email = SimpleSendableEmail::new( &#34;user@localhost&#34;.to_string(), &amp;[&#34;root@localhost&#34;.to_string()], &#34;message_id&#34;.to_string(), &#34;Hello world&#34;.to_string(), ).unwrap(); let mut sender = SendmailTransport::new(); let result = sender.send(&amp;email); assert!(result.is_ok()); }</description>
|
||||||
|
</item>
|
||||||
|
|
||||||
|
<item>
|
||||||
|
<title>Email creation</title>
|
||||||
|
<link>http://docs.lettre.at/creating-messages/email/</link>
|
||||||
|
<pubDate>Sun, 21 Jan 2018 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
|
<guid>http://docs.lettre.at/creating-messages/email/</guid>
|
||||||
|
<description>Simple example 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:
|
||||||
|
extern crate lettre_email; use lettre_email::EmailBuilder; fn main() { // Create an email let email = EmailBuilder::new() // Addresses can be specified by the tuple (email, alias) .to((&#34;user@example.org&#34;, &#34;Firstname Lastname&#34;)) // ... or by an address only .from(&#34;user@example.com&#34;) .subject(&#34;Hi, Hello world&#34;) .</description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>File transport</title>
|
<title>File transport</title>
|
||||||
<link>https://lettre.github.io/lettre/sending-messages/file/</link>
|
<link>http://docs.lettre.at/sending-messages/file/</link>
|
||||||
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
<guid>https://lettre.github.io/lettre/sending-messages/file/</guid>
|
<guid>http://docs.lettre.at/sending-messages/file/</guid>
|
||||||
<description>The file transport writes the emails to the given directory. The name of the file will be message_id.txt. It can be useful for testing purposes, or if you want to keep track of sent messages.
|
<description>The file transport writes the emails to the given directory. The name of the file will be message_id.txt. It can be useful for testing purposes, or if you want to keep track of sent messages.
|
||||||
use std::env::temp_dir; use lettre::file::FileEmailTransport; use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress}; // Write to the local temp directory let mut sender = FileEmailTransport::new(temp_dir()); let email = SimpleSendableEmail::new( EmailAddress::new("user@localhost".to_string()), vec![EmailAddress::new("root@localhost".to_string())], "message_id".to_string(), "Hello world".to_string(), ); let result = sender.send(&email); assert!(result.is_ok()); Example result in /tmp/b7c211bc-9811-45ce-8cd9-68eab575d695.</description>
|
extern crate lettre; use std::env::temp_dir; use lettre::file::FileEmailTransport; use lettre::{SimpleSendableEmail, EmailTransport}; fn main() { // Write to the local temp directory let mut sender = FileEmailTransport::new(temp_dir()); let email = SimpleSendableEmail::new( &#34;user@localhost&#34;.to_string(), &amp;[&#34;root@localhost&#34;.to_string()], &#34;message_id&#34;.to_string(), &#34;Hello world&#34;.to_string(), ).</description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>Stub transport</title>
|
<title>Stub transport</title>
|
||||||
<link>https://lettre.github.io/lettre/sending-messages/stub/</link>
|
<link>http://docs.lettre.at/sending-messages/stub/</link>
|
||||||
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
<guid>https://lettre.github.io/lettre/sending-messages/stub/</guid>
|
<guid>http://docs.lettre.at/sending-messages/stub/</guid>
|
||||||
<description>The stub transport only logs message envelope and drops the content. It can be useful for testing purposes.
|
<description>The stub transport only logs message envelope and drops the content. It can be useful for testing purposes.
|
||||||
use lettre::stub::StubEmailTransport; use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress}; let email = SimpleSendableEmail::new( EmailAddress::new("user@localhost".to_string()), vec![EmailAddress::new("root@localhost".to_string())], "message_id".to_string(), "Hello world".to_string(), ); let mut sender = StubEmailTransport::new_positive(); let result = sender.send(&email); assert!(result.is_ok()); Will log (when using a logger like env_logger):
|
extern crate lettre; use lettre::stub::StubEmailTransport; use lettre::{SimpleSendableEmail, EmailTransport}; fn main() { let email = SimpleSendableEmail::new( &#34;user@localhost&#34;.to_string(), &amp;[&#34;root@localhost&#34;.to_string()], &#34;message_id&#34;.to_string(), &#34;Hello world&#34;.to_string(), ).unwrap(); let mut sender = StubEmailTransport::new_positive(); let result = sender.send(&amp;email); assert!(result.is_ok()); } Will log (when using a logger like env_logger):
|
||||||
b7c211bc-9811-45ce-8cd9-68eab575d695: from= to= </description>
|
b7c211bc-9811-45ce-8cd9-68eab575d695: from=&lt;user@localhost&gt; to=&lt;root@localhost&gt;</description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
</channel>
|
</channel>
|
||||||
|
|||||||
223
docs/js/auto-complete.js
Normal file
223
docs/js/auto-complete.js
Normal file
@@ -0,0 +1,223 @@
|
|||||||
|
/*
|
||||||
|
JavaScript autoComplete v1.0.4
|
||||||
|
Copyright (c) 2014 Simon Steinberger / Pixabay
|
||||||
|
GitHub: https://github.com/Pixabay/JavaScript-autoComplete
|
||||||
|
License: http://www.opensource.org/licenses/mit-license.php
|
||||||
|
*/
|
||||||
|
|
||||||
|
var autoComplete = (function(){
|
||||||
|
// "use strict";
|
||||||
|
function autoComplete(options){
|
||||||
|
if (!document.querySelector) return;
|
||||||
|
|
||||||
|
// helpers
|
||||||
|
function hasClass(el, className){ return el.classList ? el.classList.contains(className) : new RegExp('\\b'+ className+'\\b').test(el.className); }
|
||||||
|
|
||||||
|
function addEvent(el, type, handler){
|
||||||
|
if (el.attachEvent) el.attachEvent('on'+type, handler); else el.addEventListener(type, handler);
|
||||||
|
}
|
||||||
|
function removeEvent(el, type, handler){
|
||||||
|
// if (el.removeEventListener) not working in IE11
|
||||||
|
if (el.detachEvent) el.detachEvent('on'+type, handler); else el.removeEventListener(type, handler);
|
||||||
|
}
|
||||||
|
function live(elClass, event, cb, context){
|
||||||
|
addEvent(context || document, event, function(e){
|
||||||
|
var found, el = e.target || e.srcElement;
|
||||||
|
while (el && !(found = hasClass(el, elClass))) el = el.parentElement;
|
||||||
|
if (found) cb.call(el, e);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
var o = {
|
||||||
|
selector: 0,
|
||||||
|
source: 0,
|
||||||
|
minChars: 3,
|
||||||
|
delay: 150,
|
||||||
|
offsetLeft: 0,
|
||||||
|
offsetTop: 1,
|
||||||
|
cache: 1,
|
||||||
|
menuClass: '',
|
||||||
|
renderItem: function (item, search){
|
||||||
|
// escape special characters
|
||||||
|
search = search.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
|
||||||
|
var re = new RegExp("(" + search.split(' ').join('|') + ")", "gi");
|
||||||
|
return '<div class="autocomplete-suggestion" data-val="' + item + '">' + item.replace(re, "<b>$1</b>") + '</div>';
|
||||||
|
},
|
||||||
|
onSelect: function(e, term, item){}
|
||||||
|
};
|
||||||
|
for (var k in options) { if (options.hasOwnProperty(k)) o[k] = options[k]; }
|
||||||
|
|
||||||
|
// init
|
||||||
|
var elems = typeof o.selector == 'object' ? [o.selector] : document.querySelectorAll(o.selector);
|
||||||
|
for (var i=0; i<elems.length; i++) {
|
||||||
|
var that = elems[i];
|
||||||
|
|
||||||
|
// create suggestions container "sc"
|
||||||
|
that.sc = document.createElement('div');
|
||||||
|
that.sc.className = 'autocomplete-suggestions '+o.menuClass;
|
||||||
|
|
||||||
|
that.autocompleteAttr = that.getAttribute('autocomplete');
|
||||||
|
that.setAttribute('autocomplete', 'off');
|
||||||
|
that.cache = {};
|
||||||
|
that.last_val = '';
|
||||||
|
|
||||||
|
that.updateSC = function(resize, next){
|
||||||
|
var rect = that.getBoundingClientRect();
|
||||||
|
that.sc.style.left = Math.round(rect.left + (window.pageXOffset || document.documentElement.scrollLeft) + o.offsetLeft) + 'px';
|
||||||
|
that.sc.style.top = Math.round(rect.bottom + (window.pageYOffset || document.documentElement.scrollTop) + o.offsetTop) + 'px';
|
||||||
|
that.sc.style.width = Math.round(rect.right - rect.left) + 'px'; // outerWidth
|
||||||
|
if (!resize) {
|
||||||
|
that.sc.style.display = 'block';
|
||||||
|
if (!that.sc.maxHeight) { that.sc.maxHeight = parseInt((window.getComputedStyle ? getComputedStyle(that.sc, null) : that.sc.currentStyle).maxHeight); }
|
||||||
|
if (!that.sc.suggestionHeight) that.sc.suggestionHeight = that.sc.querySelector('.autocomplete-suggestion').offsetHeight;
|
||||||
|
if (that.sc.suggestionHeight)
|
||||||
|
if (!next) that.sc.scrollTop = 0;
|
||||||
|
else {
|
||||||
|
var scrTop = that.sc.scrollTop, selTop = next.getBoundingClientRect().top - that.sc.getBoundingClientRect().top;
|
||||||
|
if (selTop + that.sc.suggestionHeight - that.sc.maxHeight > 0)
|
||||||
|
that.sc.scrollTop = selTop + that.sc.suggestionHeight + scrTop - that.sc.maxHeight;
|
||||||
|
else if (selTop < 0)
|
||||||
|
that.sc.scrollTop = selTop + scrTop;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
addEvent(window, 'resize', that.updateSC);
|
||||||
|
document.body.appendChild(that.sc);
|
||||||
|
|
||||||
|
live('autocomplete-suggestion', 'mouseleave', function(e){
|
||||||
|
var sel = that.sc.querySelector('.autocomplete-suggestion.selected');
|
||||||
|
if (sel) setTimeout(function(){ sel.className = sel.className.replace('selected', ''); }, 20);
|
||||||
|
}, that.sc);
|
||||||
|
|
||||||
|
live('autocomplete-suggestion', 'mouseover', function(e){
|
||||||
|
var sel = that.sc.querySelector('.autocomplete-suggestion.selected');
|
||||||
|
if (sel) sel.className = sel.className.replace('selected', '');
|
||||||
|
this.className += ' selected';
|
||||||
|
}, that.sc);
|
||||||
|
|
||||||
|
live('autocomplete-suggestion', 'mousedown', function(e){
|
||||||
|
if (hasClass(this, 'autocomplete-suggestion')) { // else outside click
|
||||||
|
var v = this.getAttribute('data-val');
|
||||||
|
that.value = v;
|
||||||
|
o.onSelect(e, v, this);
|
||||||
|
that.sc.style.display = 'none';
|
||||||
|
}
|
||||||
|
}, that.sc);
|
||||||
|
|
||||||
|
that.blurHandler = function(){
|
||||||
|
try { var over_sb = document.querySelector('.autocomplete-suggestions:hover'); } catch(e){ var over_sb = 0; }
|
||||||
|
if (!over_sb) {
|
||||||
|
that.last_val = that.value;
|
||||||
|
that.sc.style.display = 'none';
|
||||||
|
setTimeout(function(){ that.sc.style.display = 'none'; }, 350); // hide suggestions on fast input
|
||||||
|
} else if (that !== document.activeElement) setTimeout(function(){ that.focus(); }, 20);
|
||||||
|
};
|
||||||
|
addEvent(that, 'blur', that.blurHandler);
|
||||||
|
|
||||||
|
var suggest = function(data){
|
||||||
|
var val = that.value;
|
||||||
|
that.cache[val] = data;
|
||||||
|
if (data.length && val.length >= o.minChars) {
|
||||||
|
var s = '';
|
||||||
|
for (var i=0;i<data.length;i++) s += o.renderItem(data[i], val);
|
||||||
|
that.sc.innerHTML = s;
|
||||||
|
that.updateSC(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
that.sc.style.display = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
that.keydownHandler = function(e){
|
||||||
|
var key = window.event ? e.keyCode : e.which;
|
||||||
|
// down (40), up (38)
|
||||||
|
if ((key == 40 || key == 38) && that.sc.innerHTML) {
|
||||||
|
var next, sel = that.sc.querySelector('.autocomplete-suggestion.selected');
|
||||||
|
if (!sel) {
|
||||||
|
next = (key == 40) ? that.sc.querySelector('.autocomplete-suggestion') : that.sc.childNodes[that.sc.childNodes.length - 1]; // first : last
|
||||||
|
next.className += ' selected';
|
||||||
|
console.log(next);
|
||||||
|
that.value = next.getAttribute('data-val');
|
||||||
|
} else {
|
||||||
|
next = (key == 40) ? sel.nextSibling : sel.previousSibling;
|
||||||
|
if (next) {
|
||||||
|
sel.className = sel.className.replace('selected', '');
|
||||||
|
next.className += ' selected';
|
||||||
|
that.value = next.getAttribute('data-val');
|
||||||
|
}
|
||||||
|
else { sel.className = sel.className.replace('selected', ''); that.value = that.last_val; next = 0; }
|
||||||
|
}
|
||||||
|
that.updateSC(0, next);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// esc
|
||||||
|
else if (key == 27) { that.value = that.last_val; that.sc.style.display = 'none'; }
|
||||||
|
// enter
|
||||||
|
else if (key == 13 || key == 9) {
|
||||||
|
var sel = that.sc.querySelector('.autocomplete-suggestion.selected');
|
||||||
|
if (sel && that.sc.style.display != 'none') { o.onSelect(e, sel.getAttribute('data-val'), sel); setTimeout(function(){ that.sc.style.display = 'none'; }, 20); }
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addEvent(that, 'keydown', that.keydownHandler);
|
||||||
|
|
||||||
|
that.keyupHandler = function(e){
|
||||||
|
var key = window.event ? e.keyCode : e.which;
|
||||||
|
if (!key || (key < 35 || key > 40) && key != 13 && key != 27) {
|
||||||
|
var val = that.value;
|
||||||
|
if (val.length >= o.minChars) {
|
||||||
|
if (val != that.last_val) {
|
||||||
|
that.last_val = val;
|
||||||
|
clearTimeout(that.timer);
|
||||||
|
if (o.cache) {
|
||||||
|
if (val in that.cache) { suggest(that.cache[val]); return; }
|
||||||
|
// no requests if previous suggestions were empty
|
||||||
|
for (var i=1; i<val.length-o.minChars; i++) {
|
||||||
|
var part = val.slice(0, val.length-i);
|
||||||
|
if (part in that.cache && !that.cache[part].length) { suggest([]); return; }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
that.timer = setTimeout(function(){ o.source(val, suggest) }, o.delay);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
that.last_val = val;
|
||||||
|
that.sc.style.display = 'none';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
addEvent(that, 'keyup', that.keyupHandler);
|
||||||
|
|
||||||
|
that.focusHandler = function(e){
|
||||||
|
that.last_val = '\n';
|
||||||
|
that.keyupHandler(e)
|
||||||
|
};
|
||||||
|
if (!o.minChars) addEvent(that, 'focus', that.focusHandler);
|
||||||
|
}
|
||||||
|
|
||||||
|
// public destroy method
|
||||||
|
this.destroy = function(){
|
||||||
|
for (var i=0; i<elems.length; i++) {
|
||||||
|
var that = elems[i];
|
||||||
|
removeEvent(window, 'resize', that.updateSC);
|
||||||
|
removeEvent(that, 'blur', that.blurHandler);
|
||||||
|
removeEvent(that, 'focus', that.focusHandler);
|
||||||
|
removeEvent(that, 'keydown', that.keydownHandler);
|
||||||
|
removeEvent(that, 'keyup', that.keyupHandler);
|
||||||
|
if (that.autocompleteAttr)
|
||||||
|
that.setAttribute('autocomplete', that.autocompleteAttr);
|
||||||
|
else
|
||||||
|
that.removeAttribute('autocomplete');
|
||||||
|
document.body.removeChild(that.sc);
|
||||||
|
that = null;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
return autoComplete;
|
||||||
|
})();
|
||||||
|
|
||||||
|
(function(){
|
||||||
|
if (typeof define === 'function' && define.amd)
|
||||||
|
define('autoComplete', function () { return autoComplete; });
|
||||||
|
else if (typeof module !== 'undefined' && module.exports)
|
||||||
|
module.exports = autoComplete;
|
||||||
|
else
|
||||||
|
window.autoComplete = autoComplete;
|
||||||
|
})();
|
||||||
@@ -17,7 +17,7 @@ var getUrlParameter = function getUrlParameter(sPageURL) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Execute actions on images generated from Markdown pages
|
// Execute actions on images generated from Markdown pages
|
||||||
var images = $("div#body-inner img");
|
var images = $("div#body-inner img").not(".inline");
|
||||||
// Wrap image inside a featherlight (to get a full size view in a popup)
|
// Wrap image inside a featherlight (to get a full size view in a popup)
|
||||||
images.wrap(function(){
|
images.wrap(function(){
|
||||||
var image =$(this);
|
var image =$(this);
|
||||||
@@ -56,7 +56,10 @@ images.each(function(index){
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Stick the top to the top of the screen when scrolling
|
// Stick the top to the top of the screen when scrolling
|
||||||
$("#top-bar").stick_in_parent({spacer: false});
|
$("#top-bar").stick_in_parent( {
|
||||||
|
parent: ".sticky-parent",
|
||||||
|
spacer: ".sticky-spacer",
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
jQuery(document).ready(function() {
|
jQuery(document).ready(function() {
|
||||||
|
|||||||
123
docs/js/learn.js
123
docs/js/learn.js
@@ -83,9 +83,14 @@ $(window).resize(function() {
|
|||||||
|
|
||||||
|
|
||||||
jQuery(document).ready(function() {
|
jQuery(document).ready(function() {
|
||||||
|
jQuery('#sidebar .category-icon').on('click', function() {
|
||||||
|
$( this ).toggleClass("fa-angle-down fa-angle-right") ;
|
||||||
|
$( this ).parent().parent().children('ul').toggle() ;
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
var sidebarStatus = searchStatus = 'open';
|
var sidebarStatus = searchStatus = 'open';
|
||||||
$('#sidebar .highlightable').perfectScrollbar();
|
$('#sidebar .highlightable').perfectScrollbar();
|
||||||
// set the menu height
|
|
||||||
setMenuHeight();
|
setMenuHeight();
|
||||||
|
|
||||||
jQuery('#overlay').on('click', function() {
|
jQuery('#overlay').on('click', function() {
|
||||||
@@ -147,10 +152,25 @@ jQuery(document).ready(function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$.expr[":"].contains = $.expr.createPseudo(function(arg) {
|
||||||
|
return function( elem ) {
|
||||||
|
return $(elem).text().toUpperCase().indexOf(arg.toUpperCase()) >= 0;
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
if (sessionStorage.getItem('search-value')) {
|
if (sessionStorage.getItem('search-value')) {
|
||||||
jQuery(document.body).removeClass('searchbox-hidden');
|
var searchValue = sessionStorage.getItem('search-value')
|
||||||
jQuery('[data-search-input]').val(sessionStorage.getItem('search-value'));
|
$(document.body).removeClass('searchbox-hidden');
|
||||||
jQuery('[data-search-input]').trigger('input');
|
$('[data-search-input]').val(searchValue);
|
||||||
|
$('[data-search-input]').trigger('input');
|
||||||
|
var searchedElem = $('#body-inner').find(':contains(' + searchValue + ')').get(0);
|
||||||
|
if (searchedElem) {
|
||||||
|
searchedElem.scrollIntoView(true);
|
||||||
|
var scrolledY = window.scrollY;
|
||||||
|
if(scrolledY){
|
||||||
|
window.scroll(0, scrolledY - 125);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clipboard
|
// clipboard
|
||||||
@@ -218,6 +238,8 @@ jQuery(document).ready(function() {
|
|||||||
$('#top-bar a:not(:has(img)):not(.btn)').addClass('highlight');
|
$('#top-bar a:not(:has(img)):not(.btn)').addClass('highlight');
|
||||||
$('#body-inner a:not(:has(img)):not(.btn)').addClass('highlight');
|
$('#body-inner a:not(:has(img)):not(.btn)').addClass('highlight');
|
||||||
|
|
||||||
|
var touchsupport = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0)
|
||||||
|
if (!touchsupport){ // browser doesn't support touch
|
||||||
$('#toc-menu').hover(function() {
|
$('#toc-menu').hover(function() {
|
||||||
$('.progress').stop(true, false, true).fadeToggle(100);
|
$('.progress').stop(true, false, true).fadeToggle(100);
|
||||||
});
|
});
|
||||||
@@ -225,6 +247,99 @@ jQuery(document).ready(function() {
|
|||||||
$('.progress').hover(function() {
|
$('.progress').hover(function() {
|
||||||
$('.progress').stop(true, false, true).fadeToggle(100);
|
$('.progress').stop(true, false, true).fadeToggle(100);
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
if (touchsupport){ // browser does support touch
|
||||||
|
$('#toc-menu').click(function() {
|
||||||
|
$('.progress').stop(true, false, true).fadeToggle(100);
|
||||||
|
});
|
||||||
|
$('.progress').click(function() {
|
||||||
|
$('.progress').stop(true, false, true).fadeToggle(100);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fix anchor scrolling that hides behind top nav bar
|
||||||
|
* Courtesy of https://stackoverflow.com/a/13067009/28106
|
||||||
|
*
|
||||||
|
* We could use pure css for this if only heading anchors were
|
||||||
|
* involved, but this works for any anchor, including footnotes
|
||||||
|
**/
|
||||||
|
(function (document, history, location) {
|
||||||
|
var HISTORY_SUPPORT = !!(history && history.pushState);
|
||||||
|
|
||||||
|
var anchorScrolls = {
|
||||||
|
ANCHOR_REGEX: /^#[^ ]+$/,
|
||||||
|
OFFSET_HEIGHT_PX: 50,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Establish events, and fix initial scroll position if a hash is provided.
|
||||||
|
*/
|
||||||
|
init: function () {
|
||||||
|
this.scrollToCurrent();
|
||||||
|
$(window).on('hashchange', $.proxy(this, 'scrollToCurrent'));
|
||||||
|
$('body').on('click', 'a', $.proxy(this, 'delegateAnchors'));
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the offset amount to deduct from the normal scroll position.
|
||||||
|
* Modify as appropriate to allow for dynamic calculations
|
||||||
|
*/
|
||||||
|
getFixedOffset: function () {
|
||||||
|
return this.OFFSET_HEIGHT_PX;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the provided href is an anchor which resolves to an element on the
|
||||||
|
* page, scroll to it.
|
||||||
|
* @param {String} href
|
||||||
|
* @return {Boolean} - Was the href an anchor.
|
||||||
|
*/
|
||||||
|
scrollIfAnchor: function (href, pushToHistory) {
|
||||||
|
var match, anchorOffset;
|
||||||
|
|
||||||
|
if (!this.ANCHOR_REGEX.test(href)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
match = document.getElementById(href.slice(1));
|
||||||
|
|
||||||
|
if (match) {
|
||||||
|
anchorOffset = $(match).offset().top - this.getFixedOffset();
|
||||||
|
$('html, body').animate({ scrollTop: anchorOffset });
|
||||||
|
|
||||||
|
// Add the state to history as-per normal anchor links
|
||||||
|
if (HISTORY_SUPPORT && pushToHistory) {
|
||||||
|
history.pushState({}, document.title, location.pathname + href);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !!match;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Attempt to scroll to the current location's hash.
|
||||||
|
*/
|
||||||
|
scrollToCurrent: function (e) {
|
||||||
|
if (this.scrollIfAnchor(window.location.hash) && e) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the click event's target was an anchor, fix the scroll position.
|
||||||
|
*/
|
||||||
|
delegateAnchors: function (e) {
|
||||||
|
var elem = e.target;
|
||||||
|
|
||||||
|
if (this.scrollIfAnchor(elem.getAttribute('href'), true)) {
|
||||||
|
e.preventDefault();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
$(document).ready($.proxy(anchorScrolls, 'init'));
|
||||||
|
})(window.document, window.history, window.location);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
jQuery(window).on('load', function() {
|
jQuery(window).on('load', function() {
|
||||||
|
|||||||
@@ -1,9 +1,17 @@
|
|||||||
var lunrIndex, pagesIndex;
|
var lunrIndex, pagesIndex;
|
||||||
|
|
||||||
|
function endsWith(str, suffix) {
|
||||||
|
return str.indexOf(suffix, str.length - suffix.length) !== -1;
|
||||||
|
}
|
||||||
|
|
||||||
// Initialize lunrjs using our generated index file
|
// Initialize lunrjs using our generated index file
|
||||||
function initLunr() {
|
function initLunr() {
|
||||||
|
if (!endsWith(baseurl,"/")){
|
||||||
|
baseurl = baseurl+'/'
|
||||||
|
};
|
||||||
|
|
||||||
// First retrieve the index file
|
// First retrieve the index file
|
||||||
$.getJSON(baseurl + "/json/search.json")
|
$.getJSON(baseurl +"index.json")
|
||||||
.done(function(index) {
|
.done(function(index) {
|
||||||
pagesIndex = index;
|
pagesIndex = index;
|
||||||
// Set up lunrjs by declaring the fields we use
|
// Set up lunrjs by declaring the fields we use
|
||||||
@@ -50,36 +58,33 @@ function search(query) {
|
|||||||
// Let's get started
|
// Let's get started
|
||||||
initLunr();
|
initLunr();
|
||||||
$( document ).ready(function() {
|
$( document ).ready(function() {
|
||||||
var horseyList = horsey($("#search-by").get(0), {
|
var searchList = new autoComplete({
|
||||||
suggestions: function (value, done) {
|
/* selector for the search box element */
|
||||||
var query = $("#search-by").val();
|
selector: $("#search-by").get(0),
|
||||||
var results = search(query);
|
/* source is the callback to perform the search */
|
||||||
done(results);
|
source: function(term, response) {
|
||||||
|
response(search(term));
|
||||||
},
|
},
|
||||||
filter: function (q, suggestion) {
|
/* renderItem displays individual search results */
|
||||||
return true;
|
renderItem: function(item, term) {
|
||||||
|
var numContextWords = 2;
|
||||||
|
var text = item.content.match(
|
||||||
|
"(?:\\s?(?:[\\w]+)\\s?){0,"+numContextWords+"}" +
|
||||||
|
term+"(?:\\s?(?:[\\w]+)\\s?){0,"+numContextWords+"}");
|
||||||
|
item.context = text;
|
||||||
|
return '<div class="autocomplete-suggestion" ' +
|
||||||
|
'data-term="' + term + '" ' +
|
||||||
|
'data-title="' + item.title + '" ' +
|
||||||
|
'data-uri="'+ item.uri + '" ' +
|
||||||
|
'data-context="' + item.context + '">' +
|
||||||
|
'» ' + item.title +
|
||||||
|
'<div class="context">' +
|
||||||
|
(item.context || '') +'</div>' +
|
||||||
|
'</div>';
|
||||||
},
|
},
|
||||||
set: function (value) {
|
/* onSelect callback fires when a search suggestion is chosen */
|
||||||
location.href=value.href;
|
onSelect: function(e, term, item) {
|
||||||
},
|
location.href = item.getAttribute('data-uri');
|
||||||
render: function (li, suggestion) {
|
|
||||||
var uri = suggestion.uri.substring(1,suggestion.uri.length);
|
|
||||||
var indexOfIndex = uri.lastIndexOf("/index");
|
|
||||||
if (indexOfIndex == -1) {
|
|
||||||
indexOfIndex = uri.length;
|
|
||||||
}
|
}
|
||||||
var href = uri.substring(uri.indexOf("/"), indexOfIndex);
|
|
||||||
suggestion.href = baseurl + href;
|
|
||||||
|
|
||||||
|
|
||||||
var query = $("#search-by").val();
|
|
||||||
var numWords = 2;
|
|
||||||
var text = suggestion.content.match("(?:\\s?(?:[\\w]+)\\s?){0,"+numWords+"}"+query+"(?:\\s?(?:[\\w]+)\\s?){0,"+numWords+"}");
|
|
||||||
suggestion.context = text;
|
|
||||||
var image = '<div>' + '» ' + suggestion.title + '</div><div style="font-size:12px">' + (suggestion.context || '') +'</div>';
|
|
||||||
li.innerHTML = image;
|
|
||||||
},
|
|
||||||
limit: 10
|
|
||||||
});
|
});
|
||||||
horseyList.refreshPosition();
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
{
|
{
|
||||||
"uri": "/content/getting-started/intro",
|
"uri": "/content/getting-started/intro",
|
||||||
"title": "Introduction",
|
"title": "Introduction",
|
||||||
"content": "\n{{% notice note %}}\nThis documentation is written for lettre 0.7.\nPlease use https://docs.rs/lettre/0.6.2/lettre/ for lettre 0.6.\n{{% /notice%}}\n\nLettre is an email library that allows creating and sending messages. It provides:\n\nAn easy to use email builder\nPluggable email transports\nUnicode support (for emails and transports, including for sender et recipient addresses when compatible)\nSecure defaults (emails are only sent encrypted by default)\n",
|
"content": "\nLettre is an email library that allows creating and sending messages. It provides:\n\nAn easy to use email builder\nPluggable email transports\nUnicode support (for emails and transports, including for sender et recipient addresses when compatible)\nSecure defaults (emails are only sent encrypted by default)\n",
|
||||||
"tags": []
|
"tags": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
{
|
{
|
||||||
"uri": "/content/sending-messages/file",
|
"uri": "/content/sending-messages/file",
|
||||||
"title": "File transport",
|
"title": "File transport",
|
||||||
"content": "\nThe file transport writes the emails to the given directory. The name of the file will be\nmessage_id.txt.\nIt can be useful for testing purposes, or if you want to keep track of sent messages.\n\nuse std::env::temp_dir;\n\nuse lettre::file::FileEmailTransport;\nuse lettre::{SimpleSendableEmail, EmailTransport, EmailAddress};\n\n// Write to the local temp directory\nlet mut sender = FileEmailTransport::new(temp_dir());\nlet email = SimpleSendableEmail::new(\n EmailAddress::new(\"user@localhost\".to_string()),\n vec![EmailAddress::new(\"root@localhost\".to_string())],\n \"messageid\".tostring(),\n \"Hello world\".to_string(),\n );\n\nlet result = sender.send(&email);\nassert!(result.is_ok());\n\nExample result in /tmp/b7c211bc-9811-45ce-8cd9-68eab575d695.txt:\n\nb7c211bc-9811-45ce-8cd9-68eab575d695: from=user@localhost to=root@localhost\nTo: root@localhost\nFrom: user@localhost\nSubject: Hello\nDate: Sat, 31 Oct 2015 13:42:19 +0100\nMessage-ID: b7c211bc-9811-45ce-8cd9-68eab575d695.lettre@localhost\n\nHello World!\n",
|
"content": "\nThe file transport writes the emails to the given directory. The name of the file will be\nmessage_id.txt.\nIt can be useful for testing purposes, or if you want to keep track of sent messages.\n\nuse std::env::temp_dir;\n\nuse lettre::file::FileEmailTransport;\nuse lettre::{SimpleSendableEmail, EmailTransport};\n\n// Write to the local temp directory\nlet mut sender = FileEmailTransport::new(temp_dir());\nlet email = SimpleSendableEmail::new(\n \"user@localhost\",\n vec![\"root@localhost\"],\n \"message_id\",\n \"Hello world\"\n );\n\nlet result = sender.send(email);\nassert!(result.is_ok());\n\nExample result in /tmp/b7c211bc-9811-45ce-8cd9-68eab575d695.txt:\n\nb7c211bc-9811-45ce-8cd9-68eab575d695: from=user@localhost to=root@localhost\nTo: root@localhost\nFrom: user@localhost\nSubject: Hello\nDate: Sat, 31 Oct 2015 13:42:19 +0100\nMessage-ID: b7c211bc-9811-45ce-8cd9-68eab575d695.lettre@localhost\n\nHello World!\n",
|
||||||
"tags": []
|
"tags": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -38,19 +38,19 @@
|
|||||||
{
|
{
|
||||||
"uri": "/content/sending-messages/sendmail",
|
"uri": "/content/sending-messages/sendmail",
|
||||||
"title": "Sendmail transport",
|
"title": "Sendmail transport",
|
||||||
"content": "\nThe sendmail transport sends the email using the local sendmail command.\n\nuse lettre::sendmail::SendmailTransport;\nuse lettre::{SimpleSendableEmail, EmailTransport, EmailAddress};\n\nlet email = SimpleSendableEmail::new(\n EmailAddress::new(\"user@localhost\".to_string()),\n vec![EmailAddress::new(\"root@localhost\".to_string())],\n \"messageid\".tostring(),\n \"Hello world\".to_string(),\n );\n\nlet mut sender = SendmailTransport::new();\nlet result = sender.send(&email);\nassert!(result.is_ok());\n",
|
"content": "\nThe sendmail transport sends the email using the local sendmail command.\n\nuse lettre::sendmail::SendmailTransport;\nuse lettre::{SimpleSendableEmail, EmailTransport};\n\nlet email = SimpleSendableEmail::new(\n \"user@localhost\",\n vec![\"root@localhost\"],\n \"message_id\",\n \"Hello world\"\n );\n\nlet mut sender = SendmailTransport::new();\nlet result = sender.send(email);\nassert!(result.is_ok());\n",
|
||||||
"tags": []
|
"tags": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"uri": "/content/sending-messages/smtp",
|
"uri": "/content/sending-messages/smtp",
|
||||||
"title": "SMTP transport",
|
"title": "SMTP transport",
|
||||||
"content": "\nThis transport uses the SMTP protocol to send emails over the network (locally or remotely).\n\nIt is desinged to be:\n\nSecured: email are encrypted by default\nModern: Unicode support for email content and sender/recipient adresses when compatible\nFast: supports tcp connection reuse\n\nThis client is designed to send emails to a relay server, and should not be used to send\nemails directly to the destination.\n\nThe relay server can be the local email server, a specific host or a third-party service.\n\nSimple example\n\nThis is the most basic example of usage:\n\nuse lettre::{SimpleSendableEmail, EmailTransport, EmailAddress, SmtpTransport};\n\nlet email = SimpleSendableEmail::new(\n EmailAddress::new(\"user@localhost\".to_string()),\n vec![EmailAddress::new(\"root@localhost\".to_string())],\n \"messageid\".tostring(),\n \"Hello world\".to_string(),\n );\n\n// Open a local connection on port 25\nlet mut mailer =\nSmtpTransport::builderunencryptedlocalhost().unwrap().build();\n// Send the email\nlet result = mailer.send(&email);\n\nassert!(result.is_ok());\n\n Complete example\n\nuse lettre::smtp::authentication::{Credentials, Mechanism};\nuse lettre::smtp::SUBMISSION_PORT;\nuse lettre::{SimpleSendableEmail, EmailTransport, EmailAddress, SmtpTransport};\nuse lettre::smtp::extension::ClientId;\nuse lettre::smtp::ConnectionReuseParameters;\n\nlet email = SimpleSendableEmail::new(\n EmailAddress::new(\"user@localhost\".to_string()),\n vec![EmailAddress::new(\"root@localhost\".to_string())],\n \"messageid\".tostring(),\n \"Hello world\".to_string(),\n );\n\n// Connect to a remote server on a custom port\nlet mut mailer = SmtpTransport::simplebuilder(\"server.tld\".tostring()).unwrap()\n // Set the name sent during EHLO/HELO, default is localhost\n .helloname(ClientId::Domain(\"my.hostname.tld\".tostring()))\n // Add credentials for authentication\n .credentials(Credentials::new(\"username\".tostring(), \"password\".tostring()))\n // Enable SMTPUTF8 if the server supports it\n .smtp_utf8(true)\n // Configure expected authentication mechanism\n .authentication_mechanism(Mechanism::Plain)\n // Enable connection reuse\n .connection_reuse(ConnectionReuseParameters::ReuseUnlimited).build();\n\nlet result_1 = mailer.send(&email);\nassert!(result1.isok());\n\n// The second email will use the same connection\nlet result_2 = mailer.send(&email);\nassert!(result2.isok());\n\n// Explicitly close the SMTP transaction as we enabled connection reuse\nmailer.close();\n\nLower level\n\nYou can also send commands, here is a simple email transaction without\nerror handling:\n\nuse lettre::EmailAddress;\nuse lettre::smtp::SMTP_PORT;\nuse lettre::smtp::client::Client;\nuse lettre::smtp::client::net::NetworkStream;\nuse lettre::smtp::extension::ClientId;\nuse lettre::smtp::commands::*;\n\nlet mut email_client: ClientNetworkStream = Client::new();\nlet _ = emailclient.connect(&(\"localhost\", SMTPPORT), None);\nlet _ = emailclient.smtpcommand(EhloCommand::new(ClientId::new(\"myhostname\".tostring())));\nlet _ = emailclient.smtpcommand(\n MailCommand::new(Some(EmailAddress::new(\"user@example.com\".to_string())), vec![])\n );\nlet _ = emailclient.smtpcommand(\n RcptCommand::new(EmailAddress::new(\"user@example.org\".to_string()), vec![])\n );\nlet _ = emailclient.smtpcommand(DataCommand);\nlet _ = emailclient.message(Box::new(\"Test email\".asbytes()));\nlet _ = emailclient.smtpcommand(QuitCommand);\n\n",
|
"content": "\nThis transport uses the SMTP protocol to send emails over the network (locally or remotely).\n\nIt is desinged to be:\n\nSecured: email are encrypted by default\nModern: Unicode support for email content and sender/recipient adresses when compatible\nFast: supports tcp connection reuse\n\nThis client is designed to send emails to a relay server, and should not be used to send\nemails directly to the destination.\n\nThe relay server can be the local email server, a specific host or a third-party service.\n\nSimple example\n\nThis is the most basic example of usage:\n\nuse lettre::{SimpleSendableEmail, EmailTransport};\nuse lettre::smtp::SmtpTransportBuilder;\nuse lettre::smtp::SecurityLevel;\n\nlet email = SimpleSendableEmail::new(\n \"user@localhost\",\n vec![\"root@localhost\"],\n \"message_id\",\n \"Hello world\"\n );\n\n// Open a local connection on port 25\nlet mut mailer =\nSmtpTransportBuilder::localhost().unwrap().security_level(SecurityLevel::Opportunistic).build();\n// Send the email\nlet result = mailer.send(email);\n\nassert!(result.is_ok());\n\n Complete example\n\nuse lettre::smtp::{SecurityLevel, SmtpTransport,\nSmtpTransportBuilder};\nuse lettre::smtp::authentication::Mechanism;\nuse lettre::smtp::SUBMISSION_PORT;\nuse lettre::{SimpleSendableEmail, EmailTransport};\n\nlet email = SimpleSendableEmail::new(\n \"user@localhost\",\n vec![\"root@localhost\"],\n \"message_id\",\n \"Hello world\"\n );\n\n// Connect to a remote server on a custom port\nlet mut mailer = SmtpTransportBuilder::new((\"server.tld\",\nSUBMISSION_PORT)).unwrap()\n // Set the name sent during EHLO/HELO, default is localhost\n .hello_name(\"my.hostname.tld\")\n // Add credentials for authentication\n .credentials(\"username\", \"password\")\n // Specify a TLS security level. You can also specify an SslContext with\n // .ssl_context(SslContext::Ssl23)\n .security_level(SecurityLevel::AlwaysEncrypt)\n // Enable SMTPUTF8 if the server supports it\n .smtp_utf8(true)\n // Configure expected authentication mechanism\n .authentication_mechanism(Mechanism::CramMd5)\n // Enable connection reuse\n .connection_reuse(true).build();\n\nlet result_1 = mailer.send(email.clone());\nassert!(result1.isok());\n\n// The second email will use the same connection\nlet result_2 = mailer.send(email);\nassert!(result2.isok());\n\n// Explicitly close the SMTP transaction as we enabled connection reuse\nmailer.close();\n\nLower level\n\nYou can also send commands, here is a simple email transaction without\nerror handling:\n\nuse lettre::smtp::SMTP_PORT;\nuse lettre::smtp::client::Client;\nuse lettre::smtp::client::net::NetworkStream;\n\nlet mut email_client: ClientNetworkStream = Client::new();\nlet _ = emailclient.connect(&(\"localhost\", SMTPPORT), None);\nlet _ = emailclient.ehlo(\"myhostname\");\nlet _ = email_client.mail(\"user@example.com\", None);\nlet _ = email_client.rcpt(\"user@example.org\");\nlet _ = email_client.data();\nlet _ = email_client.message(\"Test email\");\nlet _ = email_client.quit();\n\n",
|
||||||
"tags": []
|
"tags": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"uri": "/content/sending-messages/stub",
|
"uri": "/content/sending-messages/stub",
|
||||||
"title": "Stub transport",
|
"title": "Stub transport",
|
||||||
"content": "\nThe stub transport only logs message envelope and drops the content. It can be useful for\ntesting purposes.\n\nuse lettre::stub::StubEmailTransport;\nuse lettre::{SimpleSendableEmail, EmailTransport, EmailAddress};\n\nlet email = SimpleSendableEmail::new(\n EmailAddress::new(\"user@localhost\".to_string()),\n vec![EmailAddress::new(\"root@localhost\".to_string())],\n \"messageid\".tostring(),\n \"Hello world\".to_string(),\n );\n\nlet mut sender = StubEmailTransport::new_positive();\nlet result = sender.send(&email);\nassert!(result.is_ok());\n\nWill log (when using a logger like env_logger):\n\nb7c211bc-9811-45ce-8cd9-68eab575d695: from=user@localhost to=root@localhost\n",
|
"content": "\nThe stub transport only logs message envelope and drops the content. It can be useful for\ntesting purposes.\n\nuse lettre::stub::StubEmailTransport;\nuse lettre::{SimpleSendableEmail, EmailTransport};\n\nlet email = SimpleSendableEmail::new(\n \"user@localhost\",\n vec![\"root@localhost\"],\n \"message_id\",\n \"Hello world\"\n );\n\nlet mut sender = StubEmailTransport;\nlet result = sender.send(email);\nassert!(result.is_ok());\n\nWill log the line:\n\nb7c211bc-9811-45ce-8cd9-68eab575d695: from=user@localhost to=root@localhost\n`",
|
||||||
"tags": []
|
"tags": []
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
273
docs/mermaid/mermaid.css
Normal file
273
docs/mermaid/mermaid.css
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
/* Flowchart variables */
|
||||||
|
/* Sequence Diagram variables */
|
||||||
|
/* Gantt chart variables */
|
||||||
|
.mermaid .label {
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.node rect,
|
||||||
|
.node circle,
|
||||||
|
.node ellipse,
|
||||||
|
.node polygon {
|
||||||
|
fill: #ECECFF;
|
||||||
|
stroke: #CCCCFF;
|
||||||
|
stroke-width: 1px;
|
||||||
|
}
|
||||||
|
.edgePath .path {
|
||||||
|
stroke: #333333;
|
||||||
|
}
|
||||||
|
.edgeLabel {
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
}
|
||||||
|
.cluster rect {
|
||||||
|
fill: #ffffde !important;
|
||||||
|
rx: 4 !important;
|
||||||
|
stroke: #aaaa33 !important;
|
||||||
|
stroke-width: 1px !important;
|
||||||
|
}
|
||||||
|
.cluster text {
|
||||||
|
fill: #333;
|
||||||
|
}
|
||||||
|
.actor {
|
||||||
|
stroke: #CCCCFF;
|
||||||
|
fill: #ECECFF;
|
||||||
|
}
|
||||||
|
text.actor {
|
||||||
|
fill: black;
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
.actor-line {
|
||||||
|
stroke: grey;
|
||||||
|
}
|
||||||
|
.messageLine0 {
|
||||||
|
stroke-width: 1.5;
|
||||||
|
stroke-dasharray: "2 2";
|
||||||
|
marker-end: "url(#arrowhead)";
|
||||||
|
stroke: #333;
|
||||||
|
}
|
||||||
|
.messageLine1 {
|
||||||
|
stroke-width: 1.5;
|
||||||
|
stroke-dasharray: "2 2";
|
||||||
|
stroke: #333;
|
||||||
|
}
|
||||||
|
#arrowhead {
|
||||||
|
fill: #333;
|
||||||
|
}
|
||||||
|
#crosshead path {
|
||||||
|
fill: #333 !important;
|
||||||
|
stroke: #333 !important;
|
||||||
|
}
|
||||||
|
.messageText {
|
||||||
|
fill: #333;
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
.labelBox {
|
||||||
|
stroke: #CCCCFF;
|
||||||
|
fill: #ECECFF;
|
||||||
|
}
|
||||||
|
.labelText {
|
||||||
|
fill: black;
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
.loopText {
|
||||||
|
fill: black;
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
.loopLine {
|
||||||
|
stroke-width: 2;
|
||||||
|
stroke-dasharray: "2 2";
|
||||||
|
marker-end: "url(#arrowhead)";
|
||||||
|
stroke: #CCCCFF;
|
||||||
|
}
|
||||||
|
.note {
|
||||||
|
stroke: #aaaa33;
|
||||||
|
fill: #fff5ad;
|
||||||
|
}
|
||||||
|
.noteText {
|
||||||
|
fill: black;
|
||||||
|
stroke: none;
|
||||||
|
font-family: 'trebuchet ms', verdana, arial;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
/** Section styling */
|
||||||
|
.section {
|
||||||
|
stroke: none;
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
.section0 {
|
||||||
|
fill: rgba(102, 102, 255, 0.49);
|
||||||
|
}
|
||||||
|
.section2 {
|
||||||
|
fill: #fff400;
|
||||||
|
}
|
||||||
|
.section1,
|
||||||
|
.section3 {
|
||||||
|
fill: white;
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
.sectionTitle0 {
|
||||||
|
fill: #333;
|
||||||
|
}
|
||||||
|
.sectionTitle1 {
|
||||||
|
fill: #333;
|
||||||
|
}
|
||||||
|
.sectionTitle2 {
|
||||||
|
fill: #333;
|
||||||
|
}
|
||||||
|
.sectionTitle3 {
|
||||||
|
fill: #333;
|
||||||
|
}
|
||||||
|
.sectionTitle {
|
||||||
|
text-anchor: start;
|
||||||
|
font-size: 11px;
|
||||||
|
text-height: 14px;
|
||||||
|
}
|
||||||
|
/* Grid and axis */
|
||||||
|
.grid .tick {
|
||||||
|
stroke: lightgrey;
|
||||||
|
opacity: 0.3;
|
||||||
|
shape-rendering: crispEdges;
|
||||||
|
}
|
||||||
|
.grid path {
|
||||||
|
stroke-width: 0;
|
||||||
|
}
|
||||||
|
/* Today line */
|
||||||
|
.today {
|
||||||
|
fill: none;
|
||||||
|
stroke: red;
|
||||||
|
stroke-width: 2px;
|
||||||
|
}
|
||||||
|
/* Task styling */
|
||||||
|
/* Default task */
|
||||||
|
.task {
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
.taskText {
|
||||||
|
text-anchor: middle;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
.taskTextOutsideRight {
|
||||||
|
fill: black;
|
||||||
|
text-anchor: start;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
.taskTextOutsideLeft {
|
||||||
|
fill: black;
|
||||||
|
text-anchor: end;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
/* Specific task settings for the sections*/
|
||||||
|
.taskText0,
|
||||||
|
.taskText1,
|
||||||
|
.taskText2,
|
||||||
|
.taskText3 {
|
||||||
|
fill: white;
|
||||||
|
}
|
||||||
|
.task0,
|
||||||
|
.task1,
|
||||||
|
.task2,
|
||||||
|
.task3 {
|
||||||
|
fill: #8a90dd;
|
||||||
|
stroke: #534fbc;
|
||||||
|
}
|
||||||
|
.taskTextOutside0,
|
||||||
|
.taskTextOutside2 {
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
.taskTextOutside1,
|
||||||
|
.taskTextOutside3 {
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
/* Active task */
|
||||||
|
.active0,
|
||||||
|
.active1,
|
||||||
|
.active2,
|
||||||
|
.active3 {
|
||||||
|
fill: #bfc7ff;
|
||||||
|
stroke: #534fbc;
|
||||||
|
}
|
||||||
|
.activeText0,
|
||||||
|
.activeText1,
|
||||||
|
.activeText2,
|
||||||
|
.activeText3 {
|
||||||
|
fill: black !important;
|
||||||
|
}
|
||||||
|
/* Completed task */
|
||||||
|
.done0,
|
||||||
|
.done1,
|
||||||
|
.done2,
|
||||||
|
.done3 {
|
||||||
|
stroke: grey;
|
||||||
|
fill: lightgrey;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
.doneText0,
|
||||||
|
.doneText1,
|
||||||
|
.doneText2,
|
||||||
|
.doneText3 {
|
||||||
|
fill: black !important;
|
||||||
|
}
|
||||||
|
/* Tasks on the critical line */
|
||||||
|
.crit0,
|
||||||
|
.crit1,
|
||||||
|
.crit2,
|
||||||
|
.crit3 {
|
||||||
|
stroke: #ff8888;
|
||||||
|
fill: red;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
.activeCrit0,
|
||||||
|
.activeCrit1,
|
||||||
|
.activeCrit2,
|
||||||
|
.activeCrit3 {
|
||||||
|
stroke: #ff8888;
|
||||||
|
fill: #bfc7ff;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
.doneCrit0,
|
||||||
|
.doneCrit1,
|
||||||
|
.doneCrit2,
|
||||||
|
.doneCrit3 {
|
||||||
|
stroke: #ff8888;
|
||||||
|
fill: lightgrey;
|
||||||
|
stroke-width: 2;
|
||||||
|
cursor: pointer;
|
||||||
|
shape-rendering: crispEdges;
|
||||||
|
}
|
||||||
|
.doneCritText0,
|
||||||
|
.doneCritText1,
|
||||||
|
.doneCritText2,
|
||||||
|
.doneCritText3 {
|
||||||
|
fill: black !important;
|
||||||
|
}
|
||||||
|
.activeCritText0,
|
||||||
|
.activeCritText1,
|
||||||
|
.activeCritText2,
|
||||||
|
.activeCritText3 {
|
||||||
|
fill: black !important;
|
||||||
|
}
|
||||||
|
.titleText {
|
||||||
|
text-anchor: middle;
|
||||||
|
font-size: 18px;
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
.node text {
|
||||||
|
font-family: 'trebuchet ms', verdana, arial;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
div.mermaidTooltip {
|
||||||
|
position: absolute;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 200px;
|
||||||
|
padding: 2px;
|
||||||
|
font-family: 'trebuchet ms', verdana, arial;
|
||||||
|
font-size: 12px;
|
||||||
|
background: #ffffde;
|
||||||
|
border: 1px solid #aaaa33;
|
||||||
|
border-radius: 2px;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
275
docs/mermaid/mermaid.dark.css
Normal file
275
docs/mermaid/mermaid.dark.css
Normal file
@@ -0,0 +1,275 @@
|
|||||||
|
/* Flowchart variables */
|
||||||
|
/* Sequence Diagram variables */
|
||||||
|
/* Gantt chart variables */
|
||||||
|
.mermaid .label {
|
||||||
|
color: #323D47;
|
||||||
|
}
|
||||||
|
.node rect,
|
||||||
|
.node circle,
|
||||||
|
.node ellipse,
|
||||||
|
.node polygon {
|
||||||
|
fill: #BDD5EA;
|
||||||
|
stroke: #81B1DB;
|
||||||
|
stroke-width: 1px;
|
||||||
|
}
|
||||||
|
.edgePath .path {
|
||||||
|
stroke: lightgrey;
|
||||||
|
}
|
||||||
|
.edgeLabel {
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
}
|
||||||
|
.cluster rect {
|
||||||
|
fill: #6D6D65 !important;
|
||||||
|
rx: 4 !important;
|
||||||
|
stroke: rgba(255, 255, 255, 0.25) !important;
|
||||||
|
stroke-width: 1px !important;
|
||||||
|
}
|
||||||
|
.cluster text {
|
||||||
|
fill: #F9FFFE;
|
||||||
|
}
|
||||||
|
.actor {
|
||||||
|
stroke: #81B1DB;
|
||||||
|
fill: #BDD5EA;
|
||||||
|
}
|
||||||
|
text.actor {
|
||||||
|
fill: black;
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
.actor-line {
|
||||||
|
stroke: lightgrey;
|
||||||
|
}
|
||||||
|
.messageLine0 {
|
||||||
|
stroke-width: 1.5;
|
||||||
|
stroke-dasharray: "2 2";
|
||||||
|
marker-end: "url(#arrowhead)";
|
||||||
|
stroke: lightgrey;
|
||||||
|
}
|
||||||
|
.messageLine1 {
|
||||||
|
stroke-width: 1.5;
|
||||||
|
stroke-dasharray: "2 2";
|
||||||
|
stroke: lightgrey;
|
||||||
|
}
|
||||||
|
#arrowhead {
|
||||||
|
fill: lightgrey !important;
|
||||||
|
}
|
||||||
|
#crosshead path {
|
||||||
|
fill: lightgrey !important;
|
||||||
|
stroke: lightgrey !important;
|
||||||
|
}
|
||||||
|
.messageText {
|
||||||
|
fill: lightgrey;
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
.labelBox {
|
||||||
|
stroke: #81B1DB;
|
||||||
|
fill: #BDD5EA;
|
||||||
|
}
|
||||||
|
.labelText {
|
||||||
|
fill: #323D47;
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
.loopText {
|
||||||
|
fill: lightgrey;
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
.loopLine {
|
||||||
|
stroke-width: 2;
|
||||||
|
stroke-dasharray: "2 2";
|
||||||
|
marker-end: "url(#arrowhead)";
|
||||||
|
stroke: #81B1DB;
|
||||||
|
}
|
||||||
|
.note {
|
||||||
|
stroke: rgba(255, 255, 255, 0.25);
|
||||||
|
fill: #fff5ad;
|
||||||
|
}
|
||||||
|
.noteText {
|
||||||
|
fill: black;
|
||||||
|
stroke: none;
|
||||||
|
font-family: 'trebuchet ms', verdana, arial;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
/** Section styling */
|
||||||
|
.section {
|
||||||
|
stroke: none;
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
.section0 {
|
||||||
|
fill: rgba(255, 255, 255, 0.3);
|
||||||
|
}
|
||||||
|
.section2 {
|
||||||
|
fill: #EAE8B9;
|
||||||
|
}
|
||||||
|
.section1,
|
||||||
|
.section3 {
|
||||||
|
fill: white;
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
.sectionTitle0 {
|
||||||
|
fill: #F9FFFE;
|
||||||
|
}
|
||||||
|
.sectionTitle1 {
|
||||||
|
fill: #F9FFFE;
|
||||||
|
}
|
||||||
|
.sectionTitle2 {
|
||||||
|
fill: #F9FFFE;
|
||||||
|
}
|
||||||
|
.sectionTitle3 {
|
||||||
|
fill: #F9FFFE;
|
||||||
|
}
|
||||||
|
.sectionTitle {
|
||||||
|
text-anchor: start;
|
||||||
|
font-size: 11px;
|
||||||
|
text-height: 14px;
|
||||||
|
}
|
||||||
|
/* Grid and axis */
|
||||||
|
.grid .tick {
|
||||||
|
stroke: rgba(255, 255, 255, 0.3);
|
||||||
|
opacity: 0.3;
|
||||||
|
shape-rendering: crispEdges;
|
||||||
|
}
|
||||||
|
.grid .tick text {
|
||||||
|
fill: lightgrey;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
.grid path {
|
||||||
|
stroke-width: 0;
|
||||||
|
}
|
||||||
|
/* Today line */
|
||||||
|
.today {
|
||||||
|
fill: none;
|
||||||
|
stroke: #DB5757;
|
||||||
|
stroke-width: 2px;
|
||||||
|
}
|
||||||
|
/* Task styling */
|
||||||
|
/* Default task */
|
||||||
|
.task {
|
||||||
|
stroke-width: 1;
|
||||||
|
}
|
||||||
|
.taskText {
|
||||||
|
text-anchor: middle;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
.taskTextOutsideRight {
|
||||||
|
fill: #323D47;
|
||||||
|
text-anchor: start;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
.taskTextOutsideLeft {
|
||||||
|
fill: #323D47;
|
||||||
|
text-anchor: end;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
/* Specific task settings for the sections*/
|
||||||
|
.taskText0,
|
||||||
|
.taskText1,
|
||||||
|
.taskText2,
|
||||||
|
.taskText3 {
|
||||||
|
fill: #323D47;
|
||||||
|
}
|
||||||
|
.task0,
|
||||||
|
.task1,
|
||||||
|
.task2,
|
||||||
|
.task3 {
|
||||||
|
fill: #BDD5EA;
|
||||||
|
stroke: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
.taskTextOutside0,
|
||||||
|
.taskTextOutside2 {
|
||||||
|
fill: lightgrey;
|
||||||
|
}
|
||||||
|
.taskTextOutside1,
|
||||||
|
.taskTextOutside3 {
|
||||||
|
fill: lightgrey;
|
||||||
|
}
|
||||||
|
/* Active task */
|
||||||
|
.active0,
|
||||||
|
.active1,
|
||||||
|
.active2,
|
||||||
|
.active3 {
|
||||||
|
fill: #81B1DB;
|
||||||
|
stroke: rgba(255, 255, 255, 0.5);
|
||||||
|
}
|
||||||
|
.activeText0,
|
||||||
|
.activeText1,
|
||||||
|
.activeText2,
|
||||||
|
.activeText3 {
|
||||||
|
fill: #323D47 !important;
|
||||||
|
}
|
||||||
|
/* Completed task */
|
||||||
|
.done0,
|
||||||
|
.done1,
|
||||||
|
.done2,
|
||||||
|
.done3 {
|
||||||
|
fill: lightgrey;
|
||||||
|
}
|
||||||
|
.doneText0,
|
||||||
|
.doneText1,
|
||||||
|
.doneText2,
|
||||||
|
.doneText3 {
|
||||||
|
fill: #323D47 !important;
|
||||||
|
}
|
||||||
|
/* Tasks on the critical line */
|
||||||
|
.crit0,
|
||||||
|
.crit1,
|
||||||
|
.crit2,
|
||||||
|
.crit3 {
|
||||||
|
stroke: #E83737;
|
||||||
|
fill: #E83737;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
.activeCrit0,
|
||||||
|
.activeCrit1,
|
||||||
|
.activeCrit2,
|
||||||
|
.activeCrit3 {
|
||||||
|
stroke: #E83737;
|
||||||
|
fill: #81B1DB;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
.doneCrit0,
|
||||||
|
.doneCrit1,
|
||||||
|
.doneCrit2,
|
||||||
|
.doneCrit3 {
|
||||||
|
stroke: #E83737;
|
||||||
|
fill: lightgrey;
|
||||||
|
stroke-width: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
shape-rendering: crispEdges;
|
||||||
|
}
|
||||||
|
.doneCritText0,
|
||||||
|
.doneCritText1,
|
||||||
|
.doneCritText2,
|
||||||
|
.doneCritText3 {
|
||||||
|
fill: lightgrey !important;
|
||||||
|
}
|
||||||
|
.activeCritText0,
|
||||||
|
.activeCritText1,
|
||||||
|
.activeCritText2,
|
||||||
|
.activeCritText3 {
|
||||||
|
fill: #323D47 !important;
|
||||||
|
}
|
||||||
|
.titleText {
|
||||||
|
text-anchor: middle;
|
||||||
|
font-size: 18px;
|
||||||
|
fill: lightgrey;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
.node text {
|
||||||
|
font-family: 'trebuchet ms', verdana, arial;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
div.mermaidTooltip {
|
||||||
|
position: absolute;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 200px;
|
||||||
|
padding: 2px;
|
||||||
|
font-family: 'trebuchet ms', verdana, arial;
|
||||||
|
font-size: 12px;
|
||||||
|
background: #6D6D65;
|
||||||
|
border: 1px solid rgba(255, 255, 255, 0.25);
|
||||||
|
border-radius: 2px;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
353
docs/mermaid/mermaid.forest.css
Normal file
353
docs/mermaid/mermaid.forest.css
Normal file
@@ -0,0 +1,353 @@
|
|||||||
|
/* Flowchart variables */
|
||||||
|
/* Sequence Diagram variables */
|
||||||
|
/* Gantt chart variables */
|
||||||
|
.mermaid .label {
|
||||||
|
font-family: 'trebuchet ms', verdana, arial;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
.node rect,
|
||||||
|
.node circle,
|
||||||
|
.node ellipse,
|
||||||
|
.node polygon {
|
||||||
|
fill: #cde498;
|
||||||
|
stroke: #13540c;
|
||||||
|
stroke-width: 1px;
|
||||||
|
}
|
||||||
|
.edgePath .path {
|
||||||
|
stroke: green;
|
||||||
|
stroke-width: 1.5px;
|
||||||
|
}
|
||||||
|
.edgeLabel {
|
||||||
|
background-color: #e8e8e8;
|
||||||
|
}
|
||||||
|
.cluster rect {
|
||||||
|
fill: #cdffb2 !important;
|
||||||
|
rx: 4 !important;
|
||||||
|
stroke: #6eaa49 !important;
|
||||||
|
stroke-width: 1px !important;
|
||||||
|
}
|
||||||
|
.cluster text {
|
||||||
|
fill: #333;
|
||||||
|
}
|
||||||
|
.actor {
|
||||||
|
stroke: #13540c;
|
||||||
|
fill: #cde498;
|
||||||
|
}
|
||||||
|
text.actor {
|
||||||
|
fill: black;
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
.actor-line {
|
||||||
|
stroke: grey;
|
||||||
|
}
|
||||||
|
.messageLine0 {
|
||||||
|
stroke-width: 1.5;
|
||||||
|
stroke-dasharray: "2 2";
|
||||||
|
marker-end: "url(#arrowhead)";
|
||||||
|
stroke: #333;
|
||||||
|
}
|
||||||
|
.messageLine1 {
|
||||||
|
stroke-width: 1.5;
|
||||||
|
stroke-dasharray: "2 2";
|
||||||
|
stroke: #333;
|
||||||
|
}
|
||||||
|
#arrowhead {
|
||||||
|
fill: #333;
|
||||||
|
}
|
||||||
|
#crosshead path {
|
||||||
|
fill: #333 !important;
|
||||||
|
stroke: #333 !important;
|
||||||
|
}
|
||||||
|
.messageText {
|
||||||
|
fill: #333;
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
.labelBox {
|
||||||
|
stroke: #326932;
|
||||||
|
fill: #cde498;
|
||||||
|
}
|
||||||
|
.labelText {
|
||||||
|
fill: black;
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
.loopText {
|
||||||
|
fill: black;
|
||||||
|
stroke: none;
|
||||||
|
}
|
||||||
|
.loopLine {
|
||||||
|
stroke-width: 2;
|
||||||
|
stroke-dasharray: "2 2";
|
||||||
|
marker-end: "url(#arrowhead)";
|
||||||
|
stroke: #326932;
|
||||||
|
}
|
||||||
|
.note {
|
||||||
|
stroke: #6eaa49;
|
||||||
|
fill: #fff5ad;
|
||||||
|
}
|
||||||
|
.noteText {
|
||||||
|
fill: black;
|
||||||
|
stroke: none;
|
||||||
|
font-family: 'trebuchet ms', verdana, arial;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
/** Section styling */
|
||||||
|
.section {
|
||||||
|
stroke: none;
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
.section0 {
|
||||||
|
fill: #6eaa49;
|
||||||
|
}
|
||||||
|
.section2 {
|
||||||
|
fill: #6eaa49;
|
||||||
|
}
|
||||||
|
.section1,
|
||||||
|
.section3 {
|
||||||
|
fill: white;
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
.sectionTitle0 {
|
||||||
|
fill: #333;
|
||||||
|
}
|
||||||
|
.sectionTitle1 {
|
||||||
|
fill: #333;
|
||||||
|
}
|
||||||
|
.sectionTitle2 {
|
||||||
|
fill: #333;
|
||||||
|
}
|
||||||
|
.sectionTitle3 {
|
||||||
|
fill: #333;
|
||||||
|
}
|
||||||
|
.sectionTitle {
|
||||||
|
text-anchor: start;
|
||||||
|
font-size: 11px;
|
||||||
|
text-height: 14px;
|
||||||
|
}
|
||||||
|
/* Grid and axis */
|
||||||
|
.grid .tick {
|
||||||
|
stroke: lightgrey;
|
||||||
|
opacity: 0.3;
|
||||||
|
shape-rendering: crispEdges;
|
||||||
|
}
|
||||||
|
.grid path {
|
||||||
|
stroke-width: 0;
|
||||||
|
}
|
||||||
|
/* Today line */
|
||||||
|
.today {
|
||||||
|
fill: none;
|
||||||
|
stroke: red;
|
||||||
|
stroke-width: 2px;
|
||||||
|
}
|
||||||
|
/* Task styling */
|
||||||
|
/* Default task */
|
||||||
|
.task {
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
.taskText {
|
||||||
|
text-anchor: middle;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
.taskTextOutsideRight {
|
||||||
|
fill: black;
|
||||||
|
text-anchor: start;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
.taskTextOutsideLeft {
|
||||||
|
fill: black;
|
||||||
|
text-anchor: end;
|
||||||
|
font-size: 11px;
|
||||||
|
}
|
||||||
|
/* Specific task settings for the sections*/
|
||||||
|
.taskText0,
|
||||||
|
.taskText1,
|
||||||
|
.taskText2,
|
||||||
|
.taskText3 {
|
||||||
|
fill: white;
|
||||||
|
}
|
||||||
|
.task0,
|
||||||
|
.task1,
|
||||||
|
.task2,
|
||||||
|
.task3 {
|
||||||
|
fill: #487e3a;
|
||||||
|
stroke: #13540c;
|
||||||
|
}
|
||||||
|
.taskTextOutside0,
|
||||||
|
.taskTextOutside2 {
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
.taskTextOutside1,
|
||||||
|
.taskTextOutside3 {
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
/* Active task */
|
||||||
|
.active0,
|
||||||
|
.active1,
|
||||||
|
.active2,
|
||||||
|
.active3 {
|
||||||
|
fill: #cde498;
|
||||||
|
stroke: #13540c;
|
||||||
|
}
|
||||||
|
.activeText0,
|
||||||
|
.activeText1,
|
||||||
|
.activeText2,
|
||||||
|
.activeText3 {
|
||||||
|
fill: black !important;
|
||||||
|
}
|
||||||
|
/* Completed task */
|
||||||
|
.done0,
|
||||||
|
.done1,
|
||||||
|
.done2,
|
||||||
|
.done3 {
|
||||||
|
stroke: grey;
|
||||||
|
fill: lightgrey;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
.doneText0,
|
||||||
|
.doneText1,
|
||||||
|
.doneText2,
|
||||||
|
.doneText3 {
|
||||||
|
fill: black !important;
|
||||||
|
}
|
||||||
|
/* Tasks on the critical line */
|
||||||
|
.crit0,
|
||||||
|
.crit1,
|
||||||
|
.crit2,
|
||||||
|
.crit3 {
|
||||||
|
stroke: #ff8888;
|
||||||
|
fill: red;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
.activeCrit0,
|
||||||
|
.activeCrit1,
|
||||||
|
.activeCrit2,
|
||||||
|
.activeCrit3 {
|
||||||
|
stroke: #ff8888;
|
||||||
|
fill: #cde498;
|
||||||
|
stroke-width: 2;
|
||||||
|
}
|
||||||
|
.doneCrit0,
|
||||||
|
.doneCrit1,
|
||||||
|
.doneCrit2,
|
||||||
|
.doneCrit3 {
|
||||||
|
stroke: #ff8888;
|
||||||
|
fill: lightgrey;
|
||||||
|
stroke-width: 2;
|
||||||
|
cursor: pointer;
|
||||||
|
shape-rendering: crispEdges;
|
||||||
|
}
|
||||||
|
.doneCritText0,
|
||||||
|
.doneCritText1,
|
||||||
|
.doneCritText2,
|
||||||
|
.doneCritText3 {
|
||||||
|
fill: black !important;
|
||||||
|
}
|
||||||
|
.activeCritText0,
|
||||||
|
.activeCritText1,
|
||||||
|
.activeCritText2,
|
||||||
|
.activeCritText3 {
|
||||||
|
fill: black !important;
|
||||||
|
}
|
||||||
|
.titleText {
|
||||||
|
text-anchor: middle;
|
||||||
|
font-size: 18px;
|
||||||
|
fill: black;
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
|
||||||
|
|
||||||
|
*/
|
||||||
|
g.classGroup text {
|
||||||
|
fill: #13540c;
|
||||||
|
stroke: none;
|
||||||
|
font-family: 'trebuchet ms', verdana, arial;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
g.classGroup rect {
|
||||||
|
fill: #cde498;
|
||||||
|
stroke: #13540c;
|
||||||
|
}
|
||||||
|
g.classGroup line {
|
||||||
|
stroke: #13540c;
|
||||||
|
stroke-width: 1;
|
||||||
|
}
|
||||||
|
svg .classLabel .box {
|
||||||
|
stroke: none;
|
||||||
|
stroke-width: 0;
|
||||||
|
fill: #cde498;
|
||||||
|
opacity: 0.5;
|
||||||
|
}
|
||||||
|
svg .classLabel .label {
|
||||||
|
fill: #13540c;
|
||||||
|
}
|
||||||
|
.relation {
|
||||||
|
stroke: #13540c;
|
||||||
|
stroke-width: 1;
|
||||||
|
fill: none;
|
||||||
|
}
|
||||||
|
.composition {
|
||||||
|
fill: #13540c;
|
||||||
|
stroke: #13540c;
|
||||||
|
stroke-width: 1;
|
||||||
|
}
|
||||||
|
#compositionStart {
|
||||||
|
fill: #13540c;
|
||||||
|
stroke: #13540c;
|
||||||
|
stroke-width: 1;
|
||||||
|
}
|
||||||
|
#compositionEnd {
|
||||||
|
fill: #13540c;
|
||||||
|
stroke: #13540c;
|
||||||
|
stroke-width: 1;
|
||||||
|
}
|
||||||
|
.aggregation {
|
||||||
|
fill: #cde498;
|
||||||
|
stroke: #13540c;
|
||||||
|
stroke-width: 1;
|
||||||
|
}
|
||||||
|
#aggregationStart {
|
||||||
|
fill: #cde498;
|
||||||
|
stroke: #13540c;
|
||||||
|
stroke-width: 1;
|
||||||
|
}
|
||||||
|
#aggregationEnd {
|
||||||
|
fill: #cde498;
|
||||||
|
stroke: #13540c;
|
||||||
|
stroke-width: 1;
|
||||||
|
}
|
||||||
|
#dependencyStart {
|
||||||
|
fill: #13540c;
|
||||||
|
stroke: #13540c;
|
||||||
|
stroke-width: 1;
|
||||||
|
}
|
||||||
|
#dependencyEnd {
|
||||||
|
fill: #13540c;
|
||||||
|
stroke: #13540c;
|
||||||
|
stroke-width: 1;
|
||||||
|
}
|
||||||
|
#extensionStart {
|
||||||
|
fill: #13540c;
|
||||||
|
stroke: #13540c;
|
||||||
|
stroke-width: 1;
|
||||||
|
}
|
||||||
|
#extensionEnd {
|
||||||
|
fill: #13540c;
|
||||||
|
stroke: #13540c;
|
||||||
|
stroke-width: 1;
|
||||||
|
}
|
||||||
|
.node text {
|
||||||
|
font-family: 'trebuchet ms', verdana, arial;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
div.mermaidTooltip {
|
||||||
|
position: absolute;
|
||||||
|
text-align: center;
|
||||||
|
max-width: 200px;
|
||||||
|
padding: 2px;
|
||||||
|
font-family: 'trebuchet ms', verdana, arial;
|
||||||
|
font-size: 12px;
|
||||||
|
background: #cdffb2;
|
||||||
|
border: 1px solid #6eaa49;
|
||||||
|
border-radius: 2px;
|
||||||
|
pointer-events: none;
|
||||||
|
z-index: 100;
|
||||||
|
}
|
||||||
30
docs/mermaid/mermaid.js
Normal file
30
docs/mermaid/mermaid.js
Normal file
File diff suppressed because one or more lines are too long
@@ -3,53 +3,64 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
<meta name="generator" content="Hugo 0.20.7" />
|
<meta name="generator" content="Hugo 0.37.1" />
|
||||||
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
||||||
<meta name="author" content="Alexis Mousset">
|
<meta name="author" content="Alexis Mousset">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="https://lettre.github.io/lettre//images/favicon.png" type="image/x-icon" />
|
<link rel="shortcut icon" href="http://docs.lettre.at//images/favicon.png" type="image/x-icon" />
|
||||||
|
|
||||||
|
<title>File transport :: Lettre site</title>
|
||||||
|
|
||||||
|
|
||||||
<title>File transport</title>
|
<link href="/css/nucleus.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/nucleus.css" rel="stylesheet">
|
<link href="/css/font-awesome.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/font-awesome.min.css" rel="stylesheet">
|
<link href="/css/hybrid.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hybrid.css" rel="stylesheet">
|
<link href="/css/featherlight.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/featherlight.min.css" rel="stylesheet">
|
<link href="/css/perfect-scrollbar.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/perfect-scrollbar.min.css" rel="stylesheet">
|
<link href="/css/auto-complete.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/horsey.css" rel="stylesheet">
|
<link href="/css/theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/theme.css" rel="stylesheet">
|
<link href="/css/hugo-theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hugo-theme.css" rel="stylesheet">
|
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery-2.x.min.js"></script>
|
|
||||||
<style type="text/css">:root #header + #content > #left > #rlblock_left
|
|
||||||
{display:none !important;}</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/jquery-2.x.min.js?1522603726"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
:root #header + #content > #left > #rlblock_left{
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="" data-url="/lettre/sending-messages/file/">
|
<body class="" data-url="/sending-messages/file/">
|
||||||
|
<nav id="sidebar" class="">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<nav id="sidebar">
|
|
||||||
<div id="header-wrapper">
|
<div id="header-wrapper">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<a href="https://lettre.github.io/lettre//getting-started/intro/"><img src="https://lettre.github.io/lettre//images/logo50.png" /></a>
|
<a href="http://docs.lettre.at//getting-started/intro/"><img src="http://docs.lettre.at//images/logo50.png" /></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="searchbox">
|
<div class="searchbox">
|
||||||
<label for="search-by"><i class="fa fa-search"></i></label>
|
<label for="search-by"><i class="fa fa-search"></i></label>
|
||||||
<input data-search-input id="search-by" type="text" placeholder="Search">
|
<input data-search-input id="search-by" type="text" placeholder="Search...">
|
||||||
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/lunr.min.js"></script>
|
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/horsey.js"></script>
|
<script type="text/javascript" src="/js/lunr.min.js?1522603726"></script>
|
||||||
|
<script type="text/javascript" src="/js/auto-complete.js?1522603726"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var baseurl = "https:\/\/lettre.github.io\/lettre\/";
|
|
||||||
|
var baseurl = "http:\/\/docs.lettre.at\/";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/search.js"></script>
|
<script type="text/javascript" src="/js/search.js?1522603726"></script>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="highlightable">
|
<div class="highlightable">
|
||||||
<ul class="topics">
|
<ul class="topics">
|
||||||
|
|
||||||
@@ -61,57 +72,44 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/" title="Getting started" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/getting-started/">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/">
|
|
||||||
<a href="/lettre/getting-started/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>1. </b>
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/intro/">
|
|
||||||
<a href="/lettre/getting-started/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/getting-started/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
@@ -125,86 +123,184 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/" title="Creating messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
<li class="dd-item " data-nav-id="/lettre/creating-messages/">
|
<a href="/creating-messages/">
|
||||||
<a href="/lettre/creating-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>2. </b>
|
|
||||||
|
|
||||||
Creating messages
|
Creating messages
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item parent" data-nav-id="/lettre/sending-messages/">
|
|
||||||
<a href="/lettre/sending-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>3. </b>
|
|
||||||
|
|
||||||
Sending messages
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/intro/">
|
|
||||||
<a href="/lettre/sending-messages/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/email/" title="Email creation" class="dd-item ">
|
||||||
|
<a href="/creating-messages/email/">
|
||||||
|
Email creation
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/smtp/">
|
|
||||||
<a href="/lettre/sending-messages/smtp/">
|
|
||||||
<span>SMTP transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/sendmail/">
|
|
||||||
<a href="/lettre/sending-messages/sendmail/">
|
|
||||||
<span>Sendmail transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item active" data-nav-id="/lettre/sending-messages/file/">
|
|
||||||
<a href="/lettre/sending-messages/file/">
|
|
||||||
<span>File transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/stub/">
|
|
||||||
<a href="/lettre/sending-messages/stub/">
|
|
||||||
<span>Stub transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/" title="Sending messages" class="dd-item
|
||||||
|
parent
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/sending-messages/">
|
||||||
|
Sending messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/sending-messages/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/smtp/" title="SMTP transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/smtp/">
|
||||||
|
SMTP transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/sendmail/" title="Sendmail transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/sendmail/">
|
||||||
|
Sendmail transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/file/" title="File transport" class="dd-item active">
|
||||||
|
<a href="/sending-messages/file/">
|
||||||
|
File transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/stub/" title="Stub transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/stub/">
|
||||||
|
Stub transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="footer">
|
<section id="footer">
|
||||||
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
||||||
@@ -213,11 +309,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="body">
|
<section id="body">
|
||||||
<div id="overlay"></div>
|
<div id="overlay"></div>
|
||||||
|
<div class="padding highlightable sticky-parent">
|
||||||
|
|
||||||
<div class="padding highlightable">
|
<div class="sticky-spacer">
|
||||||
|
|
||||||
<div id="top-bar">
|
<div id="top-bar">
|
||||||
|
|
||||||
|
|
||||||
@@ -231,6 +331,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
<span id="sidebar-toggle-span">
|
<span id="sidebar-toggle-span">
|
||||||
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
||||||
@@ -238,7 +339,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span id="toc-menu"><a href=""><i class="fa fa-list-alt"></i></a></span>
|
<span id="toc-menu"><i class="fa fa-list-alt"></i></span>
|
||||||
|
|
||||||
|
<span class="links">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -246,11 +349,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="/lettre/sending-messages/" itemprop="url"><span itemprop="title">Sending messages</span></a> <i class="fa fa-angle-right"></i>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<span itemprop="title"> File transport</span>
|
|
||||||
|
<a href='/'>Lettre site</a> > <a href='/sending-messages/'>Sending messages</a> > File transport
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="progress">
|
<div class="progress">
|
||||||
@@ -260,93 +370,61 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="body-inner">
|
<div id="body-inner">
|
||||||
|
|
||||||
<h1>File transport</h1>
|
<h1>File transport</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p>The file transport writes the emails to the given directory. The name of the file will be
|
<p>The file transport writes the emails to the given directory. The name of the file will be
|
||||||
<code>message_id.txt</code>.
|
<code>message_id.txt</code>.
|
||||||
It can be useful for testing purposes, or if you want to keep track of sent messages.</p>
|
It can be useful for testing purposes, or if you want to keep track of sent messages.</p>
|
||||||
use std::env::temp_dir;
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust" data-lang="rust"><span style="color:#66d9ef">extern</span> <span style="color:#66d9ef">crate</span> lettre;
|
||||||
|
|
||||||
use lettre::file::FileEmailTransport;
|
<span style="color:#66d9ef">use</span> std::env::temp_dir;
|
||||||
use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress};
|
|
||||||
|
|
||||||
// Write to the local temp directory
|
<span style="color:#66d9ef">use</span> lettre::file::FileEmailTransport;
|
||||||
let mut sender = FileEmailTransport::new(temp_dir());
|
<span style="color:#66d9ef">use</span> lettre::{SimpleSendableEmail, EmailTransport};
|
||||||
let email = SimpleSendableEmail::new(
|
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
|
||||||
"message_id".to_string(),
|
|
||||||
"Hello world".to_string(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let result = sender.send(&email);
|
<span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">main</span>() {
|
||||||
assert!(result.is_ok());
|
<span style="color:#75715e">// Write to the local temp directory
|
||||||
|
</span><span style="color:#75715e"></span> <span style="color:#66d9ef">let</span> <span style="color:#66d9ef">mut</span> sender <span style="color:#f92672">=</span> FileEmailTransport::new(temp_dir());
|
||||||
|
<span style="color:#66d9ef">let</span> email <span style="color:#f92672">=</span> SimpleSendableEmail::new(
|
||||||
|
<span style="color:#e6db74">"user@localhost"</span>.to_string(),
|
||||||
|
<span style="color:#f92672">&</span>[<span style="color:#e6db74">"root@localhost"</span>.to_string()],
|
||||||
|
<span style="color:#e6db74">"message_id"</span>.to_string(),
|
||||||
|
<span style="color:#e6db74">"Hello world"</span>.to_string(),
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
<span style="color:#66d9ef">let</span> result <span style="color:#f92672">=</span> sender.send(<span style="color:#f92672">&</span>email);
|
||||||
|
assert<span style="color:#f92672">!</span>(result.is_ok());
|
||||||
|
}</code></pre></div>
|
||||||
<p>Example result in <code>/tmp/b7c211bc-9811-45ce-8cd9-68eab575d695.txt</code>:</p>
|
<p>Example result in <code>/tmp/b7c211bc-9811-45ce-8cd9-68eab575d695.txt</code>:</p>
|
||||||
b7c211bc-9811-45ce-8cd9-68eab575d695: from=<user@localhost> to=<root@localhost>
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">b7c211bc-9811-45ce-8cd9-68eab575d695: from=<user@localhost> to=<root@localhost>
|
||||||
To: <root@localhost>
|
To: <root@localhost>
|
||||||
From: <user@localhost>
|
From: <user@localhost>
|
||||||
Subject: Hello
|
Subject: Hello
|
||||||
Date: Sat, 31 Oct 2015 13:42:19 +0100
|
Date: Sat, 31 Oct 2015 13:42:19 +0100
|
||||||
Message-ID: <b7c211bc-9811-45ce-8cd9-68eab575d695.lettre@localhost>
|
Message-ID: <b7c211bc-9811-45ce-8cd9-68eab575d695.lettre@localhost>
|
||||||
|
|
||||||
Hello World!
|
Hello World!</code></pre></div>
|
||||||
|
|
||||||
|
<footer class=" footline" >
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="navigation">
|
<div id="navigation">
|
||||||
|
|
||||||
|
|
||||||
@@ -368,12 +446,6 @@ Hello World!
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-prev" href="/lettre/sending-messages/sendmail/"> <i class="fa fa-chevron-left"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-next" href="/lettre/sending-messages/stub/" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -383,23 +455,203 @@ Hello World!
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-prev" href="/sending-messages/sendmail/" title="Sendmail transport"> <i class="fa fa-chevron-left"></i></a>
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-next" href="/sending-messages/stub/" title="Stub transport" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
||||||
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://lettre.github.io/lettre//js/clipboard.min.js"></script>
|
<script src="/js/clipboard.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.min.js"></script>
|
<script src="/js/perfect-scrollbar.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.jquery.min.js"></script>
|
<script src="/js/perfect-scrollbar.jquery.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery.sticky-kit.min.js"></script>
|
<script src="/js/jquery.sticky-kit.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/featherlight.min.js"></script>
|
<script src="/js/featherlight.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/html5shiv-printshiv.min.js"></script>
|
<script src="/js/html5shiv-printshiv.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/highlight.pack.js"></script>
|
<script src="/js/highlight.pack.js?1522603726"></script>
|
||||||
<script>hljs.initHighlightingOnLoad();</script>
|
<script>hljs.initHighlightingOnLoad();</script>
|
||||||
<script src="https://lettre.github.io/lettre//js/modernizr.custom.71422.js"></script>
|
<script src="/js/modernizr.custom.71422.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/learn.js"></script>
|
<script src="/js/learn.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/hugo-learn.js"></script>
|
<script src="/js/hugo-learn.js?1522603726"></script>
|
||||||
|
|
||||||
|
<link href="/mermaid/mermaid.css?1522603726" type="text/css" rel="stylesheet" />
|
||||||
|
<script src="/mermaid/mermaid.js?1522603726"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({ startOnLoad: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1,56 +1,66 @@
|
|||||||
|
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en" class="js csstransforms3d">
|
<html lang="en" class="js csstransforms3d">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
<meta name="generator" content="Hugo 0.20.7" />
|
<meta name="generator" content="Hugo 0.37.1" />
|
||||||
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
||||||
<meta name="author" content="Alexis Mousset">
|
<meta name="author" content="Alexis Mousset">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="https://lettre.github.io/lettre//images/favicon.png" type="image/x-icon" />
|
<link rel="shortcut icon" href="http://docs.lettre.at//images/favicon.png" type="image/x-icon" />
|
||||||
|
|
||||||
|
<title>Sending messages :: Lettre site</title>
|
||||||
|
|
||||||
|
|
||||||
<title>Sending messages</title>
|
<link href="/css/nucleus.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/nucleus.css" rel="stylesheet">
|
<link href="/css/font-awesome.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/font-awesome.min.css" rel="stylesheet">
|
<link href="/css/hybrid.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hybrid.css" rel="stylesheet">
|
<link href="/css/featherlight.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/featherlight.min.css" rel="stylesheet">
|
<link href="/css/perfect-scrollbar.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/perfect-scrollbar.min.css" rel="stylesheet">
|
<link href="/css/auto-complete.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/horsey.css" rel="stylesheet">
|
<link href="/css/theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/theme.css" rel="stylesheet">
|
<link href="/css/hugo-theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hugo-theme.css" rel="stylesheet">
|
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery-2.x.min.js"></script>
|
|
||||||
<style type="text/css">:root #header + #content > #left > #rlblock_left
|
|
||||||
{display:none !important;}</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/jquery-2.x.min.js?1522603726"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
:root #header + #content > #left > #rlblock_left{
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="" data-url="/lettre/sending-messages/">
|
<body class="" data-url="/sending-messages/">
|
||||||
|
<nav id="sidebar" class="">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<nav id="sidebar">
|
|
||||||
<div id="header-wrapper">
|
<div id="header-wrapper">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<a href="https://lettre.github.io/lettre//getting-started/intro/"><img src="https://lettre.github.io/lettre//images/logo50.png" /></a>
|
<a href="http://docs.lettre.at//getting-started/intro/"><img src="http://docs.lettre.at//images/logo50.png" /></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="searchbox">
|
<div class="searchbox">
|
||||||
<label for="search-by"><i class="fa fa-search"></i></label>
|
<label for="search-by"><i class="fa fa-search"></i></label>
|
||||||
<input data-search-input id="search-by" type="text" placeholder="Search">
|
<input data-search-input id="search-by" type="text" placeholder="Search...">
|
||||||
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/lunr.min.js"></script>
|
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/horsey.js"></script>
|
<script type="text/javascript" src="/js/lunr.min.js?1522603726"></script>
|
||||||
|
<script type="text/javascript" src="/js/auto-complete.js?1522603726"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var baseurl = "https:\/\/lettre.github.io\/lettre\/";
|
|
||||||
|
var baseurl = "http:\/\/docs.lettre.at\/";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/search.js"></script>
|
<script type="text/javascript" src="/js/search.js?1522603726"></script>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="highlightable">
|
<div class="highlightable">
|
||||||
<ul class="topics">
|
<ul class="topics">
|
||||||
|
|
||||||
@@ -62,57 +72,44 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/" title="Getting started" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/getting-started/">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/">
|
|
||||||
<a href="/lettre/getting-started/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>1. </b>
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/intro/">
|
|
||||||
<a href="/lettre/getting-started/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/getting-started/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
@@ -126,86 +123,184 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/" title="Creating messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
<li class="dd-item " data-nav-id="/lettre/creating-messages/">
|
<a href="/creating-messages/">
|
||||||
<a href="/lettre/creating-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>2. </b>
|
|
||||||
|
|
||||||
Creating messages
|
Creating messages
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item active parent" data-nav-id="/lettre/sending-messages/">
|
|
||||||
<a href="/lettre/sending-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>3. </b>
|
|
||||||
|
|
||||||
Sending messages
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/intro/">
|
|
||||||
<a href="/lettre/sending-messages/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/email/" title="Email creation" class="dd-item ">
|
||||||
|
<a href="/creating-messages/email/">
|
||||||
|
Email creation
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/smtp/">
|
|
||||||
<a href="/lettre/sending-messages/smtp/">
|
|
||||||
<span>SMTP transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/sendmail/">
|
|
||||||
<a href="/lettre/sending-messages/sendmail/">
|
|
||||||
<span>Sendmail transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/file/">
|
|
||||||
<a href="/lettre/sending-messages/file/">
|
|
||||||
<span>File transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/stub/">
|
|
||||||
<a href="/lettre/sending-messages/stub/">
|
|
||||||
<span>Stub transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/" title="Sending messages" class="dd-item
|
||||||
|
parent
|
||||||
|
active
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/sending-messages/">
|
||||||
|
Sending messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/sending-messages/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/smtp/" title="SMTP transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/smtp/">
|
||||||
|
SMTP transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/sendmail/" title="Sendmail transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/sendmail/">
|
||||||
|
Sendmail transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/file/" title="File transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/file/">
|
||||||
|
File transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/stub/" title="Stub transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/stub/">
|
||||||
|
Stub transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="footer">
|
<section id="footer">
|
||||||
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
||||||
@@ -214,13 +309,29 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="body">
|
<section id="body">
|
||||||
<div id="overlay"></div>
|
<div id="overlay"></div>
|
||||||
|
<div class="padding highlightable sticky-parent">
|
||||||
|
|
||||||
<div class="padding highlightable">
|
<div class="sticky-spacer">
|
||||||
|
|
||||||
<div id="top-bar">
|
<div id="top-bar">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="top-github-link">
|
||||||
|
<a class="github-link" href="https://github.com/lettre/lettre/edit/master/website/content/sending-messages/_index.md" target="blank">
|
||||||
|
<i class="fa fa-code-fork"></i>
|
||||||
|
Edit this page
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
<span id="sidebar-toggle-span">
|
<span id="sidebar-toggle-span">
|
||||||
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
||||||
@@ -228,6 +339,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
|
<span id="toc-menu"><i class="fa fa-list-alt"></i></span>
|
||||||
|
|
||||||
|
<span class="links">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -235,17 +349,43 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a href='/'>Lettre site</a> > Sending messages
|
||||||
|
|
||||||
<span itemprop="title"> Sending messages</span>
|
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="progress">
|
||||||
|
<div class="wrapper">
|
||||||
|
<nav id="TableOfContents">
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li>
|
||||||
|
<ul>
|
||||||
|
<li><a href="#sending-messages">Sending Messages</a></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul></li>
|
||||||
|
</ul>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div id="chapter">
|
|
||||||
|
|
||||||
<div id="body-inner">
|
<div id="body-inner">
|
||||||
|
|
||||||
|
<h1>Sending messages</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -254,55 +394,13 @@
|
|||||||
<p>This section explains how to manipulate emails you have created.</p>
|
<p>This section explains how to manipulate emails you have created.</p>
|
||||||
|
|
||||||
|
|
||||||
|
<footer class=" footline" >
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="navigation">
|
<div id="navigation">
|
||||||
|
|
||||||
@@ -317,12 +415,6 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-prev" href="/lettre/creating-messages/"> <i class="fa fa-chevron-left"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-next" href="/lettre/sending-messages/intro/" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -340,26 +432,200 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-prev" href="/creating-messages/email/" title="Email creation"> <i class="fa fa-chevron-left"></i></a>
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-next" href="/sending-messages/intro/" title="Introduction" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
||||||
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://lettre.github.io/lettre//js/clipboard.min.js"></script>
|
<script src="/js/clipboard.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.min.js"></script>
|
<script src="/js/perfect-scrollbar.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.jquery.min.js"></script>
|
<script src="/js/perfect-scrollbar.jquery.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery.sticky-kit.min.js"></script>
|
<script src="/js/jquery.sticky-kit.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/featherlight.min.js"></script>
|
<script src="/js/featherlight.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/html5shiv-printshiv.min.js"></script>
|
<script src="/js/html5shiv-printshiv.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/highlight.pack.js"></script>
|
<script src="/js/highlight.pack.js?1522603726"></script>
|
||||||
<script>hljs.initHighlightingOnLoad();</script>
|
<script>hljs.initHighlightingOnLoad();</script>
|
||||||
<script src="https://lettre.github.io/lettre//js/modernizr.custom.71422.js"></script>
|
<script src="/js/modernizr.custom.71422.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/learn.js"></script>
|
<script src="/js/learn.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/hugo-learn.js"></script>
|
<script src="/js/hugo-learn.js?1522603726"></script>
|
||||||
|
|
||||||
|
<link href="/mermaid/mermaid.css?1522603726" type="text/css" rel="stylesheet" />
|
||||||
|
<script src="/mermaid/mermaid.js?1522603726"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({ startOnLoad: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,67 +2,67 @@
|
|||||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
<channel>
|
<channel>
|
||||||
<title>Sending messages on Lettre site</title>
|
<title>Sending messages on Lettre site</title>
|
||||||
<link>https://lettre.github.io/lettre/sending-messages/</link>
|
<link>http://docs.lettre.at/sending-messages/</link>
|
||||||
<description>Recent content in Sending messages on Lettre site</description>
|
<description>Recent content in Sending messages on Lettre site</description>
|
||||||
<generator>Hugo -- gohugo.io</generator>
|
<generator>Hugo -- gohugo.io</generator>
|
||||||
<language>en-us</language>
|
<language>en-us</language>
|
||||||
<lastBuildDate>Sun, 21 May 2017 23:46:01 +0200</lastBuildDate>
|
<lastBuildDate>Sun, 21 May 2017 23:46:01 +0200</lastBuildDate>
|
||||||
|
|
||||||
<atom:link href="https://lettre.github.io/lettre/sending-messages/index.xml" rel="self" type="application/rss+xml" />
|
<atom:link href="http://docs.lettre.at/sending-messages/index.xml" rel="self" type="application/rss+xml" />
|
||||||
|
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>Introduction</title>
|
<title>Introduction</title>
|
||||||
<link>https://lettre.github.io/lettre/sending-messages/intro/</link>
|
<link>http://docs.lettre.at/sending-messages/intro/</link>
|
||||||
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
<guid>https://lettre.github.io/lettre/sending-messages/intro/</guid>
|
<guid>http://docs.lettre.at/sending-messages/intro/</guid>
|
||||||
<description>This mailer contains several different transports for your emails. To be sendable, the emails have to implement SendableEmail, which is the case for emails created with lettre_email.
|
<description>This mailer contains several different transports for your emails. To be sendable, the emails have to implement SendableEmail, which is the case for emails created with lettre_email.
|
||||||
The following transports are available:
|
The following transports are available:
|
||||||
The SmtpTransport uses the SMTP protocol to send the message over the network. It is the prefered way of sending emails. The SendmailTransport uses the sendmail command to send messages. It is an alternative to the SMTP transport.</description>
|
The SmtpTransport uses the SMTP protocol to send the message over the network. It is the preferred way of sending emails. The SendmailTransport uses the sendmail command to send messages. It is an alternative to the SMTP transport.</description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>SMTP transport</title>
|
<title>SMTP transport</title>
|
||||||
<link>https://lettre.github.io/lettre/sending-messages/smtp/</link>
|
<link>http://docs.lettre.at/sending-messages/smtp/</link>
|
||||||
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
<guid>https://lettre.github.io/lettre/sending-messages/smtp/</guid>
|
<guid>http://docs.lettre.at/sending-messages/smtp/</guid>
|
||||||
<description>This transport uses the SMTP protocol to send emails over the network (locally or remotely).
|
<description>This transport uses the SMTP protocol to send emails over the network (locally or remotely).
|
||||||
It is desinged to be:
|
It is designed to be:
|
||||||
Secured: email are encrypted by default Modern: Unicode support for email content and sender/recipient adresses when compatible Fast: supports tcp connection reuse This client is designed to send emails to a relay server, and should not be used to send emails directly to the destination.
|
Secured: email are encrypted by default Modern: Unicode support for email content and sender/recipient addresses when compatible Fast: supports tcp connection reuse This client is designed to send emails to a relay server, and should not be used to send emails directly to the destination.
|
||||||
The relay server can be the local email server, a specific host or a third-party service.</description>
|
The relay server can be the local email server, a specific host or a third-party service.</description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>Sendmail transport</title>
|
<title>Sendmail transport</title>
|
||||||
<link>https://lettre.github.io/lettre/sending-messages/sendmail/</link>
|
<link>http://docs.lettre.at/sending-messages/sendmail/</link>
|
||||||
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
<guid>https://lettre.github.io/lettre/sending-messages/sendmail/</guid>
|
<guid>http://docs.lettre.at/sending-messages/sendmail/</guid>
|
||||||
<description>The sendmail transport sends the email using the local sendmail command.
|
<description>The sendmail transport sends the email using the local sendmail command.
|
||||||
use lettre::sendmail::SendmailTransport; use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress}; let email = SimpleSendableEmail::new( EmailAddress::new("user@localhost".to_string()), vec![EmailAddress::new("root@localhost".to_string())], "message_id".to_string(), "Hello world".to_string(), ); let mut sender = SendmailTransport::new(); let result = sender.send(&email); assert!(result.is_ok()); </description>
|
extern crate lettre; use lettre::sendmail::SendmailTransport; use lettre::{SimpleSendableEmail, EmailTransport}; fn main() { let email = SimpleSendableEmail::new( &#34;user@localhost&#34;.to_string(), &amp;[&#34;root@localhost&#34;.to_string()], &#34;message_id&#34;.to_string(), &#34;Hello world&#34;.to_string(), ).unwrap(); let mut sender = SendmailTransport::new(); let result = sender.send(&amp;email); assert!(result.is_ok()); }</description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>File transport</title>
|
<title>File transport</title>
|
||||||
<link>https://lettre.github.io/lettre/sending-messages/file/</link>
|
<link>http://docs.lettre.at/sending-messages/file/</link>
|
||||||
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
<guid>https://lettre.github.io/lettre/sending-messages/file/</guid>
|
<guid>http://docs.lettre.at/sending-messages/file/</guid>
|
||||||
<description>The file transport writes the emails to the given directory. The name of the file will be message_id.txt. It can be useful for testing purposes, or if you want to keep track of sent messages.
|
<description>The file transport writes the emails to the given directory. The name of the file will be message_id.txt. It can be useful for testing purposes, or if you want to keep track of sent messages.
|
||||||
use std::env::temp_dir; use lettre::file::FileEmailTransport; use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress}; // Write to the local temp directory let mut sender = FileEmailTransport::new(temp_dir()); let email = SimpleSendableEmail::new( EmailAddress::new("user@localhost".to_string()), vec![EmailAddress::new("root@localhost".to_string())], "message_id".to_string(), "Hello world".to_string(), ); let result = sender.send(&email); assert!(result.is_ok()); Example result in /tmp/b7c211bc-9811-45ce-8cd9-68eab575d695.</description>
|
extern crate lettre; use std::env::temp_dir; use lettre::file::FileEmailTransport; use lettre::{SimpleSendableEmail, EmailTransport}; fn main() { // Write to the local temp directory let mut sender = FileEmailTransport::new(temp_dir()); let email = SimpleSendableEmail::new( &#34;user@localhost&#34;.to_string(), &amp;[&#34;root@localhost&#34;.to_string()], &#34;message_id&#34;.to_string(), &#34;Hello world&#34;.to_string(), ).</description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
<item>
|
<item>
|
||||||
<title>Stub transport</title>
|
<title>Stub transport</title>
|
||||||
<link>https://lettre.github.io/lettre/sending-messages/stub/</link>
|
<link>http://docs.lettre.at/sending-messages/stub/</link>
|
||||||
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
<pubDate>Sun, 21 May 2017 23:46:17 +0200</pubDate>
|
||||||
|
|
||||||
<guid>https://lettre.github.io/lettre/sending-messages/stub/</guid>
|
<guid>http://docs.lettre.at/sending-messages/stub/</guid>
|
||||||
<description>The stub transport only logs message envelope and drops the content. It can be useful for testing purposes.
|
<description>The stub transport only logs message envelope and drops the content. It can be useful for testing purposes.
|
||||||
use lettre::stub::StubEmailTransport; use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress}; let email = SimpleSendableEmail::new( EmailAddress::new("user@localhost".to_string()), vec![EmailAddress::new("root@localhost".to_string())], "message_id".to_string(), "Hello world".to_string(), ); let mut sender = StubEmailTransport::new_positive(); let result = sender.send(&email); assert!(result.is_ok()); Will log (when using a logger like env_logger):
|
extern crate lettre; use lettre::stub::StubEmailTransport; use lettre::{SimpleSendableEmail, EmailTransport}; fn main() { let email = SimpleSendableEmail::new( &#34;user@localhost&#34;.to_string(), &amp;[&#34;root@localhost&#34;.to_string()], &#34;message_id&#34;.to_string(), &#34;Hello world&#34;.to_string(), ).unwrap(); let mut sender = StubEmailTransport::new_positive(); let result = sender.send(&amp;email); assert!(result.is_ok()); } Will log (when using a logger like env_logger):
|
||||||
b7c211bc-9811-45ce-8cd9-68eab575d695: from= to= </description>
|
b7c211bc-9811-45ce-8cd9-68eab575d695: from=&lt;user@localhost&gt; to=&lt;root@localhost&gt;</description>
|
||||||
</item>
|
</item>
|
||||||
|
|
||||||
</channel>
|
</channel>
|
||||||
|
|||||||
@@ -3,53 +3,64 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
<meta name="generator" content="Hugo 0.20.7" />
|
<meta name="generator" content="Hugo 0.37.1" />
|
||||||
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
||||||
<meta name="author" content="Alexis Mousset">
|
<meta name="author" content="Alexis Mousset">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="https://lettre.github.io/lettre//images/favicon.png" type="image/x-icon" />
|
<link rel="shortcut icon" href="http://docs.lettre.at//images/favicon.png" type="image/x-icon" />
|
||||||
|
|
||||||
|
<title>Introduction :: Lettre site</title>
|
||||||
|
|
||||||
|
|
||||||
<title>Introduction</title>
|
<link href="/css/nucleus.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/nucleus.css" rel="stylesheet">
|
<link href="/css/font-awesome.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/font-awesome.min.css" rel="stylesheet">
|
<link href="/css/hybrid.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hybrid.css" rel="stylesheet">
|
<link href="/css/featherlight.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/featherlight.min.css" rel="stylesheet">
|
<link href="/css/perfect-scrollbar.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/perfect-scrollbar.min.css" rel="stylesheet">
|
<link href="/css/auto-complete.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/horsey.css" rel="stylesheet">
|
<link href="/css/theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/theme.css" rel="stylesheet">
|
<link href="/css/hugo-theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hugo-theme.css" rel="stylesheet">
|
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery-2.x.min.js"></script>
|
|
||||||
<style type="text/css">:root #header + #content > #left > #rlblock_left
|
|
||||||
{display:none !important;}</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/jquery-2.x.min.js?1522603726"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
:root #header + #content > #left > #rlblock_left{
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="" data-url="/lettre/sending-messages/intro/">
|
<body class="" data-url="/sending-messages/intro/">
|
||||||
|
<nav id="sidebar" class="">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<nav id="sidebar">
|
|
||||||
<div id="header-wrapper">
|
<div id="header-wrapper">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<a href="https://lettre.github.io/lettre//getting-started/intro/"><img src="https://lettre.github.io/lettre//images/logo50.png" /></a>
|
<a href="http://docs.lettre.at//getting-started/intro/"><img src="http://docs.lettre.at//images/logo50.png" /></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="searchbox">
|
<div class="searchbox">
|
||||||
<label for="search-by"><i class="fa fa-search"></i></label>
|
<label for="search-by"><i class="fa fa-search"></i></label>
|
||||||
<input data-search-input id="search-by" type="text" placeholder="Search">
|
<input data-search-input id="search-by" type="text" placeholder="Search...">
|
||||||
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/lunr.min.js"></script>
|
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/horsey.js"></script>
|
<script type="text/javascript" src="/js/lunr.min.js?1522603726"></script>
|
||||||
|
<script type="text/javascript" src="/js/auto-complete.js?1522603726"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var baseurl = "https:\/\/lettre.github.io\/lettre\/";
|
|
||||||
|
var baseurl = "http:\/\/docs.lettre.at\/";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/search.js"></script>
|
<script type="text/javascript" src="/js/search.js?1522603726"></script>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="highlightable">
|
<div class="highlightable">
|
||||||
<ul class="topics">
|
<ul class="topics">
|
||||||
|
|
||||||
@@ -61,57 +72,44 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/" title="Getting started" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/getting-started/">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/">
|
|
||||||
<a href="/lettre/getting-started/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>1. </b>
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/intro/">
|
|
||||||
<a href="/lettre/getting-started/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/getting-started/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
@@ -125,86 +123,184 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/" title="Creating messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
<li class="dd-item " data-nav-id="/lettre/creating-messages/">
|
<a href="/creating-messages/">
|
||||||
<a href="/lettre/creating-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>2. </b>
|
|
||||||
|
|
||||||
Creating messages
|
Creating messages
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item parent" data-nav-id="/lettre/sending-messages/">
|
|
||||||
<a href="/lettre/sending-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>3. </b>
|
|
||||||
|
|
||||||
Sending messages
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item active" data-nav-id="/lettre/sending-messages/intro/">
|
|
||||||
<a href="/lettre/sending-messages/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/email/" title="Email creation" class="dd-item ">
|
||||||
|
<a href="/creating-messages/email/">
|
||||||
|
Email creation
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/smtp/">
|
|
||||||
<a href="/lettre/sending-messages/smtp/">
|
|
||||||
<span>SMTP transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/sendmail/">
|
|
||||||
<a href="/lettre/sending-messages/sendmail/">
|
|
||||||
<span>Sendmail transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/file/">
|
|
||||||
<a href="/lettre/sending-messages/file/">
|
|
||||||
<span>File transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/stub/">
|
|
||||||
<a href="/lettre/sending-messages/stub/">
|
|
||||||
<span>Stub transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/" title="Sending messages" class="dd-item
|
||||||
|
parent
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/sending-messages/">
|
||||||
|
Sending messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/intro/" title="Introduction" class="dd-item active">
|
||||||
|
<a href="/sending-messages/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/smtp/" title="SMTP transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/smtp/">
|
||||||
|
SMTP transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/sendmail/" title="Sendmail transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/sendmail/">
|
||||||
|
Sendmail transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/file/" title="File transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/file/">
|
||||||
|
File transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/stub/" title="Stub transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/stub/">
|
||||||
|
Stub transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="footer">
|
<section id="footer">
|
||||||
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
||||||
@@ -213,11 +309,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="body">
|
<section id="body">
|
||||||
<div id="overlay"></div>
|
<div id="overlay"></div>
|
||||||
|
<div class="padding highlightable sticky-parent">
|
||||||
|
|
||||||
<div class="padding highlightable">
|
<div class="sticky-spacer">
|
||||||
|
|
||||||
<div id="top-bar">
|
<div id="top-bar">
|
||||||
|
|
||||||
|
|
||||||
@@ -231,6 +331,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
<span id="sidebar-toggle-span">
|
<span id="sidebar-toggle-span">
|
||||||
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
||||||
@@ -238,7 +339,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span id="toc-menu"><a href=""><i class="fa fa-list-alt"></i></a></span>
|
<span id="toc-menu"><i class="fa fa-list-alt"></i></span>
|
||||||
|
|
||||||
|
<span class="links">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -246,11 +349,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="/lettre/sending-messages/" itemprop="url"><span itemprop="title">Sending messages</span></a> <i class="fa fa-angle-right"></i>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<span itemprop="title"> Introduction</span>
|
|
||||||
|
<a href='/'>Lettre site</a> > <a href='/sending-messages/'>Sending messages</a> > Introduction
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="progress">
|
<div class="progress">
|
||||||
@@ -260,14 +370,19 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="body-inner">
|
<div id="body-inner">
|
||||||
|
|
||||||
<h1>Introduction</h1>
|
<h1>Introduction</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p>This mailer contains several different transports for your emails. To be sendable, the
|
<p>This mailer contains several different transports for your emails. To be sendable, the
|
||||||
emails have to implement <code>SendableEmail</code>, which is the case for emails created with <code>lettre_email</code>.</p>
|
emails have to implement <code>SendableEmail</code>, which is the case for emails created with <code>lettre_email</code>.</p>
|
||||||
|
|
||||||
@@ -275,7 +390,7 @@ emails have to implement <code>SendableEmail</code>, which is the case for email
|
|||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>The <code>SmtpTransport</code> uses the SMTP protocol to send the message over the network. It is
|
<li>The <code>SmtpTransport</code> uses the SMTP protocol to send the message over the network. It is
|
||||||
the prefered way of sending emails.</li>
|
the preferred way of sending emails.</li>
|
||||||
<li>The <code>SendmailTransport</code> uses the sendmail command to send messages. It is an alternative to
|
<li>The <code>SendmailTransport</code> uses the sendmail command to send messages. It is an alternative to
|
||||||
the SMTP transport.</li>
|
the SMTP transport.</li>
|
||||||
<li>The <code>FileTransport</code> creates a file containing the email content to be sent. It can be used
|
<li>The <code>FileTransport</code> creates a file containing the email content to be sent. It can be used
|
||||||
@@ -285,54 +400,15 @@ logs.</li>
|
|||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
<footer class=" footline" >
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="navigation">
|
<div id="navigation">
|
||||||
|
|
||||||
|
|
||||||
@@ -348,12 +424,6 @@ logs.</li>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-prev" href="/lettre/sending-messages/"> <i class="fa fa-chevron-left"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-next" href="/lettre/sending-messages/smtp/" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -369,23 +439,200 @@ logs.</li>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-prev" href="/sending-messages/" title="Sending messages"> <i class="fa fa-chevron-left"></i></a>
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-next" href="/sending-messages/smtp/" title="SMTP transport" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
||||||
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://lettre.github.io/lettre//js/clipboard.min.js"></script>
|
<script src="/js/clipboard.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.min.js"></script>
|
<script src="/js/perfect-scrollbar.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.jquery.min.js"></script>
|
<script src="/js/perfect-scrollbar.jquery.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery.sticky-kit.min.js"></script>
|
<script src="/js/jquery.sticky-kit.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/featherlight.min.js"></script>
|
<script src="/js/featherlight.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/html5shiv-printshiv.min.js"></script>
|
<script src="/js/html5shiv-printshiv.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/highlight.pack.js"></script>
|
<script src="/js/highlight.pack.js?1522603726"></script>
|
||||||
<script>hljs.initHighlightingOnLoad();</script>
|
<script>hljs.initHighlightingOnLoad();</script>
|
||||||
<script src="https://lettre.github.io/lettre//js/modernizr.custom.71422.js"></script>
|
<script src="/js/modernizr.custom.71422.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/learn.js"></script>
|
<script src="/js/learn.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/hugo-learn.js"></script>
|
<script src="/js/hugo-learn.js?1522603726"></script>
|
||||||
|
|
||||||
|
<link href="/mermaid/mermaid.css?1522603726" type="text/css" rel="stylesheet" />
|
||||||
|
<script src="/mermaid/mermaid.js?1522603726"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({ startOnLoad: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -3,53 +3,64 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
<meta name="generator" content="Hugo 0.20.7" />
|
<meta name="generator" content="Hugo 0.37.1" />
|
||||||
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
||||||
<meta name="author" content="Alexis Mousset">
|
<meta name="author" content="Alexis Mousset">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="https://lettre.github.io/lettre//images/favicon.png" type="image/x-icon" />
|
<link rel="shortcut icon" href="http://docs.lettre.at//images/favicon.png" type="image/x-icon" />
|
||||||
|
|
||||||
|
<title>Sendmail transport :: Lettre site</title>
|
||||||
|
|
||||||
|
|
||||||
<title>Sendmail transport</title>
|
<link href="/css/nucleus.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/nucleus.css" rel="stylesheet">
|
<link href="/css/font-awesome.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/font-awesome.min.css" rel="stylesheet">
|
<link href="/css/hybrid.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hybrid.css" rel="stylesheet">
|
<link href="/css/featherlight.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/featherlight.min.css" rel="stylesheet">
|
<link href="/css/perfect-scrollbar.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/perfect-scrollbar.min.css" rel="stylesheet">
|
<link href="/css/auto-complete.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/horsey.css" rel="stylesheet">
|
<link href="/css/theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/theme.css" rel="stylesheet">
|
<link href="/css/hugo-theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hugo-theme.css" rel="stylesheet">
|
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery-2.x.min.js"></script>
|
|
||||||
<style type="text/css">:root #header + #content > #left > #rlblock_left
|
|
||||||
{display:none !important;}</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/jquery-2.x.min.js?1522603726"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
:root #header + #content > #left > #rlblock_left{
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="" data-url="/lettre/sending-messages/sendmail/">
|
<body class="" data-url="/sending-messages/sendmail/">
|
||||||
|
<nav id="sidebar" class="">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<nav id="sidebar">
|
|
||||||
<div id="header-wrapper">
|
<div id="header-wrapper">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<a href="https://lettre.github.io/lettre//getting-started/intro/"><img src="https://lettre.github.io/lettre//images/logo50.png" /></a>
|
<a href="http://docs.lettre.at//getting-started/intro/"><img src="http://docs.lettre.at//images/logo50.png" /></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="searchbox">
|
<div class="searchbox">
|
||||||
<label for="search-by"><i class="fa fa-search"></i></label>
|
<label for="search-by"><i class="fa fa-search"></i></label>
|
||||||
<input data-search-input id="search-by" type="text" placeholder="Search">
|
<input data-search-input id="search-by" type="text" placeholder="Search...">
|
||||||
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/lunr.min.js"></script>
|
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/horsey.js"></script>
|
<script type="text/javascript" src="/js/lunr.min.js?1522603726"></script>
|
||||||
|
<script type="text/javascript" src="/js/auto-complete.js?1522603726"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var baseurl = "https:\/\/lettre.github.io\/lettre\/";
|
|
||||||
|
var baseurl = "http:\/\/docs.lettre.at\/";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/search.js"></script>
|
<script type="text/javascript" src="/js/search.js?1522603726"></script>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="highlightable">
|
<div class="highlightable">
|
||||||
<ul class="topics">
|
<ul class="topics">
|
||||||
|
|
||||||
@@ -61,57 +72,44 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/" title="Getting started" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/getting-started/">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/">
|
|
||||||
<a href="/lettre/getting-started/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>1. </b>
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/intro/">
|
|
||||||
<a href="/lettre/getting-started/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/getting-started/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
@@ -125,86 +123,184 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/" title="Creating messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
<li class="dd-item " data-nav-id="/lettre/creating-messages/">
|
<a href="/creating-messages/">
|
||||||
<a href="/lettre/creating-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>2. </b>
|
|
||||||
|
|
||||||
Creating messages
|
Creating messages
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item parent" data-nav-id="/lettre/sending-messages/">
|
|
||||||
<a href="/lettre/sending-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>3. </b>
|
|
||||||
|
|
||||||
Sending messages
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/intro/">
|
|
||||||
<a href="/lettre/sending-messages/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/email/" title="Email creation" class="dd-item ">
|
||||||
|
<a href="/creating-messages/email/">
|
||||||
|
Email creation
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/smtp/">
|
|
||||||
<a href="/lettre/sending-messages/smtp/">
|
|
||||||
<span>SMTP transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item active" data-nav-id="/lettre/sending-messages/sendmail/">
|
|
||||||
<a href="/lettre/sending-messages/sendmail/">
|
|
||||||
<span>Sendmail transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/file/">
|
|
||||||
<a href="/lettre/sending-messages/file/">
|
|
||||||
<span>File transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/stub/">
|
|
||||||
<a href="/lettre/sending-messages/stub/">
|
|
||||||
<span>Stub transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/" title="Sending messages" class="dd-item
|
||||||
|
parent
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/sending-messages/">
|
||||||
|
Sending messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/sending-messages/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/smtp/" title="SMTP transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/smtp/">
|
||||||
|
SMTP transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/sendmail/" title="Sendmail transport" class="dd-item active">
|
||||||
|
<a href="/sending-messages/sendmail/">
|
||||||
|
Sendmail transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/file/" title="File transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/file/">
|
||||||
|
File transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/stub/" title="Stub transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/stub/">
|
||||||
|
Stub transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="footer">
|
<section id="footer">
|
||||||
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
||||||
@@ -213,11 +309,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="body">
|
<section id="body">
|
||||||
<div id="overlay"></div>
|
<div id="overlay"></div>
|
||||||
|
<div class="padding highlightable sticky-parent">
|
||||||
|
|
||||||
<div class="padding highlightable">
|
<div class="sticky-spacer">
|
||||||
|
|
||||||
<div id="top-bar">
|
<div id="top-bar">
|
||||||
|
|
||||||
|
|
||||||
@@ -231,6 +331,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
<span id="sidebar-toggle-span">
|
<span id="sidebar-toggle-span">
|
||||||
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
||||||
@@ -238,7 +339,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span id="toc-menu"><a href=""><i class="fa fa-list-alt"></i></a></span>
|
<span id="toc-menu"><i class="fa fa-list-alt"></i></span>
|
||||||
|
|
||||||
|
<span class="links">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -246,11 +349,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="/lettre/sending-messages/" itemprop="url"><span itemprop="title">Sending messages</span></a> <i class="fa fa-angle-right"></i>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<span itemprop="title"> Sendmail transport</span>
|
|
||||||
|
<a href='/'>Lettre site</a> > <a href='/sending-messages/'>Sending messages</a> > Sendmail transport
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="progress">
|
<div class="progress">
|
||||||
@@ -260,78 +370,47 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="body-inner">
|
<div id="body-inner">
|
||||||
|
|
||||||
<h1>Sendmail transport</h1>
|
<h1>Sendmail transport</h1>
|
||||||
|
|
||||||
|
|
||||||
<p>The sendmail transport sends the email using the local sendmail command.</p>
|
|
||||||
use lettre::sendmail::SendmailTransport;
|
|
||||||
use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress};
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<p>The sendmail transport sends the email using the local sendmail command.</p>
|
||||||
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust,no_run" data-lang="rust,no_run">extern crate lettre;
|
||||||
|
|
||||||
|
use lettre::sendmail::SendmailTransport;
|
||||||
|
use lettre::{SimpleSendableEmail, EmailTransport};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
let email = SimpleSendableEmail::new(
|
let email = SimpleSendableEmail::new(
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
"user@localhost".to_string(),
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
&["root@localhost".to_string()],
|
||||||
"message_id".to_string(),
|
"message_id".to_string(),
|
||||||
"Hello world".to_string(),
|
"Hello world".to_string(),
|
||||||
);
|
).unwrap();
|
||||||
|
|
||||||
let mut sender = SendmailTransport::new();
|
let mut sender = SendmailTransport::new();
|
||||||
let result = sender.send(&email);
|
let result = sender.send(&email);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
}</code></pre></div>
|
||||||
|
|
||||||
|
<footer class=" footline" >
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="navigation">
|
<div id="navigation">
|
||||||
|
|
||||||
|
|
||||||
@@ -351,12 +430,6 @@ assert!(result.is_ok());
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-prev" href="/lettre/sending-messages/smtp/"> <i class="fa fa-chevron-left"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-next" href="/lettre/sending-messages/file/" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -368,23 +441,203 @@ assert!(result.is_ok());
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-prev" href="/sending-messages/smtp/" title="SMTP transport"> <i class="fa fa-chevron-left"></i></a>
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-next" href="/sending-messages/file/" title="File transport" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
||||||
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://lettre.github.io/lettre//js/clipboard.min.js"></script>
|
<script src="/js/clipboard.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.min.js"></script>
|
<script src="/js/perfect-scrollbar.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.jquery.min.js"></script>
|
<script src="/js/perfect-scrollbar.jquery.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery.sticky-kit.min.js"></script>
|
<script src="/js/jquery.sticky-kit.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/featherlight.min.js"></script>
|
<script src="/js/featherlight.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/html5shiv-printshiv.min.js"></script>
|
<script src="/js/html5shiv-printshiv.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/highlight.pack.js"></script>
|
<script src="/js/highlight.pack.js?1522603726"></script>
|
||||||
<script>hljs.initHighlightingOnLoad();</script>
|
<script>hljs.initHighlightingOnLoad();</script>
|
||||||
<script src="https://lettre.github.io/lettre//js/modernizr.custom.71422.js"></script>
|
<script src="/js/modernizr.custom.71422.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/learn.js"></script>
|
<script src="/js/learn.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/hugo-learn.js"></script>
|
<script src="/js/hugo-learn.js?1522603726"></script>
|
||||||
|
|
||||||
|
<link href="/mermaid/mermaid.css?1522603726" type="text/css" rel="stylesheet" />
|
||||||
|
<script src="/mermaid/mermaid.js?1522603726"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({ startOnLoad: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -3,53 +3,64 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
<meta name="generator" content="Hugo 0.20.7" />
|
<meta name="generator" content="Hugo 0.37.1" />
|
||||||
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
||||||
<meta name="author" content="Alexis Mousset">
|
<meta name="author" content="Alexis Mousset">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="https://lettre.github.io/lettre//images/favicon.png" type="image/x-icon" />
|
<link rel="shortcut icon" href="http://docs.lettre.at//images/favicon.png" type="image/x-icon" />
|
||||||
|
|
||||||
|
<title>SMTP transport :: Lettre site</title>
|
||||||
|
|
||||||
|
|
||||||
<title>SMTP transport</title>
|
<link href="/css/nucleus.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/nucleus.css" rel="stylesheet">
|
<link href="/css/font-awesome.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/font-awesome.min.css" rel="stylesheet">
|
<link href="/css/hybrid.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hybrid.css" rel="stylesheet">
|
<link href="/css/featherlight.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/featherlight.min.css" rel="stylesheet">
|
<link href="/css/perfect-scrollbar.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/perfect-scrollbar.min.css" rel="stylesheet">
|
<link href="/css/auto-complete.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/horsey.css" rel="stylesheet">
|
<link href="/css/theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/theme.css" rel="stylesheet">
|
<link href="/css/hugo-theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hugo-theme.css" rel="stylesheet">
|
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery-2.x.min.js"></script>
|
|
||||||
<style type="text/css">:root #header + #content > #left > #rlblock_left
|
|
||||||
{display:none !important;}</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/jquery-2.x.min.js?1522603726"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
:root #header + #content > #left > #rlblock_left{
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="" data-url="/lettre/sending-messages/smtp/">
|
<body class="" data-url="/sending-messages/smtp/">
|
||||||
|
<nav id="sidebar" class="">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<nav id="sidebar">
|
|
||||||
<div id="header-wrapper">
|
<div id="header-wrapper">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<a href="https://lettre.github.io/lettre//getting-started/intro/"><img src="https://lettre.github.io/lettre//images/logo50.png" /></a>
|
<a href="http://docs.lettre.at//getting-started/intro/"><img src="http://docs.lettre.at//images/logo50.png" /></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="searchbox">
|
<div class="searchbox">
|
||||||
<label for="search-by"><i class="fa fa-search"></i></label>
|
<label for="search-by"><i class="fa fa-search"></i></label>
|
||||||
<input data-search-input id="search-by" type="text" placeholder="Search">
|
<input data-search-input id="search-by" type="text" placeholder="Search...">
|
||||||
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/lunr.min.js"></script>
|
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/horsey.js"></script>
|
<script type="text/javascript" src="/js/lunr.min.js?1522603726"></script>
|
||||||
|
<script type="text/javascript" src="/js/auto-complete.js?1522603726"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var baseurl = "https:\/\/lettre.github.io\/lettre\/";
|
|
||||||
|
var baseurl = "http:\/\/docs.lettre.at\/";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/search.js"></script>
|
<script type="text/javascript" src="/js/search.js?1522603726"></script>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="highlightable">
|
<div class="highlightable">
|
||||||
<ul class="topics">
|
<ul class="topics">
|
||||||
|
|
||||||
@@ -61,57 +72,44 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/" title="Getting started" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/getting-started/">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/">
|
|
||||||
<a href="/lettre/getting-started/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>1. </b>
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/intro/">
|
|
||||||
<a href="/lettre/getting-started/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/getting-started/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
@@ -125,86 +123,184 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/" title="Creating messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
<li class="dd-item " data-nav-id="/lettre/creating-messages/">
|
<a href="/creating-messages/">
|
||||||
<a href="/lettre/creating-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>2. </b>
|
|
||||||
|
|
||||||
Creating messages
|
Creating messages
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item parent" data-nav-id="/lettre/sending-messages/">
|
|
||||||
<a href="/lettre/sending-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>3. </b>
|
|
||||||
|
|
||||||
Sending messages
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/intro/">
|
|
||||||
<a href="/lettre/sending-messages/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/email/" title="Email creation" class="dd-item ">
|
||||||
|
<a href="/creating-messages/email/">
|
||||||
|
Email creation
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="dd-item active" data-nav-id="/lettre/sending-messages/smtp/">
|
|
||||||
<a href="/lettre/sending-messages/smtp/">
|
|
||||||
<span>SMTP transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/sendmail/">
|
|
||||||
<a href="/lettre/sending-messages/sendmail/">
|
|
||||||
<span>Sendmail transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/file/">
|
|
||||||
<a href="/lettre/sending-messages/file/">
|
|
||||||
<span>File transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/stub/">
|
|
||||||
<a href="/lettre/sending-messages/stub/">
|
|
||||||
<span>Stub transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/" title="Sending messages" class="dd-item
|
||||||
|
parent
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/sending-messages/">
|
||||||
|
Sending messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/sending-messages/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/smtp/" title="SMTP transport" class="dd-item active">
|
||||||
|
<a href="/sending-messages/smtp/">
|
||||||
|
SMTP transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/sendmail/" title="Sendmail transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/sendmail/">
|
||||||
|
Sendmail transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/file/" title="File transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/file/">
|
||||||
|
File transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/stub/" title="Stub transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/stub/">
|
||||||
|
Stub transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="footer">
|
<section id="footer">
|
||||||
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
||||||
@@ -213,11 +309,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="body">
|
<section id="body">
|
||||||
<div id="overlay"></div>
|
<div id="overlay"></div>
|
||||||
|
<div class="padding highlightable sticky-parent">
|
||||||
|
|
||||||
<div class="padding highlightable">
|
<div class="sticky-spacer">
|
||||||
|
|
||||||
<div id="top-bar">
|
<div id="top-bar">
|
||||||
|
|
||||||
|
|
||||||
@@ -231,6 +331,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
<span id="sidebar-toggle-span">
|
<span id="sidebar-toggle-span">
|
||||||
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
||||||
@@ -238,7 +339,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span id="toc-menu"><a href=""><i class="fa fa-list-alt"></i></a></span>
|
<span id="toc-menu"><i class="fa fa-list-alt"></i></span>
|
||||||
|
|
||||||
|
<span class="links">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -246,11 +349,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="/lettre/sending-messages/" itemprop="url"><span itemprop="title">Sending messages</span></a> <i class="fa fa-angle-right"></i>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<span itemprop="title"> SMTP transport</span>
|
|
||||||
|
<a href='/'>Lettre site</a> > <a href='/sending-messages/'>Sending messages</a> > SMTP transport
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="progress">
|
<div class="progress">
|
||||||
@@ -275,8 +385,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="body-inner">
|
<div id="body-inner">
|
||||||
|
|
||||||
@@ -285,13 +397,16 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p>This transport uses the SMTP protocol to send emails over the network (locally or remotely).</p>
|
<p>This transport uses the SMTP protocol to send emails over the network (locally or remotely).</p>
|
||||||
|
|
||||||
<p>It is desinged to be:</p>
|
<p>It is designed to be:</p>
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
<li>Secured: email are encrypted by default</li>
|
<li>Secured: email are encrypted by default</li>
|
||||||
<li>Modern: Unicode support for email content and sender/recipient adresses when compatible</li>
|
<li>Modern: Unicode support for email content and sender/recipient addresses when compatible</li>
|
||||||
<li>Fast: supports tcp connection reuse</li>
|
<li>Fast: supports tcp connection reuse</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
@@ -303,44 +418,48 @@ emails directly to the destination.</p>
|
|||||||
<h4 id="simple-example">Simple example</h4>
|
<h4 id="simple-example">Simple example</h4>
|
||||||
|
|
||||||
<p>This is the most basic example of usage:</p>
|
<p>This is the most basic example of usage:</p>
|
||||||
use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress, SmtpTransport};
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust,no_run" data-lang="rust,no_run">extern crate lettre;
|
||||||
|
|
||||||
|
use lettre::{SimpleSendableEmail, EmailTransport, SmtpTransport};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
let email = SimpleSendableEmail::new(
|
let email = SimpleSendableEmail::new(
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
"user@localhost".to_string(),
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
&["root@localhost".to_string()],
|
||||||
"message_id".to_string(),
|
"message_id".to_string(),
|
||||||
"Hello world".to_string(),
|
"Hello world".to_string(),
|
||||||
);
|
).unwrap();
|
||||||
|
|
||||||
// Open a local connection on port 25
|
// Open a local connection on port 25
|
||||||
let mut mailer =
|
let mut mailer =
|
||||||
SmtpTransport::builder_unencrypted_localhost().unwrap().build();
|
SmtpTransport::builder_unencrypted_localhost().unwrap().build();
|
||||||
// Send the email
|
// Send the email
|
||||||
let result = mailer.send(&email);
|
let result = mailer.send(&email);
|
||||||
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
}</code></pre></div>
|
||||||
<h4 id="complete-example">Complete example</h4>
|
<h4 id="complete-example">Complete example</h4>
|
||||||
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust,no_run" data-lang="rust,no_run">extern crate lettre;
|
||||||
|
|
||||||
use lettre::smtp::authentication::{Credentials, Mechanism};
|
use lettre::smtp::authentication::{Credentials, Mechanism};
|
||||||
use lettre::smtp::SUBMISSION_PORT;
|
use lettre::{SimpleSendableEmail, EmailTransport, SmtpTransport};
|
||||||
use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress, SmtpTransport};
|
|
||||||
use lettre::smtp::extension::ClientId;
|
use lettre::smtp::extension::ClientId;
|
||||||
use lettre::smtp::ConnectionReuseParameters;
|
use lettre::smtp::ConnectionReuseParameters;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
let email = SimpleSendableEmail::new(
|
let email = SimpleSendableEmail::new(
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
"user@localhost".to_string(),
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
&["root@localhost".to_string()],
|
||||||
"message_id".to_string(),
|
"message_id".to_string(),
|
||||||
"Hello world".to_string(),
|
"Hello world".to_string(),
|
||||||
);
|
).unwrap();
|
||||||
|
|
||||||
// Connect to a remote server on a custom port
|
// Connect to a remote server on a custom port
|
||||||
let mut mailer = SmtpTransport::simple_builder("server.tld".to_string()).unwrap()
|
let mut mailer = SmtpTransport::simple_builder("server.tld").unwrap()
|
||||||
// Set the name sent during EHLO/HELO, default is `localhost`
|
// Set the name sent during EHLO/HELO, default is `localhost`
|
||||||
.hello_name(ClientId::Domain("my.hostname.tld".to_string()))
|
.hello_name(ClientId::Domain("my.hostname.tld".to_string()))
|
||||||
// Add credentials for authentication
|
// Add credentials for authentication
|
||||||
.credentials(Credentials::new("username".to_string(), "password".to_string()))
|
.credentials(Credentials::new("username".to_string(), "password".to_string()))
|
||||||
// Enable SMTPUTF8 if the server supports it
|
// Enable SMTPUTF8 if the server supports it
|
||||||
.smtp_utf8(true)
|
.smtp_utf8(true)
|
||||||
// Configure expected authentication mechanism
|
// Configure expected authentication mechanism
|
||||||
@@ -348,20 +467,22 @@ let mut mailer = SmtpTransport::simple_builder("server.tld".to_string()).unwrap(
|
|||||||
// Enable connection reuse
|
// Enable connection reuse
|
||||||
.connection_reuse(ConnectionReuseParameters::ReuseUnlimited).build();
|
.connection_reuse(ConnectionReuseParameters::ReuseUnlimited).build();
|
||||||
|
|
||||||
let result_1 = mailer.send(&email);
|
let result_1 = mailer.send(&email);
|
||||||
assert!(result_1.is_ok());
|
assert!(result_1.is_ok());
|
||||||
|
|
||||||
// The second email will use the same connection
|
// The second email will use the same connection
|
||||||
let result_2 = mailer.send(&email);
|
let result_2 = mailer.send(&email);
|
||||||
assert!(result_2.is_ok());
|
assert!(result_2.is_ok());
|
||||||
|
|
||||||
// Explicitly close the SMTP transaction as we enabled connection reuse
|
// Explicitly close the SMTP transaction as we enabled connection reuse
|
||||||
mailer.close();
|
mailer.close();
|
||||||
|
}</code></pre></div>
|
||||||
<h4 id="lower-level">Lower level</h4>
|
<h4 id="lower-level">Lower level</h4>
|
||||||
|
|
||||||
<p>You can also send commands, here is a simple email transaction without
|
<p>You can also send commands, here is a simple email transaction without
|
||||||
error handling:</p>
|
error handling:</p>
|
||||||
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust,no_run" data-lang="rust,no_run">extern crate lettre;
|
||||||
|
|
||||||
use lettre::EmailAddress;
|
use lettre::EmailAddress;
|
||||||
use lettre::smtp::SMTP_PORT;
|
use lettre::smtp::SMTP_PORT;
|
||||||
use lettre::smtp::client::Client;
|
use lettre::smtp::client::Client;
|
||||||
@@ -369,68 +490,30 @@ use lettre::smtp::client::net::NetworkStream;
|
|||||||
use lettre::smtp::extension::ClientId;
|
use lettre::smtp::extension::ClientId;
|
||||||
use lettre::smtp::commands::*;
|
use lettre::smtp::commands::*;
|
||||||
|
|
||||||
let mut email_client: Client<NetworkStream> = Client::new();
|
fn main() {
|
||||||
let _ = email_client.connect(&("localhost", SMTP_PORT), None);
|
let mut email_client: Client<NetworkStream> = Client::new();
|
||||||
let _ = email_client.smtp_command(EhloCommand::new(ClientId::new("my_hostname".to_string())));
|
let _ = email_client.connect(&("localhost", SMTP_PORT), None);
|
||||||
let _ = email_client.smtp_command(
|
let _ = email_client.command(EhloCommand::new(ClientId::new("my_hostname".to_string())));
|
||||||
MailCommand::new(Some(EmailAddress::new("user@example.com".to_string())), vec![])
|
let _ = email_client.command(
|
||||||
|
MailCommand::new(Some(EmailAddress::new("user@example.com".to_string()).unwrap()), vec![])
|
||||||
);
|
);
|
||||||
let _ = email_client.smtp_command(
|
let _ = email_client.command(
|
||||||
RcptCommand::new(EmailAddress::new("user@example.org".to_string()), vec![])
|
RcptCommand::new(EmailAddress::new("user@example.org".to_string()).unwrap(), vec![])
|
||||||
);
|
);
|
||||||
let _ = email_client.smtp_command(DataCommand);
|
let _ = email_client.command(DataCommand);
|
||||||
let _ = email_client.message(Box::new("Test email".as_bytes()));
|
let _ = email_client.message(Box::new("Test email".as_bytes()));
|
||||||
let _ = email_client.smtp_command(QuitCommand);
|
let _ = email_client.command(QuitCommand);
|
||||||
|
}</code></pre></div>
|
||||||
|
|
||||||
|
<footer class=" footline" >
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="navigation">
|
<div id="navigation">
|
||||||
|
|
||||||
|
|
||||||
@@ -448,12 +531,6 @@ let _ = email_client.smtp_command(QuitCommand);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-prev" href="/lettre/sending-messages/intro/"> <i class="fa fa-chevron-left"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-next" href="/lettre/sending-messages/sendmail/" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -467,23 +544,203 @@ let _ = email_client.smtp_command(QuitCommand);
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-prev" href="/sending-messages/intro/" title="Introduction"> <i class="fa fa-chevron-left"></i></a>
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-next" href="/sending-messages/sendmail/" title="Sendmail transport" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
||||||
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://lettre.github.io/lettre//js/clipboard.min.js"></script>
|
<script src="/js/clipboard.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.min.js"></script>
|
<script src="/js/perfect-scrollbar.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.jquery.min.js"></script>
|
<script src="/js/perfect-scrollbar.jquery.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery.sticky-kit.min.js"></script>
|
<script src="/js/jquery.sticky-kit.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/featherlight.min.js"></script>
|
<script src="/js/featherlight.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/html5shiv-printshiv.min.js"></script>
|
<script src="/js/html5shiv-printshiv.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/highlight.pack.js"></script>
|
<script src="/js/highlight.pack.js?1522603726"></script>
|
||||||
<script>hljs.initHighlightingOnLoad();</script>
|
<script>hljs.initHighlightingOnLoad();</script>
|
||||||
<script src="https://lettre.github.io/lettre//js/modernizr.custom.71422.js"></script>
|
<script src="/js/modernizr.custom.71422.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/learn.js"></script>
|
<script src="/js/learn.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/hugo-learn.js"></script>
|
<script src="/js/hugo-learn.js?1522603726"></script>
|
||||||
|
|
||||||
|
<link href="/mermaid/mermaid.css?1522603726" type="text/css" rel="stylesheet" />
|
||||||
|
<script src="/mermaid/mermaid.js?1522603726"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({ startOnLoad: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -3,53 +3,64 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
<meta name="generator" content="Hugo 0.20.7" />
|
<meta name="generator" content="Hugo 0.37.1" />
|
||||||
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
||||||
<meta name="author" content="Alexis Mousset">
|
<meta name="author" content="Alexis Mousset">
|
||||||
|
|
||||||
<link rel="shortcut icon" href="https://lettre.github.io/lettre//images/favicon.png" type="image/x-icon" />
|
<link rel="shortcut icon" href="http://docs.lettre.at//images/favicon.png" type="image/x-icon" />
|
||||||
|
|
||||||
|
<title>Stub transport :: Lettre site</title>
|
||||||
|
|
||||||
|
|
||||||
<title>Stub transport</title>
|
<link href="/css/nucleus.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/nucleus.css" rel="stylesheet">
|
<link href="/css/font-awesome.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/font-awesome.min.css" rel="stylesheet">
|
<link href="/css/hybrid.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hybrid.css" rel="stylesheet">
|
<link href="/css/featherlight.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/featherlight.min.css" rel="stylesheet">
|
<link href="/css/perfect-scrollbar.min.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/perfect-scrollbar.min.css" rel="stylesheet">
|
<link href="/css/auto-complete.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/horsey.css" rel="stylesheet">
|
<link href="/css/theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/theme.css" rel="stylesheet">
|
<link href="/css/hugo-theme.css?1522603726" rel="stylesheet">
|
||||||
<link href="https://lettre.github.io/lettre//css/hugo-theme.css" rel="stylesheet">
|
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery-2.x.min.js"></script>
|
|
||||||
<style type="text/css">:root #header + #content > #left > #rlblock_left
|
|
||||||
{display:none !important;}</style>
|
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/jquery-2.x.min.js?1522603726"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
:root #header + #content > #left > #rlblock_left{
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
<body class="" data-url="/lettre/sending-messages/stub/">
|
<body class="" data-url="/sending-messages/stub/">
|
||||||
|
<nav id="sidebar" class="">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<nav id="sidebar">
|
|
||||||
<div id="header-wrapper">
|
<div id="header-wrapper">
|
||||||
<div id="header">
|
<div id="header">
|
||||||
<a href="https://lettre.github.io/lettre//getting-started/intro/"><img src="https://lettre.github.io/lettre//images/logo50.png" /></a>
|
<a href="http://docs.lettre.at//getting-started/intro/"><img src="http://docs.lettre.at//images/logo50.png" /></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="searchbox">
|
<div class="searchbox">
|
||||||
<label for="search-by"><i class="fa fa-search"></i></label>
|
<label for="search-by"><i class="fa fa-search"></i></label>
|
||||||
<input data-search-input id="search-by" type="text" placeholder="Search">
|
<input data-search-input id="search-by" type="text" placeholder="Search...">
|
||||||
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
||||||
</div>
|
</div>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/lunr.min.js"></script>
|
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/horsey.js"></script>
|
<script type="text/javascript" src="/js/lunr.min.js?1522603726"></script>
|
||||||
|
<script type="text/javascript" src="/js/auto-complete.js?1522603726"></script>
|
||||||
<script type="text/javascript">
|
<script type="text/javascript">
|
||||||
var baseurl = "https:\/\/lettre.github.io\/lettre\/";
|
|
||||||
|
var baseurl = "http:\/\/docs.lettre.at\/";
|
||||||
|
|
||||||
</script>
|
</script>
|
||||||
<script type="text/javascript" src="https://lettre.github.io/lettre//js/search.js"></script>
|
<script type="text/javascript" src="/js/search.js?1522603726"></script>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="highlightable">
|
<div class="highlightable">
|
||||||
<ul class="topics">
|
<ul class="topics">
|
||||||
|
|
||||||
@@ -61,57 +72,44 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/" title="Getting started" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/getting-started/">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/">
|
|
||||||
<a href="/lettre/getting-started/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>1. </b>
|
|
||||||
|
|
||||||
Getting started
|
Getting started
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/getting-started/intro/">
|
|
||||||
<a href="/lettre/getting-started/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/getting-started/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
@@ -125,86 +123,184 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/" title="Creating messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
<li class="dd-item " data-nav-id="/lettre/creating-messages/">
|
<a href="/creating-messages/">
|
||||||
<a href="/lettre/creating-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>2. </b>
|
|
||||||
|
|
||||||
Creating messages
|
Creating messages
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
</a>
|
||||||
|
|
||||||
</li>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<li class="dd-item parent" data-nav-id="/lettre/sending-messages/">
|
|
||||||
<a href="/lettre/sending-messages/">
|
|
||||||
<span>
|
|
||||||
|
|
||||||
<b>3. </b>
|
|
||||||
|
|
||||||
Sending messages
|
|
||||||
|
|
||||||
</span>
|
|
||||||
</a>
|
|
||||||
|
|
||||||
<ul>
|
<ul>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/intro/">
|
|
||||||
<a href="/lettre/sending-messages/intro/">
|
|
||||||
<span>Introduction </i></span>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/email/" title="Email creation" class="dd-item ">
|
||||||
|
<a href="/creating-messages/email/">
|
||||||
|
Email creation
|
||||||
|
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/smtp/">
|
|
||||||
<a href="/lettre/sending-messages/smtp/">
|
|
||||||
<span>SMTP transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/sendmail/">
|
|
||||||
<a href="/lettre/sending-messages/sendmail/">
|
|
||||||
<span>Sendmail transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item " data-nav-id="/lettre/sending-messages/file/">
|
|
||||||
<a href="/lettre/sending-messages/file/">
|
|
||||||
<span>File transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
<li class="dd-item active" data-nav-id="/lettre/sending-messages/stub/">
|
|
||||||
<a href="/lettre/sending-messages/stub/">
|
|
||||||
<span>Stub transport </i></span>
|
|
||||||
</a>
|
|
||||||
</li>
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
|
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/" title="Sending messages" class="dd-item
|
||||||
|
parent
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/sending-messages/">
|
||||||
|
Sending messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/sending-messages/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/smtp/" title="SMTP transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/smtp/">
|
||||||
|
SMTP transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/sendmail/" title="Sendmail transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/sendmail/">
|
||||||
|
Sendmail transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/file/" title="File transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/file/">
|
||||||
|
File transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/stub/" title="Stub transport" class="dd-item active">
|
||||||
|
<a href="/sending-messages/stub/">
|
||||||
|
Stub transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</ul>
|
</ul>
|
||||||
<hr>
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="footer">
|
<section id="footer">
|
||||||
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
||||||
@@ -213,11 +309,15 @@
|
|||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<section id="body">
|
<section id="body">
|
||||||
<div id="overlay"></div>
|
<div id="overlay"></div>
|
||||||
|
<div class="padding highlightable sticky-parent">
|
||||||
|
|
||||||
<div class="padding highlightable">
|
<div class="sticky-spacer">
|
||||||
|
|
||||||
<div id="top-bar">
|
<div id="top-bar">
|
||||||
|
|
||||||
|
|
||||||
@@ -231,6 +331,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
<span id="sidebar-toggle-span">
|
<span id="sidebar-toggle-span">
|
||||||
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
||||||
@@ -238,7 +339,9 @@
|
|||||||
</a>
|
</a>
|
||||||
</span>
|
</span>
|
||||||
|
|
||||||
<span id="toc-menu"><a href=""><i class="fa fa-list-alt"></i></a></span>
|
<span id="toc-menu"><i class="fa fa-list-alt"></i></span>
|
||||||
|
|
||||||
|
<span class="links">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -246,11 +349,18 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a href="/lettre/sending-messages/" itemprop="url"><span itemprop="title">Sending messages</span></a> <i class="fa fa-angle-right"></i>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<span itemprop="title"> Stub transport</span>
|
|
||||||
|
<a href='/'>Lettre site</a> > <a href='/sending-messages/'>Sending messages</a> > Stub transport
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="progress">
|
<div class="progress">
|
||||||
@@ -260,82 +370,50 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="body-inner">
|
<div id="body-inner">
|
||||||
|
|
||||||
<h1>Stub transport</h1>
|
<h1>Stub transport</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<p>The stub transport only logs message envelope and drops the content. It can be useful for
|
<p>The stub transport only logs message envelope and drops the content. It can be useful for
|
||||||
testing purposes.</p>
|
testing purposes.</p>
|
||||||
use lettre::stub::StubEmailTransport;
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-rust" data-lang="rust"><span style="color:#66d9ef">extern</span> <span style="color:#66d9ef">crate</span> lettre;
|
||||||
use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress};
|
|
||||||
|
|
||||||
let email = SimpleSendableEmail::new(
|
<span style="color:#66d9ef">use</span> lettre::stub::StubEmailTransport;
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
<span style="color:#66d9ef">use</span> lettre::{SimpleSendableEmail, EmailTransport};
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
|
||||||
"message_id".to_string(),
|
|
||||||
"Hello world".to_string(),
|
|
||||||
);
|
|
||||||
|
|
||||||
let mut sender = StubEmailTransport::new_positive();
|
<span style="color:#66d9ef">fn</span> <span style="color:#a6e22e">main</span>() {
|
||||||
let result = sender.send(&email);
|
<span style="color:#66d9ef">let</span> email <span style="color:#f92672">=</span> SimpleSendableEmail::new(
|
||||||
assert!(result.is_ok());
|
<span style="color:#e6db74">"user@localhost"</span>.to_string(),
|
||||||
|
<span style="color:#f92672">&</span>[<span style="color:#e6db74">"root@localhost"</span>.to_string()],
|
||||||
|
<span style="color:#e6db74">"message_id"</span>.to_string(),
|
||||||
|
<span style="color:#e6db74">"Hello world"</span>.to_string(),
|
||||||
|
).unwrap();
|
||||||
|
|
||||||
|
<span style="color:#66d9ef">let</span> <span style="color:#66d9ef">mut</span> sender <span style="color:#f92672">=</span> StubEmailTransport::new_positive();
|
||||||
|
<span style="color:#66d9ef">let</span> result <span style="color:#f92672">=</span> sender.send(<span style="color:#f92672">&</span>email);
|
||||||
|
assert<span style="color:#f92672">!</span>(result.is_ok());
|
||||||
|
}</code></pre></div>
|
||||||
<p>Will log (when using a logger like <code>env_logger</code>):</p>
|
<p>Will log (when using a logger like <code>env_logger</code>):</p>
|
||||||
b7c211bc-9811-45ce-8cd9-68eab575d695: from=<user@localhost> to=<root@localhost>
|
<div class="highlight"><pre style="color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-text" data-lang="text">b7c211bc-9811-45ce-8cd9-68eab575d695: from=<user@localhost> to=<root@localhost></code></pre></div>
|
||||||
|
|
||||||
|
<footer class=" footline" >
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<div id="navigation">
|
<div id="navigation">
|
||||||
|
|
||||||
|
|
||||||
@@ -359,7 +437,6 @@ b7c211bc-9811-45ce-8cd9-68eab575d695: from=<user@localhost> to=<root@localhost>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<a class="nav nav-prev" href="/lettre/sending-messages/file/"> <i class="fa fa-chevron-left"></i></a>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -370,23 +447,197 @@ b7c211bc-9811-45ce-8cd9-68eab575d695: from=<user@localhost> to=<root@localhost>
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-prev" href="/sending-messages/file/" title="File transport"> <i class="fa fa-chevron-left"></i></a>
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-next" href="/sending-messages/intro/" title="Introduction" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
||||||
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
||||||
</div>
|
</div>
|
||||||
<script src="https://lettre.github.io/lettre//js/clipboard.min.js"></script>
|
<script src="/js/clipboard.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.min.js"></script>
|
<script src="/js/perfect-scrollbar.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/perfect-scrollbar.jquery.min.js"></script>
|
<script src="/js/perfect-scrollbar.jquery.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/jquery.sticky-kit.min.js"></script>
|
<script src="/js/jquery.sticky-kit.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/featherlight.min.js"></script>
|
<script src="/js/featherlight.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/html5shiv-printshiv.min.js"></script>
|
<script src="/js/html5shiv-printshiv.min.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/highlight.pack.js"></script>
|
<script src="/js/highlight.pack.js?1522603726"></script>
|
||||||
<script>hljs.initHighlightingOnLoad();</script>
|
<script>hljs.initHighlightingOnLoad();</script>
|
||||||
<script src="https://lettre.github.io/lettre//js/modernizr.custom.71422.js"></script>
|
<script src="/js/modernizr.custom.71422.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/learn.js"></script>
|
<script src="/js/learn.js?1522603726"></script>
|
||||||
<script src="https://lettre.github.io/lettre//js/hugo-learn.js"></script>
|
<script src="/js/hugo-learn.js?1522603726"></script>
|
||||||
|
|
||||||
|
<link href="/mermaid/mermaid.css?1522603726" type="text/css" rel="stylesheet" />
|
||||||
|
<script src="/mermaid/mermaid.js?1522603726"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({ startOnLoad: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -1,64 +1,70 @@
|
|||||||
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
|
||||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
||||||
|
xmlns:xhtml="http://www.w3.org/1999/xhtml">
|
||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>https://lettre.github.io/lettre/getting-started/intro/</loc>
|
<loc>http://docs.lettre.at/getting-started/intro/</loc>
|
||||||
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>https://lettre.github.io/lettre/sending-messages/intro/</loc>
|
<loc>http://docs.lettre.at/sending-messages/intro/</loc>
|
||||||
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>https://lettre.github.io/lettre/getting-started/</loc>
|
<loc>http://docs.lettre.at/getting-started/</loc>
|
||||||
<lastmod>2017-05-21T23:46:01+02:00</lastmod>
|
<lastmod>2017-05-21T23:46:01+02:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>https://lettre.github.io/lettre/sending-messages/smtp/</loc>
|
<loc>http://docs.lettre.at/sending-messages/smtp/</loc>
|
||||||
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>https://lettre.github.io/lettre/creating-messages/</loc>
|
<loc>http://docs.lettre.at/creating-messages/</loc>
|
||||||
<lastmod>2017-05-21T23:46:01+02:00</lastmod>
|
<lastmod>2017-05-21T23:46:01+02:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>https://lettre.github.io/lettre/sending-messages/sendmail/</loc>
|
<loc>http://docs.lettre.at/sending-messages/sendmail/</loc>
|
||||||
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>https://lettre.github.io/lettre/sending-messages/</loc>
|
<loc>http://docs.lettre.at/sending-messages/</loc>
|
||||||
<lastmod>2017-05-21T23:46:01+02:00</lastmod>
|
<lastmod>2017-05-21T23:46:01+02:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>https://lettre.github.io/lettre/sending-messages/file/</loc>
|
<loc>http://docs.lettre.at/creating-messages/email/</loc>
|
||||||
|
<lastmod>2018-01-21T23:46:17+02:00</lastmod>
|
||||||
|
</url>
|
||||||
|
|
||||||
|
<url>
|
||||||
|
<loc>http://docs.lettre.at/sending-messages/file/</loc>
|
||||||
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>https://lettre.github.io/lettre/sending-messages/stub/</loc>
|
<loc>http://docs.lettre.at/sending-messages/stub/</loc>
|
||||||
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>https://lettre.github.io/lettre/categories/</loc>
|
<loc>http://docs.lettre.at/categories/</loc>
|
||||||
<priority>0</priority>
|
<priority>0</priority>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>https://lettre.github.io/lettre/</loc>
|
<loc>http://docs.lettre.at/</loc>
|
||||||
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
<lastmod>2017-05-21T23:46:17+02:00</lastmod>
|
||||||
<priority>0</priority>
|
<priority>0</priority>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
<url>
|
<url>
|
||||||
<loc>https://lettre.github.io/lettre/tags/</loc>
|
<loc>http://docs.lettre.at/tags/</loc>
|
||||||
<priority>0</priority>
|
<priority>0</priority>
|
||||||
</url>
|
</url>
|
||||||
|
|
||||||
|
|||||||
593
docs/tags/index.html
Normal file
593
docs/tags/index.html
Normal file
@@ -0,0 +1,593 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en" class="js csstransforms3d">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
|
||||||
|
<meta name="generator" content="Hugo 0.37.1" />
|
||||||
|
<meta name="description" content="Documentation for the Lettre mailer in Rust">
|
||||||
|
<meta name="author" content="Alexis Mousset">
|
||||||
|
|
||||||
|
<link rel="shortcut icon" href="http://docs.lettre.at//images/favicon.png" type="image/x-icon" />
|
||||||
|
|
||||||
|
<title>Tags :: Lettre site</title>
|
||||||
|
|
||||||
|
|
||||||
|
<link href="/css/nucleus.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/font-awesome.min.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/hybrid.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/featherlight.min.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/perfect-scrollbar.min.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/auto-complete.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/theme.css?1522603726" rel="stylesheet">
|
||||||
|
<link href="/css/hugo-theme.css?1522603726" rel="stylesheet">
|
||||||
|
|
||||||
|
|
||||||
|
<script src="/js/jquery-2.x.min.js?1522603726"></script>
|
||||||
|
|
||||||
|
<style type="text/css">
|
||||||
|
:root #header + #content > #left > #rlblock_left{
|
||||||
|
display:none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</head>
|
||||||
|
<body class="" data-url="/tags/">
|
||||||
|
<nav id="sidebar" class="">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="header-wrapper">
|
||||||
|
<div id="header">
|
||||||
|
<a href="http://docs.lettre.at//getting-started/intro/"><img src="http://docs.lettre.at//images/logo50.png" /></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="searchbox">
|
||||||
|
<label for="search-by"><i class="fa fa-search"></i></label>
|
||||||
|
<input data-search-input id="search-by" type="text" placeholder="Search...">
|
||||||
|
<span data-search-clear=""><i class="fa fa-close"></i></span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="/js/lunr.min.js?1522603726"></script>
|
||||||
|
<script type="text/javascript" src="/js/auto-complete.js?1522603726"></script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
|
||||||
|
var baseurl = "http:\/\/docs.lettre.at\/";
|
||||||
|
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript" src="/js/search.js?1522603726"></script>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="highlightable">
|
||||||
|
<ul class="topics">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/" title="Getting started" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/getting-started/">
|
||||||
|
Getting started
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/getting-started/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/getting-started/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/" title="Creating messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/creating-messages/">
|
||||||
|
Creating messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/creating-messages/email/" title="Email creation" class="dd-item ">
|
||||||
|
<a href="/creating-messages/email/">
|
||||||
|
Email creation
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/" title="Sending messages" class="dd-item
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
">
|
||||||
|
<a href="/sending-messages/">
|
||||||
|
Sending messages
|
||||||
|
|
||||||
|
</a>
|
||||||
|
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/intro/" title="Introduction" class="dd-item ">
|
||||||
|
<a href="/sending-messages/intro/">
|
||||||
|
Introduction
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/smtp/" title="SMTP transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/smtp/">
|
||||||
|
SMTP transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/sendmail/" title="Sendmail transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/sendmail/">
|
||||||
|
Sendmail transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/file/" title="File transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/file/">
|
||||||
|
File transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<li data-nav-id="/sending-messages/stub/" title="Stub transport" class="dd-item ">
|
||||||
|
<a href="/sending-messages/stub/">
|
||||||
|
Stub transport
|
||||||
|
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section id="footer">
|
||||||
|
<p>Built with <a href="https://github.com/matcornic/hugo-theme-learn"><i class="fa fa-heart"></i></a> from <a href="http://getgrav.org">Grav</a> and <a href="http://gohugo.io/">Hugo</a></p>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
</div>
|
||||||
|
</nav>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<section id="body">
|
||||||
|
<div id="overlay"></div>
|
||||||
|
<div class="padding highlightable sticky-parent">
|
||||||
|
|
||||||
|
<div class="sticky-spacer">
|
||||||
|
<div id="top-bar">
|
||||||
|
|
||||||
|
|
||||||
|
<div id="breadcrumbs" itemscope="" itemtype="http://data-vocabulary.org/Breadcrumb">
|
||||||
|
<span id="sidebar-toggle-span">
|
||||||
|
<a href="#" id="sidebar-toggle" data-sidebar-toggle="">
|
||||||
|
<i class="fa fa-bars"></i>
|
||||||
|
</a>
|
||||||
|
</span>
|
||||||
|
|
||||||
|
<span id="toc-menu"><i class="fa fa-list-alt"></i></span>
|
||||||
|
|
||||||
|
<span class="links">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Tags
|
||||||
|
|
||||||
|
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="progress">
|
||||||
|
<div class="wrapper">
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<div id="body-inner">
|
||||||
|
|
||||||
|
<h1>Tags</h1>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<footer class=" footline" >
|
||||||
|
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="navigation">
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<a class="nav nav-next" href="/getting-started/" title="Getting started" style="margin-right: 0px;"><i class="fa fa-chevron-right"></i></a>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</section>
|
||||||
|
|
||||||
|
<div style="left: -1000px; overflow: scroll; position: absolute; top: -1000px; border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;">
|
||||||
|
<div style="border: none; box-sizing: content-box; height: 200px; margin: 0px; padding: 0px; width: 200px;"></div>
|
||||||
|
</div>
|
||||||
|
<script src="/js/clipboard.min.js?1522603726"></script>
|
||||||
|
<script src="/js/perfect-scrollbar.min.js?1522603726"></script>
|
||||||
|
<script src="/js/perfect-scrollbar.jquery.min.js?1522603726"></script>
|
||||||
|
<script src="/js/jquery.sticky-kit.min.js?1522603726"></script>
|
||||||
|
<script src="/js/featherlight.min.js?1522603726"></script>
|
||||||
|
<script src="/js/html5shiv-printshiv.min.js?1522603726"></script>
|
||||||
|
<script src="/js/highlight.pack.js?1522603726"></script>
|
||||||
|
<script>hljs.initHighlightingOnLoad();</script>
|
||||||
|
<script src="/js/modernizr.custom.71422.js?1522603726"></script>
|
||||||
|
<script src="/js/learn.js?1522603726"></script>
|
||||||
|
<script src="/js/hugo-learn.js?1522603726"></script>
|
||||||
|
|
||||||
|
<link href="/mermaid/mermaid.css?1522603726" type="text/css" rel="stylesheet" />
|
||||||
|
<script src="/mermaid/mermaid.js?1522603726"></script>
|
||||||
|
<script>
|
||||||
|
mermaid.initialize({ startOnLoad: true });
|
||||||
|
</script>
|
||||||
|
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -2,12 +2,12 @@
|
|||||||
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
|
||||||
<channel>
|
<channel>
|
||||||
<title>Tags on Lettre site</title>
|
<title>Tags on Lettre site</title>
|
||||||
<link>https://lettre.github.io/lettre/tags/</link>
|
<link>http://docs.lettre.at/tags/</link>
|
||||||
<description>Recent content in Tags on Lettre site</description>
|
<description>Recent content in Tags on Lettre site</description>
|
||||||
<generator>Hugo -- gohugo.io</generator>
|
<generator>Hugo -- gohugo.io</generator>
|
||||||
<language>en-us</language>
|
<language>en-us</language>
|
||||||
|
|
||||||
<atom:link href="https://lettre.github.io/lettre/tags/index.xml" rel="self" type="application/rss+xml" />
|
<atom:link href="http://docs.lettre.at/tags/index.xml" rel="self" type="application/rss+xml" />
|
||||||
|
|
||||||
|
|
||||||
</channel>
|
</channel>
|
||||||
|
|||||||
@@ -1,37 +0,0 @@
|
|||||||
### v0.7.0 (2017-10-08)
|
|
||||||
|
|
||||||
#### Features
|
|
||||||
|
|
||||||
* **all**
|
|
||||||
* Split into the *lettre* and *lettre_email* crates
|
|
||||||
* A lot of small improvements
|
|
||||||
|
|
||||||
* **smtp transport**
|
|
||||||
* Use *tls-native* instead of *openssl*
|
|
||||||
* Allow validating server certificate
|
|
||||||
|
|
||||||
### v0.6.2 (2017-02-18)
|
|
||||||
|
|
||||||
#### Features
|
|
||||||
|
|
||||||
* **all**
|
|
||||||
* 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
|
|
||||||
|
|
||||||
* **tests**
|
|
||||||
* #93: Force building tests before coverage computing
|
|
||||||
|
|
||||||
### v0.6.0 (2016-05-05)
|
|
||||||
|
|
||||||
Nothing.
|
|
||||||
|
|
||||||
1
lettre/CHANGELOG.md
Symbolic link
1
lettre/CHANGELOG.md
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../CHANGELOG.md
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
|
|
||||||
name = "lettre"
|
name = "lettre"
|
||||||
version = "0.7.0"
|
version = "0.8.1" # remember to update html_root_url
|
||||||
description = "Email client"
|
description = "Email client"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
documentation = "https://docs.rs/lettre/"
|
documentation = "https://docs.rs/lettre/"
|
||||||
@@ -15,18 +15,21 @@ keywords = ["email", "smtp", "mailer"]
|
|||||||
travis-ci = { repository = "lettre/lettre" }
|
travis-ci = { repository = "lettre/lettre" }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
log = "^0.3"
|
log = "^0.4"
|
||||||
|
nom = { version = "^3.2", optional = true }
|
||||||
bufstream = { version = "^0.1", optional = true }
|
bufstream = { version = "^0.1", optional = true }
|
||||||
native-tls = { version = "^0.1", optional = true }
|
native-tls = { version = "^0.1", optional = true }
|
||||||
base64 = { version = "^0.7", optional = true }
|
base64 = { version = "^0.9", optional = true }
|
||||||
hex = { version = "^0.2", optional = true }
|
hex = { version = "^0.3", optional = true }
|
||||||
|
hostname = { version = "^0.1", optional = true }
|
||||||
rust-crypto = { version = "^0.2", optional = true }
|
rust-crypto = { version = "^0.2", optional = true }
|
||||||
serde = { version = "^1.0", optional = true }
|
serde = { version = "^1.0", optional = true }
|
||||||
serde_json = { version = "^1.0", optional = true }
|
serde_json = { version = "^1.0", optional = true }
|
||||||
serde_derive = { version = "^1.0", optional = true }
|
serde_derive = { version = "^1.0", optional = true }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "^0.4"
|
env_logger = "^0.5"
|
||||||
|
glob = "0.2"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = ["file-transport", "crammd5-auth", "smtp-transport", "sendmail-transport"]
|
default = ["file-transport", "crammd5-auth", "smtp-transport", "sendmail-transport"]
|
||||||
@@ -34,7 +37,7 @@ unstable = []
|
|||||||
serde-impls = ["serde", "serde_derive"]
|
serde-impls = ["serde", "serde_derive"]
|
||||||
file-transport = ["serde-impls", "serde_json"]
|
file-transport = ["serde-impls", "serde_json"]
|
||||||
crammd5-auth = ["rust-crypto", "hex"]
|
crammd5-auth = ["rust-crypto", "hex"]
|
||||||
smtp-transport = ["bufstream", "native-tls", "base64"]
|
smtp-transport = ["bufstream", "native-tls", "base64", "nom", "hostname"]
|
||||||
sendmail-transport = []
|
sendmail-transport = []
|
||||||
|
|
||||||
[[example]]
|
[[example]]
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
extern crate lettre;
|
|
||||||
extern crate env_logger;
|
extern crate env_logger;
|
||||||
|
extern crate lettre;
|
||||||
|
|
||||||
use lettre::{EmailAddress, EmailTransport, SimpleSendableEmail, SmtpTransport};
|
use lettre::{EmailTransport, SimpleSendableEmail, SmtpTransport};
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
env_logger::init().unwrap();
|
env_logger::init();
|
||||||
|
|
||||||
let email = SimpleSendableEmail::new(
|
let email = SimpleSendableEmail::new(
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
"user@localhost".to_string(),
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
&["root@localhost".to_string()],
|
||||||
"file_id".to_string(),
|
"my-message-id".to_string(),
|
||||||
"Hello ß☺ example".to_string(),
|
"Hello ß☺ example".to_string(),
|
||||||
);
|
).unwrap();
|
||||||
|
|
||||||
// Open a local connection on port 25
|
// Open a local connection on port 25
|
||||||
let mut mailer = SmtpTransport::builder_unencrypted_localhost()
|
let mut mailer = SmtpTransport::builder_unencrypted_localhost()
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
../rustfmt.toml
|
|
||||||
@@ -34,8 +34,8 @@ impl StdError for Error {
|
|||||||
|
|
||||||
fn cause(&self) -> Option<&StdError> {
|
fn cause(&self) -> Option<&StdError> {
|
||||||
match *self {
|
match *self {
|
||||||
Io(ref err) => Some(&*err as &StdError),
|
Io(ref err) => Some(&*err),
|
||||||
JsonSerialization(ref err) => Some(&*err as &StdError),
|
JsonSerialization(ref err) => Some(&*err),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,36 +2,6 @@
|
|||||||
//! `message_id.txt`.
|
//! `message_id.txt`.
|
||||||
//! 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.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
|
||||||
//! use std::env::temp_dir;
|
|
||||||
//!
|
|
||||||
//! use lettre::file::FileEmailTransport;
|
|
||||||
//! use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress};
|
|
||||||
//!
|
|
||||||
//! // Write to the local temp directory
|
|
||||||
//! let mut sender = FileEmailTransport::new(temp_dir());
|
|
||||||
//! let email = SimpleSendableEmail::new(
|
|
||||||
//! EmailAddress::new("user@localhost".to_string()),
|
|
||||||
//! vec![EmailAddress::new("root@localhost".to_string())],
|
|
||||||
//! "message_id".to_string(),
|
|
||||||
//! "Hello world".to_string(),
|
|
||||||
//! );
|
|
||||||
//!
|
|
||||||
//! let result = sender.send(&email);
|
|
||||||
//! assert!(result.is_ok());
|
|
||||||
//! ```
|
|
||||||
//! Example result in `/tmp/b7c211bc-9811-45ce-8cd9-68eab575d695.txt`:
|
|
||||||
//!
|
|
||||||
//! ```text
|
|
||||||
//! b7c211bc-9811-45ce-8cd9-68eab575d695: from=<user@localhost> to=<root@localhost>
|
|
||||||
//! To: <root@localhost>
|
|
||||||
//! From: <user@localhost>
|
|
||||||
//! Subject: Hello
|
|
||||||
//! Date: Sat, 31 Oct 2015 13:42:19 +0100
|
|
||||||
//! Message-ID: <b7c211bc-9811-45ce-8cd9-68eab575d695.lettre@localhost>
|
|
||||||
//!
|
|
||||||
//! Hello World!
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use EmailTransport;
|
use EmailTransport;
|
||||||
use SendableEmail;
|
use SendableEmail;
|
||||||
@@ -47,6 +17,7 @@ pub mod error;
|
|||||||
|
|
||||||
/// Writes the content and the envelope information to a file
|
/// Writes the content and the envelope information to a file
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct FileEmailTransport {
|
pub struct FileEmailTransport {
|
||||||
path: PathBuf,
|
path: PathBuf,
|
||||||
}
|
}
|
||||||
@@ -70,16 +41,13 @@ impl<'a, T: Read + 'a> EmailTransport<'a, T, FileResult> for FileEmailTransport
|
|||||||
let mut message_content = String::new();
|
let mut message_content = String::new();
|
||||||
let _ = email.message().read_to_string(&mut message_content);
|
let _ = email.message().read_to_string(&mut message_content);
|
||||||
|
|
||||||
let simple_email = SimpleSendableEmail::new(
|
let simple_email = SimpleSendableEmail::new_with_envelope(
|
||||||
email.from().clone(),
|
email.envelope().clone(),
|
||||||
email.to().clone(),
|
email.message_id().to_string(),
|
||||||
email.message_id().clone(),
|
|
||||||
message_content,
|
message_content,
|
||||||
);
|
);
|
||||||
|
|
||||||
f.write_all(
|
f.write_all(serde_json::to_string(&simple_email)?.as_bytes())?;
|
||||||
serde_json::to_string(&simple_email)?.as_bytes(),
|
|
||||||
)?;
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,25 +4,32 @@
|
|||||||
//! emails have to implement `SendableEmail`.
|
//! emails have to implement `SendableEmail`.
|
||||||
//!
|
//!
|
||||||
|
|
||||||
#![deny(missing_docs, unsafe_code, unstable_features, warnings)]
|
#![doc(html_root_url = "https://docs.rs/lettre/0.8.1")]
|
||||||
|
#![deny(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
|
||||||
#[macro_use]
|
trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
|
||||||
extern crate log;
|
unused_qualifications)]
|
||||||
#[cfg(feature = "crammd5-auth")]
|
|
||||||
extern crate hex;
|
|
||||||
#[cfg(feature = "crammd5-auth")]
|
|
||||||
extern crate crypto;
|
|
||||||
#[cfg(feature = "smtp-transport")]
|
#[cfg(feature = "smtp-transport")]
|
||||||
extern crate base64;
|
extern crate base64;
|
||||||
#[cfg(feature = "smtp-transport")]
|
#[cfg(feature = "smtp-transport")]
|
||||||
extern crate bufstream;
|
extern crate bufstream;
|
||||||
|
#[cfg(feature = "crammd5-auth")]
|
||||||
|
extern crate crypto;
|
||||||
|
#[cfg(feature = "crammd5-auth")]
|
||||||
|
extern crate hex;
|
||||||
|
#[cfg(feature = "smtp-transport")]
|
||||||
|
extern crate hostname;
|
||||||
|
#[macro_use]
|
||||||
|
extern crate log;
|
||||||
#[cfg(feature = "smtp-transport")]
|
#[cfg(feature = "smtp-transport")]
|
||||||
extern crate native_tls;
|
extern crate native_tls;
|
||||||
#[cfg(feature = "file-transport")]
|
#[cfg(feature = "smtp-transport")]
|
||||||
extern crate serde_json;
|
#[macro_use]
|
||||||
|
extern crate nom;
|
||||||
#[cfg(feature = "serde-impls")]
|
#[cfg(feature = "serde-impls")]
|
||||||
#[macro_use]
|
#[macro_use]
|
||||||
extern crate serde_derive;
|
extern crate serde_derive;
|
||||||
|
#[cfg(feature = "file-transport")]
|
||||||
|
extern crate serde_json;
|
||||||
|
|
||||||
#[cfg(feature = "smtp-transport")]
|
#[cfg(feature = "smtp-transport")]
|
||||||
pub mod smtp;
|
pub mod smtp;
|
||||||
@@ -37,16 +44,68 @@ pub use file::FileEmailTransport;
|
|||||||
#[cfg(feature = "sendmail-transport")]
|
#[cfg(feature = "sendmail-transport")]
|
||||||
pub use sendmail::SendmailTransport;
|
pub use sendmail::SendmailTransport;
|
||||||
#[cfg(feature = "smtp-transport")]
|
#[cfg(feature = "smtp-transport")]
|
||||||
pub use smtp::{SmtpTransport, ClientSecurity};
|
pub use smtp::{ClientSecurity, SmtpTransport};
|
||||||
#[cfg(feature = "smtp-transport")]
|
#[cfg(feature = "smtp-transport")]
|
||||||
pub use smtp::client::net::ClientTlsParameters;
|
pub use smtp::client::net::ClientTlsParameters;
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
use std::error::Error as StdError;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
|
/// Error type for email content
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum Error {
|
||||||
|
/// Missing from in envelope
|
||||||
|
MissingFrom,
|
||||||
|
/// Missing to in envelope
|
||||||
|
MissingTo,
|
||||||
|
/// Invalid email
|
||||||
|
InvalidEmailAddress,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StdError for Error {
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
Error::MissingFrom => "missing source address, invalid envelope",
|
||||||
|
Error::MissingTo => "missing destination address, invalid envelope",
|
||||||
|
Error::InvalidEmailAddress => "invalid email address",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn cause(&self) -> Option<&StdError> {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Display for Error {
|
||||||
|
fn fmt(&self, fmt: &mut Formatter) -> Result<(), fmt::Error> {
|
||||||
|
fmt.write_str(self.description())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Email result type
|
||||||
|
pub type EmailResult<T> = Result<T, Error>;
|
||||||
|
|
||||||
/// Email address
|
/// Email address
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct EmailAddress(pub String);
|
pub struct EmailAddress(String);
|
||||||
|
|
||||||
|
impl EmailAddress {
|
||||||
|
/// Creates a new `EmailAddress`. For now it makes no validation.
|
||||||
|
pub fn new(address: String) -> EmailResult<EmailAddress> {
|
||||||
|
// TODO make some basic sanity checks
|
||||||
|
Ok(EmailAddress(address))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FromStr for EmailAddress {
|
||||||
|
type Err = Error;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||||
|
EmailAddress::new(s.to_string())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Display for EmailAddress {
|
impl Display for EmailAddress {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
@@ -54,19 +113,98 @@ impl Display for EmailAddress {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EmailAddress {
|
/// Simple email envelope representation
|
||||||
/// Creates a new email address
|
///
|
||||||
pub fn new(address: String) -> EmailAddress {
|
/// We only accept mailboxes, and do not support source routes (as per RFC).
|
||||||
EmailAddress(address)
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
|
pub struct Envelope {
|
||||||
|
/// The envelope recipients' addresses
|
||||||
|
///
|
||||||
|
/// This can not be empty.
|
||||||
|
forward_path: Vec<EmailAddress>,
|
||||||
|
/// The envelope sender address
|
||||||
|
reverse_path: Option<EmailAddress>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Envelope {
|
||||||
|
/// Creates a new envelope, which may fail if `to` is empty.
|
||||||
|
pub fn new(from: Option<EmailAddress>, to: Vec<EmailAddress>) -> EmailResult<Envelope> {
|
||||||
|
if to.is_empty() {
|
||||||
|
return Err(Error::MissingTo);
|
||||||
|
}
|
||||||
|
Ok(Envelope {
|
||||||
|
forward_path: to,
|
||||||
|
reverse_path: from,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Destination addresses of the envelope
|
||||||
|
pub fn to(&self) -> &[EmailAddress] {
|
||||||
|
self.forward_path.as_slice()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Source address of the envelope
|
||||||
|
pub fn from(&self) -> Option<&EmailAddress> {
|
||||||
|
self.reverse_path.as_ref()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a new builder
|
||||||
|
pub fn builder() -> EnvelopeBuilder {
|
||||||
|
EnvelopeBuilder::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Simple email envelope representation
|
||||||
|
#[derive(PartialEq, Eq, Clone, Debug, Default)]
|
||||||
|
pub struct EnvelopeBuilder {
|
||||||
|
/// The envelope recipients' addresses
|
||||||
|
to: Vec<EmailAddress>,
|
||||||
|
/// The envelope sender address
|
||||||
|
from: Option<EmailAddress>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl EnvelopeBuilder {
|
||||||
|
/// Constructs an envelope with no recipients and an empty sender
|
||||||
|
pub fn new() -> Self {
|
||||||
|
EnvelopeBuilder {
|
||||||
|
to: vec![],
|
||||||
|
from: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a recipient
|
||||||
|
pub fn to<S: Into<EmailAddress>>(mut self, address: S) -> Self {
|
||||||
|
self.add_to(address);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a recipient
|
||||||
|
pub fn add_to<S: Into<EmailAddress>>(&mut self, address: S) {
|
||||||
|
self.to.push(address.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the sender
|
||||||
|
pub fn from<S: Into<EmailAddress>>(mut self, address: S) -> Self {
|
||||||
|
self.set_from(address);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Sets the sender
|
||||||
|
pub fn set_from<S: Into<EmailAddress>>(&mut self, address: S) {
|
||||||
|
self.from = Some(address.into());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Build the envelope
|
||||||
|
pub fn build(self) -> EmailResult<Envelope> {
|
||||||
|
Envelope::new(self.from, self.to)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Email sendable by an SMTP client
|
/// Email sendable by an SMTP client
|
||||||
pub trait SendableEmail<'a, T: Read + 'a> {
|
pub trait SendableEmail<'a, T: Read + 'a> {
|
||||||
/// To
|
/// Envelope
|
||||||
fn to(&self) -> Vec<EmailAddress>;
|
fn envelope(&self) -> Envelope;
|
||||||
/// From
|
|
||||||
fn from(&self) -> EmailAddress;
|
|
||||||
/// Message ID, used for logging
|
/// Message ID, used for logging
|
||||||
fn message_id(&self) -> String;
|
fn message_id(&self) -> String;
|
||||||
/// Message content
|
/// Message content
|
||||||
@@ -83,10 +221,8 @@ pub trait EmailTransport<'a, U: Read + 'a, V> {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct SimpleSendableEmail {
|
pub struct SimpleSendableEmail {
|
||||||
/// To
|
/// Envelope
|
||||||
to: Vec<EmailAddress>,
|
envelope: Envelope,
|
||||||
/// From
|
|
||||||
from: EmailAddress,
|
|
||||||
/// Message ID
|
/// Message ID
|
||||||
message_id: String,
|
message_id: String,
|
||||||
/// Message content
|
/// Message content
|
||||||
@@ -96,27 +232,39 @@ pub struct SimpleSendableEmail {
|
|||||||
impl SimpleSendableEmail {
|
impl SimpleSendableEmail {
|
||||||
/// Returns a new email
|
/// Returns a new email
|
||||||
pub fn new(
|
pub fn new(
|
||||||
from_address: EmailAddress,
|
from_address: String,
|
||||||
to_addresses: Vec<EmailAddress>,
|
to_addresses: &[String],
|
||||||
|
message_id: String,
|
||||||
|
message: String,
|
||||||
|
) -> EmailResult<SimpleSendableEmail> {
|
||||||
|
let to: Result<Vec<EmailAddress>, Error> = to_addresses
|
||||||
|
.iter()
|
||||||
|
.map(|x| EmailAddress::new(x.clone()))
|
||||||
|
.collect();
|
||||||
|
Ok(SimpleSendableEmail::new_with_envelope(
|
||||||
|
Envelope::new(Some(EmailAddress::new(from_address)?), to?)?,
|
||||||
|
message_id,
|
||||||
|
message,
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a new email from a valid envelope
|
||||||
|
pub fn new_with_envelope(
|
||||||
|
envelope: Envelope,
|
||||||
message_id: String,
|
message_id: String,
|
||||||
message: String,
|
message: String,
|
||||||
) -> SimpleSendableEmail {
|
) -> SimpleSendableEmail {
|
||||||
SimpleSendableEmail {
|
SimpleSendableEmail {
|
||||||
from: from_address,
|
envelope,
|
||||||
to: to_addresses,
|
message_id,
|
||||||
message_id: message_id,
|
|
||||||
message: message.into_bytes(),
|
message: message.into_bytes(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SendableEmail<'a, &'a [u8]> for SimpleSendableEmail {
|
impl<'a> SendableEmail<'a, &'a [u8]> for SimpleSendableEmail {
|
||||||
fn to(&self) -> Vec<EmailAddress> {
|
fn envelope(&self) -> Envelope {
|
||||||
self.to.clone()
|
self.envelope.clone()
|
||||||
}
|
|
||||||
|
|
||||||
fn from(&self) -> EmailAddress {
|
|
||||||
self.from.clone()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn message_id(&self) -> String {
|
fn message_id(&self) -> String {
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ impl StdError for Error {
|
|||||||
|
|
||||||
fn cause(&self) -> Option<&StdError> {
|
fn cause(&self) -> Option<&StdError> {
|
||||||
match *self {
|
match *self {
|
||||||
Io(ref err) => Some(&*err as &StdError),
|
Io(ref err) => Some(&*err),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +1,5 @@
|
|||||||
//! The sendmail transport sends the email using the local sendmail command.
|
//! The sendmail transport sends the email using the local sendmail command.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
|
||||||
//! use lettre::sendmail::SendmailTransport;
|
|
||||||
//! use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress};
|
|
||||||
//!
|
|
||||||
//! let email = SimpleSendableEmail::new(
|
|
||||||
//! EmailAddress::new("user@localhost".to_string()),
|
|
||||||
//! vec![EmailAddress::new("root@localhost".to_string())],
|
|
||||||
//! "message_id".to_string(),
|
|
||||||
//! "Hello world".to_string(),
|
|
||||||
//! );
|
|
||||||
//!
|
|
||||||
//! let mut sender = SendmailTransport::new();
|
|
||||||
//! let result = sender.send(&email);
|
|
||||||
//! assert!(result.is_ok());
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use {EmailTransport, SendableEmail};
|
use {EmailTransport, SendableEmail};
|
||||||
use sendmail::error::SendmailResult;
|
use sendmail::error::SendmailResult;
|
||||||
@@ -26,6 +11,7 @@ pub mod error;
|
|||||||
|
|
||||||
/// Sends an email using the `sendmail` command
|
/// Sends an email using the `sendmail` command
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct SendmailTransport {
|
pub struct SendmailTransport {
|
||||||
command: String,
|
command: String,
|
||||||
}
|
}
|
||||||
@@ -33,28 +19,35 @@ pub struct SendmailTransport {
|
|||||||
impl SendmailTransport {
|
impl SendmailTransport {
|
||||||
/// Creates a new transport with the default `/usr/sbin/sendmail` command
|
/// Creates a new transport with the default `/usr/sbin/sendmail` command
|
||||||
pub fn new() -> SendmailTransport {
|
pub fn new() -> SendmailTransport {
|
||||||
SendmailTransport { command: "/usr/sbin/sendmail".to_string() }
|
SendmailTransport {
|
||||||
|
command: "/usr/sbin/sendmail".to_string(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new transport to the given sendmail command
|
/// Creates a new transport to the given sendmail command
|
||||||
pub fn new_with_command<S: Into<String>>(command: S) -> SendmailTransport {
|
pub fn new_with_command<S: Into<String>>(command: S) -> SendmailTransport {
|
||||||
SendmailTransport { command: command.into() }
|
SendmailTransport {
|
||||||
|
command: command.into(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a, T: Read + 'a> EmailTransport<'a, T, SendmailResult> for SendmailTransport {
|
impl<'a, T: Read + 'a> EmailTransport<'a, T, SendmailResult> for SendmailTransport {
|
||||||
fn send<U: SendableEmail<'a, T> + 'a>(&mut self, email: &'a U) -> SendmailResult {
|
fn send<U: SendableEmail<'a, T> + 'a>(&mut self, email: &'a U) -> SendmailResult {
|
||||||
|
let envelope = email.envelope();
|
||||||
|
|
||||||
// Spawn the sendmail command
|
// Spawn the sendmail command
|
||||||
let to_addresses: Vec<String> = email.to().iter().map(|x| x.to_string()).collect();
|
let to_addresses: Vec<String> = envelope.to().iter().map(|x| x.to_string()).collect();
|
||||||
let mut process = Command::new(&self.command)
|
let mut process = Command::new(&self.command)
|
||||||
.args(
|
.args(&[
|
||||||
&[
|
|
||||||
"-i",
|
"-i",
|
||||||
"-f",
|
"-f",
|
||||||
&email.from().to_string(),
|
&match envelope.from() {
|
||||||
|
Some(address) => address.to_string(),
|
||||||
|
None => "\"\"".to_string(),
|
||||||
|
},
|
||||||
&to_addresses.join(" "),
|
&to_addresses.join(" "),
|
||||||
],
|
])
|
||||||
)
|
|
||||||
.stdin(Stdio::piped())
|
.stdin(Stdio::piped())
|
||||||
.stdout(Stdio::piped())
|
.stdout(Stdio::piped())
|
||||||
.spawn()?;
|
.spawn()?;
|
||||||
@@ -62,9 +55,12 @@ impl<'a, T: Read + 'a> EmailTransport<'a, T, SendmailResult> for SendmailTranspo
|
|||||||
let mut message_content = String::new();
|
let mut message_content = String::new();
|
||||||
let _ = email.message().read_to_string(&mut message_content);
|
let _ = email.message().read_to_string(&mut message_content);
|
||||||
|
|
||||||
match process.stdin.as_mut().unwrap().write_all(
|
match process
|
||||||
message_content.as_bytes(),
|
.stdin
|
||||||
) {
|
.as_mut()
|
||||||
|
.unwrap()
|
||||||
|
.write_all(message_content.as_bytes())
|
||||||
|
{
|
||||||
Ok(_) => (),
|
Ok(_) => (),
|
||||||
Err(error) => return Err(From::from(error)),
|
Err(error) => return Err(From::from(error)),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,30 +7,28 @@ use crypto::mac::Mac;
|
|||||||
#[cfg(feature = "crammd5-auth")]
|
#[cfg(feature = "crammd5-auth")]
|
||||||
use crypto::md5::Md5;
|
use crypto::md5::Md5;
|
||||||
#[cfg(feature = "crammd5-auth")]
|
#[cfg(feature = "crammd5-auth")]
|
||||||
use hex::ToHex;
|
use hex;
|
||||||
use smtp::NUL;
|
use smtp::NUL;
|
||||||
use smtp::error::Error;
|
use smtp::error::Error;
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
|
||||||
/// Accepted authentication mecanisms on an encrypted connection
|
/// Accepted authentication mechanisms on an encrypted connection
|
||||||
/// Trying LOGIN last as it is deprecated.
|
/// Trying LOGIN last as it is deprecated.
|
||||||
#[cfg(feature = "crammd5-auth")]
|
#[cfg(feature = "crammd5-auth")]
|
||||||
pub const DEFAULT_ENCRYPTED_MECHANISMS: &'static [Mechanism] =
|
pub const DEFAULT_ENCRYPTED_MECHANISMS: &[Mechanism] =
|
||||||
&[Mechanism::Plain, Mechanism::CramMd5, Mechanism::Login];
|
&[Mechanism::Plain, Mechanism::CramMd5, Mechanism::Login];
|
||||||
/// Accepted authentication mecanisms on an encrypted connection
|
/// Accepted authentication mechanisms on an encrypted connection
|
||||||
/// Trying LOGIN last as it is deprecated.
|
/// Trying LOGIN last as it is deprecated.
|
||||||
#[cfg(not(feature = "crammd5-auth"))]
|
#[cfg(not(feature = "crammd5-auth"))]
|
||||||
pub const DEFAULT_ENCRYPTED_MECHANISMS: &'static [Mechanism] =
|
pub const DEFAULT_ENCRYPTED_MECHANISMS: &[Mechanism] = &[Mechanism::Plain, Mechanism::Login];
|
||||||
&[Mechanism::Plain, Mechanism::Login];
|
|
||||||
|
|
||||||
/// Accepted authentication mecanisms on an unencrypted connection
|
/// Accepted authentication mechanisms on an unencrypted connection
|
||||||
#[cfg(feature = "crammd5-auth")]
|
#[cfg(feature = "crammd5-auth")]
|
||||||
pub const DEFAULT_UNENCRYPTED_MECHANISMS: &'static [Mechanism] = &[Mechanism::CramMd5];
|
pub const DEFAULT_UNENCRYPTED_MECHANISMS: &[Mechanism] = &[Mechanism::CramMd5];
|
||||||
/// Accepted authentication mecanisms on an unencrypted connection
|
/// Accepted authentication mechanisms on an unencrypted connection
|
||||||
/// When CRAMMD5 support is not enabled, no mechanisms are allowed.
|
/// When CRAMMD5 support is not enabled, no mechanisms are allowed.
|
||||||
#[cfg(not(feature = "crammd5-auth"))]
|
#[cfg(not(feature = "crammd5-auth"))]
|
||||||
pub const DEFAULT_UNENCRYPTED_MECHANISMS: &'static [Mechanism] = &[];
|
pub const DEFAULT_UNENCRYPTED_MECHANISMS: &[Mechanism] = &[];
|
||||||
|
|
||||||
|
|
||||||
/// Convertable to user credentials
|
/// Convertable to user credentials
|
||||||
pub trait IntoCredentials {
|
pub trait IntoCredentials {
|
||||||
@@ -53,6 +51,7 @@ impl<S: Into<String>, T: Into<String>> IntoCredentials for (S, T) {
|
|||||||
|
|
||||||
/// Contains user credentials
|
/// Contains user credentials
|
||||||
#[derive(PartialEq, Eq, Clone, Hash, Debug)]
|
#[derive(PartialEq, Eq, Clone, Hash, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct Credentials {
|
pub struct Credentials {
|
||||||
username: String,
|
username: String,
|
||||||
password: String,
|
password: String,
|
||||||
@@ -61,15 +60,13 @@ pub struct Credentials {
|
|||||||
impl Credentials {
|
impl Credentials {
|
||||||
/// Create a `Credentials` struct from username and password
|
/// Create a `Credentials` struct from username and password
|
||||||
pub fn new(username: String, password: String) -> Credentials {
|
pub fn new(username: String, password: String) -> Credentials {
|
||||||
Credentials {
|
Credentials { username, password }
|
||||||
username: username,
|
|
||||||
password: password,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents authentication mechanisms
|
/// Represents authentication mechanisms
|
||||||
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
|
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub enum Mechanism {
|
pub enum Mechanism {
|
||||||
/// PLAIN authentication mechanism
|
/// PLAIN authentication mechanism
|
||||||
/// RFC 4616: https://tools.ietf.org/html/rfc4616
|
/// RFC 4616: https://tools.ietf.org/html/rfc4616
|
||||||
@@ -119,18 +116,13 @@ impl Mechanism {
|
|||||||
challenge: Option<&str>,
|
challenge: Option<&str>,
|
||||||
) -> Result<String, Error> {
|
) -> Result<String, Error> {
|
||||||
match *self {
|
match *self {
|
||||||
Mechanism::Plain => {
|
Mechanism::Plain => match challenge {
|
||||||
match challenge {
|
|
||||||
Some(_) => Err(Error::Client("This mechanism does not expect a challenge")),
|
Some(_) => Err(Error::Client("This mechanism does not expect a challenge")),
|
||||||
None => Ok(format!(
|
None => Ok(format!(
|
||||||
"{}{}{}{}",
|
"{}{}{}{}",
|
||||||
NUL,
|
NUL, credentials.username, NUL, credentials.password
|
||||||
credentials.username,
|
|
||||||
NUL,
|
|
||||||
credentials.password
|
|
||||||
)),
|
)),
|
||||||
}
|
},
|
||||||
}
|
|
||||||
Mechanism::Login => {
|
Mechanism::Login => {
|
||||||
let decoded_challenge = match challenge {
|
let decoded_challenge = match challenge {
|
||||||
Some(challenge) => challenge,
|
Some(challenge) => challenge,
|
||||||
@@ -160,7 +152,7 @@ impl Mechanism {
|
|||||||
Ok(format!(
|
Ok(format!(
|
||||||
"{} {}",
|
"{} {}",
|
||||||
credentials.username,
|
credentials.username,
|
||||||
hmac.result().code().to_hex()
|
hex::encode(hmac.result().code())
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -212,7 +204,7 @@ mod test {
|
|||||||
mechanism
|
mechanism
|
||||||
.response(
|
.response(
|
||||||
&credentials,
|
&credentials,
|
||||||
Some("PDE3ODkzLjEzMjA2NzkxMjNAdGVzc2VyYWN0LnN1c2FtLmluPg=="),
|
Some("PDE3ODkzLjEzMjA2NzkxMjNAdGVzc2VyYWN0LnN1c2FtLmluPg==")
|
||||||
)
|
)
|
||||||
.unwrap(),
|
.unwrap(),
|
||||||
"alice a540ebe4ef2304070bbc3c456c1f64c0"
|
"alice a540ebe4ef2304070bbc3c456c1f64c0"
|
||||||
|
|||||||
@@ -41,11 +41,11 @@ impl MockStream {
|
|||||||
vec
|
vec
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next_vec(&mut self, vec: Vec<u8>) {
|
pub fn next_vec(&mut self, vec: &[u8]) {
|
||||||
let mut cursor = self.reader.lock().unwrap();
|
let mut cursor = self.reader.lock().unwrap();
|
||||||
cursor.set_position(0);
|
cursor.set_position(0);
|
||||||
cursor.get_mut().clear();
|
cursor.get_mut().clear();
|
||||||
cursor.get_mut().extend_from_slice(vec.as_slice());
|
cursor.get_mut().extend_from_slice(vec);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn swap(&mut self) {
|
pub fn swap(&mut self) {
|
||||||
|
|||||||
@@ -1,12 +1,13 @@
|
|||||||
//! SMTP client
|
//! SMTP client
|
||||||
|
|
||||||
use bufstream::BufStream;
|
use bufstream::BufStream;
|
||||||
|
use nom::ErrorKind as NomErrorKind;
|
||||||
use smtp::{CRLF, MESSAGE_ENDING};
|
use smtp::{CRLF, MESSAGE_ENDING};
|
||||||
use smtp::authentication::{Credentials, Mechanism};
|
use smtp::authentication::{Credentials, Mechanism};
|
||||||
use smtp::client::net::{ClientTlsParameters, Connector, NetworkStream, Timeout};
|
use smtp::client::net::{ClientTlsParameters, Connector, NetworkStream, Timeout};
|
||||||
use smtp::commands::*;
|
use smtp::commands::*;
|
||||||
use smtp::error::{Error, SmtpResult};
|
use smtp::error::{Error, SmtpResult};
|
||||||
use smtp::response::ResponseParser;
|
use smtp::response::Response;
|
||||||
use std::fmt::{Debug, Display};
|
use std::fmt::{Debug, Display};
|
||||||
use std::io::{self, BufRead, BufReader, Read, Write};
|
use std::io::{self, BufRead, BufReader, Read, Write};
|
||||||
use std::net::ToSocketAddrs;
|
use std::net::ToSocketAddrs;
|
||||||
@@ -17,7 +18,8 @@ pub mod net;
|
|||||||
pub mod mock;
|
pub mod mock;
|
||||||
|
|
||||||
/// The codec used for transparency
|
/// The codec used for transparency
|
||||||
#[derive(Default, Debug)]
|
#[derive(Default, Clone, Copy, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct ClientCodec {
|
pub struct ClientCodec {
|
||||||
escape_count: u8,
|
escape_count: u8,
|
||||||
}
|
}
|
||||||
@@ -60,9 +62,9 @@ impl ClientCodec {
|
|||||||
start = idx;
|
start = idx;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(buf.write_all(&frame[start..])?)
|
buf.write_all(&frame[start..])?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,12 +75,6 @@ fn escape_crlf(string: &str) -> String {
|
|||||||
string.replace(CRLF, "<CRLF>")
|
string.replace(CRLF, "<CRLF>")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the string removing all the CRLF
|
|
||||||
/// Used for debug displays
|
|
||||||
fn remove_crlf(string: &str) -> String {
|
|
||||||
string.replace(CRLF, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Structure that implements the SMTP client
|
/// Structure that implements the SMTP client
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct Client<S: Write + Read = NetworkStream> {
|
pub struct Client<S: Write + Read = NetworkStream> {
|
||||||
@@ -106,7 +102,7 @@ impl<S: Write + Read> Client<S> {
|
|||||||
impl<S: Connector + Write + Read + Timeout + Debug> Client<S> {
|
impl<S: Connector + Write + Read + Timeout + Debug> Client<S> {
|
||||||
/// Closes the SMTP transaction if possible
|
/// Closes the SMTP transaction if possible
|
||||||
pub fn close(&mut self) {
|
pub fn close(&mut self) {
|
||||||
let _ = self.smtp_command(QuitCommand);
|
let _ = self.command(QuitCommand);
|
||||||
self.stream = None;
|
self.stream = None;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -166,29 +162,27 @@ impl<S: Connector + Write + Read + Timeout + Debug> Client<S> {
|
|||||||
// Try to connect
|
// Try to connect
|
||||||
self.set_stream(Connector::connect(&server_addr, tls_parameters)?);
|
self.set_stream(Connector::connect(&server_addr, tls_parameters)?);
|
||||||
|
|
||||||
self.get_reply()
|
self.read_response()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Checks if the server is connected using the NOOP SMTP command
|
/// Checks if the server is connected using the NOOP SMTP command
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(wrong_self_convention))]
|
#[cfg_attr(feature = "cargo-clippy", allow(wrong_self_convention))]
|
||||||
pub fn is_connected(&mut self) -> bool {
|
pub fn is_connected(&mut self) -> bool {
|
||||||
self.smtp_command(NoopCommand).is_ok()
|
self.command(NoopCommand).is_ok()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends an AUTH command with the given mechanism, and handles challenge if needed
|
/// Sends an AUTH command with the given mechanism, and handles challenge if needed
|
||||||
pub fn auth(&mut self, mechanism: Mechanism, credentials: &Credentials) -> SmtpResult {
|
pub fn auth(&mut self, mechanism: Mechanism, credentials: &Credentials) -> SmtpResult {
|
||||||
// TODO
|
// TODO
|
||||||
let mut challenges = 10;
|
let mut challenges = 10;
|
||||||
let mut response = self.smtp_command(
|
let mut response = self.command(AuthCommand::new(mechanism, credentials.clone(), None)?)?;
|
||||||
AuthCommand::new(mechanism, credentials.clone(), None)?,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
while challenges > 0 && response.has_code(334) {
|
while challenges > 0 && response.has_code(334) {
|
||||||
challenges -= 1;
|
challenges -= 1;
|
||||||
response = self.smtp_command(AuthCommand::new_from_response(
|
response = self.command(AuthCommand::new_from_response(
|
||||||
mechanism,
|
mechanism,
|
||||||
credentials.clone(),
|
credentials.clone(),
|
||||||
response,
|
&response,
|
||||||
)?)?;
|
)?)?;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,8 +203,11 @@ impl<S: Connector + Write + Read + Timeout + Debug> Client<S> {
|
|||||||
out_buf.clear();
|
out_buf.clear();
|
||||||
|
|
||||||
let consumed = match message_reader.fill_buf() {
|
let consumed = match message_reader.fill_buf() {
|
||||||
Ok(bytes) => { codec.encode(bytes, &mut out_buf)?; bytes.len() },
|
Ok(bytes) => {
|
||||||
Err(ref err) => panic!("Failed with: {}", err)
|
codec.encode(bytes, &mut out_buf)?;
|
||||||
|
bytes.len()
|
||||||
|
}
|
||||||
|
Err(ref err) => panic!("Failed with: {}", err),
|
||||||
};
|
};
|
||||||
message_reader.consume(consumed);
|
message_reader.consume(consumed);
|
||||||
|
|
||||||
@@ -218,21 +215,21 @@ impl<S: Connector + Write + Read + Timeout + Debug> Client<S> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.write_server(out_buf.as_slice())?;
|
self.write(out_buf.as_slice())?;
|
||||||
}
|
}
|
||||||
|
|
||||||
self.write_server(MESSAGE_ENDING.as_bytes())?;
|
self.write(MESSAGE_ENDING.as_bytes())?;
|
||||||
self.get_reply()
|
self.read_response()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends an SMTP command
|
/// Sends an SMTP command
|
||||||
pub fn smtp_command<C: Display>(&mut self, command: C) -> SmtpResult {
|
pub fn command<C: Display>(&mut self, command: C) -> SmtpResult {
|
||||||
self.write_server(command.to_string().as_bytes())?;
|
self.write(command.to_string().as_bytes())?;
|
||||||
self.get_reply()
|
self.read_response()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Writes a string to the server
|
/// Writes a string to the server
|
||||||
fn write_server(&mut self, string: &[u8]) -> Result<(), Error> {
|
fn write(&mut self, string: &[u8]) -> Result<(), Error> {
|
||||||
if self.stream.is_none() {
|
if self.stream.is_none() {
|
||||||
return Err(From::from("Connection closed"));
|
return Err(From::from("Connection closed"));
|
||||||
}
|
}
|
||||||
@@ -248,33 +245,34 @@ impl<S: Connector + Write + Read + Timeout + Debug> Client<S> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the SMTP response
|
/// Gets the SMTP response
|
||||||
fn get_reply(&mut self) -> SmtpResult {
|
fn read_response(&mut self) -> SmtpResult {
|
||||||
|
let mut raw_response = String::new();
|
||||||
|
let mut response = raw_response.parse::<Response>();
|
||||||
|
|
||||||
let mut parser = ResponseParser::default();
|
while response.is_err() {
|
||||||
|
if response.as_ref().err().unwrap() != &NomErrorKind::Complete {
|
||||||
let mut line = String::new();
|
break;
|
||||||
self.stream.as_mut().unwrap().read_line(&mut line)?;
|
}
|
||||||
|
// TODO read more than one line
|
||||||
debug!("Read: {}", escape_crlf(line.as_ref()));
|
self.stream.as_mut().unwrap().read_line(&mut raw_response)?;
|
||||||
|
response = raw_response.parse::<Response>();
|
||||||
while parser.read_line(remove_crlf(line.as_ref()).as_ref())? {
|
|
||||||
line.clear();
|
|
||||||
self.stream.as_mut().unwrap().read_line(&mut line)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let response = parser.response()?;
|
debug!("Read: {}", escape_crlf(raw_response.as_ref()));
|
||||||
|
|
||||||
if response.is_positive() {
|
let final_response = response?;
|
||||||
Ok(response)
|
|
||||||
|
if final_response.is_positive() {
|
||||||
|
Ok(final_response)
|
||||||
} else {
|
} else {
|
||||||
Err(From::from(response))
|
Err(From::from(final_response))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::{ClientCodec, escape_crlf, remove_crlf};
|
use super::{escape_crlf, ClientCodec};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_codec() {
|
fn test_codec() {
|
||||||
@@ -296,16 +294,6 @@ mod test {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_remove_crlf() {
|
|
||||||
assert_eq!(remove_crlf("\r\n"), "");
|
|
||||||
assert_eq!(remove_crlf("EHLO my_name\r\n"), "EHLO my_name");
|
|
||||||
assert_eq!(
|
|
||||||
remove_crlf("EHLO my_name\r\nSIZE 42\r\n"),
|
|
||||||
"EHLO my_nameSIZE 42"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_escape_crlf() {
|
fn test_escape_crlf() {
|
||||||
assert_eq!(escape_crlf("\r\n"), "<CRLF>");
|
assert_eq!(escape_crlf("\r\n"), "<CRLF>");
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! A trait to represent a stream
|
//! A trait to represent a stream
|
||||||
|
|
||||||
use native_tls::{TlsConnector, TlsStream, Protocol};
|
use native_tls::{Protocol, TlsConnector, TlsStream};
|
||||||
use smtp::client::mock::MockStream;
|
use smtp::client::mock::MockStream;
|
||||||
use std::io::{self, ErrorKind, Read, Write};
|
use std::io::{self, ErrorKind, Read, Write};
|
||||||
use std::net::{Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, TcpStream};
|
use std::net::{Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4, TcpStream};
|
||||||
@@ -8,6 +8,7 @@ use std::time::Duration;
|
|||||||
|
|
||||||
/// Parameters to use for secure clients
|
/// Parameters to use for secure clients
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct ClientTlsParameters {
|
pub struct ClientTlsParameters {
|
||||||
/// A connector from `native-tls`
|
/// A connector from `native-tls`
|
||||||
pub connector: TlsConnector,
|
pub connector: TlsConnector,
|
||||||
@@ -18,16 +19,13 @@ pub struct ClientTlsParameters {
|
|||||||
impl ClientTlsParameters {
|
impl ClientTlsParameters {
|
||||||
/// Creates a `ClientTlsParameters`
|
/// Creates a `ClientTlsParameters`
|
||||||
pub fn new(domain: String, connector: TlsConnector) -> ClientTlsParameters {
|
pub fn new(domain: String, connector: TlsConnector) -> ClientTlsParameters {
|
||||||
ClientTlsParameters {
|
ClientTlsParameters { connector, domain }
|
||||||
connector: connector,
|
|
||||||
domain: domain,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Accepted protocols by default.
|
/// Accepted protocols by default.
|
||||||
/// This removes TLS 1.0 compared to tls-native defaults.
|
/// This removes TLS 1.0 compared to tls-native defaults.
|
||||||
pub const DEFAULT_TLS_PROTOCOLS : &'static [Protocol] = &[Protocol::Tlsv11, Protocol::Tlsv12];
|
pub const DEFAULT_TLS_PROTOCOLS: &[Protocol] = &[Protocol::Tlsv11, Protocol::Tlsv12];
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
/// Represents the different types of underlying network streams
|
/// Represents the different types of underlying network streams
|
||||||
@@ -46,11 +44,10 @@ impl NetworkStream {
|
|||||||
match *self {
|
match *self {
|
||||||
NetworkStream::Tcp(ref s) => s.peer_addr(),
|
NetworkStream::Tcp(ref s) => s.peer_addr(),
|
||||||
NetworkStream::Tls(ref s) => s.get_ref().peer_addr(),
|
NetworkStream::Tls(ref s) => s.get_ref().peer_addr(),
|
||||||
NetworkStream::Mock(_) => {
|
NetworkStream::Mock(_) => Ok(SocketAddr::V4(SocketAddrV4::new(
|
||||||
Ok(SocketAddr::V4(
|
Ipv4Addr::new(127, 0, 0, 1),
|
||||||
SocketAddrV4::new(Ipv4Addr::new(127, 0, 0, 1), 80),
|
80,
|
||||||
))
|
))),
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,13 +108,11 @@ impl Connector for NetworkStream {
|
|||||||
let tcp_stream = TcpStream::connect(addr)?;
|
let tcp_stream = TcpStream::connect(addr)?;
|
||||||
|
|
||||||
match tls_parameters {
|
match tls_parameters {
|
||||||
Some(context) => {
|
Some(context) => context
|
||||||
context
|
|
||||||
.connector
|
.connector
|
||||||
.connect(context.domain.as_ref(), tcp_stream)
|
.connect(context.domain.as_ref(), tcp_stream)
|
||||||
.map(NetworkStream::Tls)
|
.map(NetworkStream::Tls)
|
||||||
.map_err(|e| io::Error::new(ErrorKind::Other, e))
|
.map_err(|e| io::Error::new(ErrorKind::Other, e)),
|
||||||
}
|
|
||||||
None => Ok(NetworkStream::Tcp(tcp_stream)),
|
None => Ok(NetworkStream::Tcp(tcp_stream)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,15 +120,13 @@ impl Connector for NetworkStream {
|
|||||||
#[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
|
#[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))]
|
||||||
fn upgrade_tls(&mut self, tls_parameters: &ClientTlsParameters) -> io::Result<()> {
|
fn upgrade_tls(&mut self, tls_parameters: &ClientTlsParameters) -> io::Result<()> {
|
||||||
*self = match *self {
|
*self = match *self {
|
||||||
NetworkStream::Tcp(ref mut stream) => {
|
NetworkStream::Tcp(ref mut stream) => match tls_parameters
|
||||||
match tls_parameters.connector.connect(
|
.connector
|
||||||
tls_parameters.domain.as_ref(),
|
.connect(tls_parameters.domain.as_ref(), stream.try_clone().unwrap())
|
||||||
stream.try_clone().unwrap(),
|
{
|
||||||
) {
|
|
||||||
Ok(tls_stream) => NetworkStream::Tls(tls_stream),
|
Ok(tls_stream) => NetworkStream::Tls(tls_stream),
|
||||||
Err(err) => return Err(io::Error::new(ErrorKind::Other, err)),
|
Err(err) => return Err(io::Error::new(ErrorKind::Other, err)),
|
||||||
}
|
},
|
||||||
}
|
|
||||||
NetworkStream::Tls(_) => return Ok(()),
|
NetworkStream::Tls(_) => return Ok(()),
|
||||||
NetworkStream::Mock(_) => return Ok(()),
|
NetworkStream::Mock(_) => return Ok(()),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
|
|
||||||
/// EHLO command
|
/// EHLO command
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct EhloCommand {
|
pub struct EhloCommand {
|
||||||
client_id: ClientId,
|
client_id: ClientId,
|
||||||
}
|
}
|
||||||
@@ -26,12 +27,13 @@ impl Display for EhloCommand {
|
|||||||
impl EhloCommand {
|
impl EhloCommand {
|
||||||
/// Creates a EHLO command
|
/// Creates a EHLO command
|
||||||
pub fn new(client_id: ClientId) -> EhloCommand {
|
pub fn new(client_id: ClientId) -> EhloCommand {
|
||||||
EhloCommand { client_id: client_id }
|
EhloCommand { client_id }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// STARTTLS command
|
/// STARTTLS command
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug, Copy)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct StarttlsCommand;
|
pub struct StarttlsCommand;
|
||||||
|
|
||||||
impl Display for StarttlsCommand {
|
impl Display for StarttlsCommand {
|
||||||
@@ -43,6 +45,7 @@ impl Display for StarttlsCommand {
|
|||||||
|
|
||||||
/// MAIL command
|
/// MAIL command
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct MailCommand {
|
pub struct MailCommand {
|
||||||
sender: Option<EmailAddress>,
|
sender: Option<EmailAddress>,
|
||||||
parameters: Vec<MailParameter>,
|
parameters: Vec<MailParameter>,
|
||||||
@@ -68,15 +71,13 @@ impl Display for MailCommand {
|
|||||||
impl MailCommand {
|
impl MailCommand {
|
||||||
/// Creates a MAIL command
|
/// Creates a MAIL command
|
||||||
pub fn new(sender: Option<EmailAddress>, parameters: Vec<MailParameter>) -> MailCommand {
|
pub fn new(sender: Option<EmailAddress>, parameters: Vec<MailParameter>) -> MailCommand {
|
||||||
MailCommand {
|
MailCommand { sender, parameters }
|
||||||
sender: sender,
|
|
||||||
parameters: parameters,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RCPT command
|
/// RCPT command
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct RcptCommand {
|
pub struct RcptCommand {
|
||||||
recipient: EmailAddress,
|
recipient: EmailAddress,
|
||||||
parameters: Vec<RcptParameter>,
|
parameters: Vec<RcptParameter>,
|
||||||
@@ -96,14 +97,15 @@ impl RcptCommand {
|
|||||||
/// Creates an RCPT command
|
/// Creates an RCPT command
|
||||||
pub fn new(recipient: EmailAddress, parameters: Vec<RcptParameter>) -> RcptCommand {
|
pub fn new(recipient: EmailAddress, parameters: Vec<RcptParameter>) -> RcptCommand {
|
||||||
RcptCommand {
|
RcptCommand {
|
||||||
recipient: recipient,
|
recipient,
|
||||||
parameters: parameters,
|
parameters,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// DATA command
|
/// DATA command
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug, Copy)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct DataCommand;
|
pub struct DataCommand;
|
||||||
|
|
||||||
impl Display for DataCommand {
|
impl Display for DataCommand {
|
||||||
@@ -114,7 +116,8 @@ impl Display for DataCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// QUIT command
|
/// QUIT command
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug, Copy)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct QuitCommand;
|
pub struct QuitCommand;
|
||||||
|
|
||||||
impl Display for QuitCommand {
|
impl Display for QuitCommand {
|
||||||
@@ -125,7 +128,8 @@ impl Display for QuitCommand {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// NOOP command
|
/// NOOP command
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug, Copy)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct NoopCommand;
|
pub struct NoopCommand;
|
||||||
|
|
||||||
impl Display for NoopCommand {
|
impl Display for NoopCommand {
|
||||||
@@ -137,6 +141,7 @@ impl Display for NoopCommand {
|
|||||||
|
|
||||||
/// HELP command
|
/// HELP command
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct HelpCommand {
|
pub struct HelpCommand {
|
||||||
argument: Option<String>,
|
argument: Option<String>,
|
||||||
}
|
}
|
||||||
@@ -154,12 +159,13 @@ impl Display for HelpCommand {
|
|||||||
impl HelpCommand {
|
impl HelpCommand {
|
||||||
/// Creates an HELP command
|
/// Creates an HELP command
|
||||||
pub fn new(argument: Option<String>) -> HelpCommand {
|
pub fn new(argument: Option<String>) -> HelpCommand {
|
||||||
HelpCommand { argument: argument }
|
HelpCommand { argument }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// VRFY command
|
/// VRFY command
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct VrfyCommand {
|
pub struct VrfyCommand {
|
||||||
argument: String,
|
argument: String,
|
||||||
}
|
}
|
||||||
@@ -174,12 +180,13 @@ impl Display for VrfyCommand {
|
|||||||
impl VrfyCommand {
|
impl VrfyCommand {
|
||||||
/// Creates a VRFY command
|
/// Creates a VRFY command
|
||||||
pub fn new(argument: String) -> VrfyCommand {
|
pub fn new(argument: String) -> VrfyCommand {
|
||||||
VrfyCommand { argument: argument }
|
VrfyCommand { argument }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// EXPN command
|
/// EXPN command
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct ExpnCommand {
|
pub struct ExpnCommand {
|
||||||
argument: String,
|
argument: String,
|
||||||
}
|
}
|
||||||
@@ -194,12 +201,13 @@ impl Display for ExpnCommand {
|
|||||||
impl ExpnCommand {
|
impl ExpnCommand {
|
||||||
/// Creates an EXPN command
|
/// Creates an EXPN command
|
||||||
pub fn new(argument: String) -> ExpnCommand {
|
pub fn new(argument: String) -> ExpnCommand {
|
||||||
ExpnCommand { argument: argument }
|
ExpnCommand { argument }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// RSET command
|
/// RSET command
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug, Copy)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct RsetCommand;
|
pub struct RsetCommand;
|
||||||
|
|
||||||
impl Display for RsetCommand {
|
impl Display for RsetCommand {
|
||||||
@@ -211,6 +219,7 @@ impl Display for RsetCommand {
|
|||||||
|
|
||||||
/// AUTH command
|
/// AUTH command
|
||||||
#[derive(PartialEq, Clone, Debug)]
|
#[derive(PartialEq, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct AuthCommand {
|
pub struct AuthCommand {
|
||||||
mechanism: Mechanism,
|
mechanism: Mechanism,
|
||||||
credentials: Credentials,
|
credentials: Credentials,
|
||||||
@@ -249,18 +258,15 @@ impl AuthCommand {
|
|||||||
challenge: Option<String>,
|
challenge: Option<String>,
|
||||||
) -> Result<AuthCommand, Error> {
|
) -> Result<AuthCommand, Error> {
|
||||||
let response = if mechanism.supports_initial_response() || challenge.is_some() {
|
let response = if mechanism.supports_initial_response() || challenge.is_some() {
|
||||||
Some(mechanism.response(
|
Some(mechanism.response(&credentials, challenge.as_ref().map(String::as_str))?)
|
||||||
&credentials,
|
|
||||||
challenge.as_ref().map(String::as_str),
|
|
||||||
)?)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
Ok(AuthCommand {
|
Ok(AuthCommand {
|
||||||
mechanism: mechanism,
|
mechanism,
|
||||||
credentials: credentials,
|
credentials,
|
||||||
challenge: challenge,
|
challenge,
|
||||||
response: response,
|
response,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -269,7 +275,7 @@ impl AuthCommand {
|
|||||||
pub fn new_from_response(
|
pub fn new_from_response(
|
||||||
mechanism: Mechanism,
|
mechanism: Mechanism,
|
||||||
credentials: Credentials,
|
credentials: Credentials,
|
||||||
response: Response,
|
response: &Response,
|
||||||
) -> Result<AuthCommand, Error> {
|
) -> Result<AuthCommand, Error> {
|
||||||
if !response.has_code(334) {
|
if !response.has_code(334) {
|
||||||
return Err(Error::ResponseParsing("Expecting a challenge"));
|
return Err(Error::ResponseParsing("Expecting a challenge"));
|
||||||
@@ -283,27 +289,22 @@ impl AuthCommand {
|
|||||||
debug!("auth encoded challenge: {}", encoded_challenge);
|
debug!("auth encoded challenge: {}", encoded_challenge);
|
||||||
|
|
||||||
let decoded_challenge = match base64::decode(&encoded_challenge) {
|
let decoded_challenge = match base64::decode(&encoded_challenge) {
|
||||||
Ok(challenge) => {
|
Ok(challenge) => match String::from_utf8(challenge) {
|
||||||
match String::from_utf8(challenge) {
|
|
||||||
Ok(value) => value,
|
Ok(value) => value,
|
||||||
Err(error) => return Err(Error::Utf8Parsing(error)),
|
Err(error) => return Err(Error::Utf8Parsing(error)),
|
||||||
}
|
},
|
||||||
}
|
|
||||||
Err(error) => return Err(Error::ChallengeParsing(error)),
|
Err(error) => return Err(Error::ChallengeParsing(error)),
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("auth decoded challenge: {}", decoded_challenge);
|
debug!("auth decoded challenge: {}", decoded_challenge);
|
||||||
|
|
||||||
let response = Some(mechanism.response(
|
let response = Some(mechanism.response(&credentials, Some(decoded_challenge.as_ref()))?);
|
||||||
&credentials,
|
|
||||||
Some(decoded_challenge.as_ref()),
|
|
||||||
)?);
|
|
||||||
|
|
||||||
Ok(AuthCommand {
|
Ok(AuthCommand {
|
||||||
mechanism: mechanism,
|
mechanism,
|
||||||
credentials: credentials,
|
credentials,
|
||||||
challenge: Some(decoded_challenge),
|
challenge: Some(decoded_challenge),
|
||||||
response: response,
|
response,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -313,14 +314,12 @@ mod test {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use smtp::extension::MailBodyParameter;
|
use smtp::extension::MailBodyParameter;
|
||||||
#[cfg(feature = "crammd5-auth")]
|
#[cfg(feature = "crammd5-auth")]
|
||||||
use smtp::response::Code;
|
use smtp::response::{Category, Code, Detail, Severity};
|
||||||
#[cfg(feature = "crammd5-auth")]
|
|
||||||
use std::str::FromStr;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_display() {
|
fn test_display() {
|
||||||
let id = ClientId::Domain("localhost".to_string());
|
let id = ClientId::Domain("localhost".to_string());
|
||||||
let email = EmailAddress::new("test@example.com".to_string());
|
let email = EmailAddress::new("test@example.com".to_string()).unwrap();
|
||||||
let mail_parameter = MailParameter::Other {
|
let mail_parameter = MailParameter::Other {
|
||||||
keyword: "TEST".to_string(),
|
keyword: "TEST".to_string(),
|
||||||
value: Some("value".to_string()),
|
value: Some("value".to_string()),
|
||||||
@@ -418,7 +417,14 @@ mod test {
|
|||||||
AuthCommand::new_from_response(
|
AuthCommand::new_from_response(
|
||||||
Mechanism::CramMd5,
|
Mechanism::CramMd5,
|
||||||
credentials.clone(),
|
credentials.clone(),
|
||||||
Response::new(Code::from_str("334").unwrap(), vec!["dGVzdAo=".to_string()]),
|
&Response::new(
|
||||||
|
Code::new(
|
||||||
|
Severity::PositiveIntermediate,
|
||||||
|
Category::Unspecified3,
|
||||||
|
Detail::Four,
|
||||||
|
),
|
||||||
|
vec!["dGVzdAo=".to_string()],
|
||||||
|
),
|
||||||
).unwrap()
|
).unwrap()
|
||||||
),
|
),
|
||||||
"dXNlciA1NTIzNThiMzExOWFjOWNkYzM2YWRiN2MxNWRmMWJkNw==\r\n"
|
"dXNlciA1NTIzNThiMzExOWFjOWNkYzM2YWRiN2MxNWRmMWJkNw==\r\n"
|
||||||
|
|||||||
@@ -2,13 +2,14 @@
|
|||||||
|
|
||||||
use self::Error::*;
|
use self::Error::*;
|
||||||
use base64::DecodeError;
|
use base64::DecodeError;
|
||||||
|
use native_tls;
|
||||||
|
use nom;
|
||||||
use smtp::response::{Response, Severity};
|
use smtp::response::{Response, Severity};
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::{Display, Formatter};
|
use std::fmt::{Display, Formatter};
|
||||||
use std::io;
|
use std::io;
|
||||||
use std::string::FromUtf8Error;
|
use std::string::FromUtf8Error;
|
||||||
use native_tls;
|
|
||||||
|
|
||||||
/// An enum of all error kinds.
|
/// An enum of all error kinds.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
@@ -35,6 +36,8 @@ pub enum Error {
|
|||||||
Io(io::Error),
|
Io(io::Error),
|
||||||
/// TLS error
|
/// TLS error
|
||||||
Tls(native_tls::Error),
|
Tls(native_tls::Error),
|
||||||
|
/// Parsing error
|
||||||
|
Parsing(nom::simple_errors::Err),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Error {
|
impl Display for Error {
|
||||||
@@ -49,18 +52,14 @@ impl StdError for Error {
|
|||||||
match *self {
|
match *self {
|
||||||
// Try to display the first line of the server's response that usually
|
// Try to display the first line of the server's response that usually
|
||||||
// contains a short humanly readable error message
|
// contains a short humanly readable error message
|
||||||
Transient(ref err) => {
|
Transient(ref err) => match err.first_line() {
|
||||||
match err.first_line() {
|
|
||||||
Some(line) => line,
|
Some(line) => line,
|
||||||
None => "undetailed transient error during SMTP transaction",
|
None => "undetailed transient error during SMTP transaction",
|
||||||
}
|
},
|
||||||
}
|
Permanent(ref err) => match err.first_line() {
|
||||||
Permanent(ref err) => {
|
|
||||||
match err.first_line() {
|
|
||||||
Some(line) => line,
|
Some(line) => line,
|
||||||
None => "undetailed permanent error during SMTP transaction",
|
None => "undetailed permanent error during SMTP transaction",
|
||||||
}
|
},
|
||||||
}
|
|
||||||
ResponseParsing(err) => err,
|
ResponseParsing(err) => err,
|
||||||
ChallengeParsing(ref err) => err.description(),
|
ChallengeParsing(ref err) => err.description(),
|
||||||
Utf8Parsing(ref err) => err.description(),
|
Utf8Parsing(ref err) => err.description(),
|
||||||
@@ -68,15 +67,17 @@ impl StdError for Error {
|
|||||||
Client(err) => err,
|
Client(err) => err,
|
||||||
Io(ref err) => err.description(),
|
Io(ref err) => err.description(),
|
||||||
Tls(ref err) => err.description(),
|
Tls(ref err) => err.description(),
|
||||||
|
Parsing(ref err) => err.description(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn cause(&self) -> Option<&StdError> {
|
fn cause(&self) -> Option<&StdError> {
|
||||||
match *self {
|
match *self {
|
||||||
ChallengeParsing(ref err) => Some(&*err as &StdError),
|
ChallengeParsing(ref err) => Some(&*err),
|
||||||
Utf8Parsing(ref err) => Some(&*err as &StdError),
|
Utf8Parsing(ref err) => Some(&*err),
|
||||||
Io(ref err) => Some(&*err as &StdError),
|
Io(ref err) => Some(&*err),
|
||||||
Tls(ref err) => Some(&*err as &StdError),
|
Tls(ref err) => Some(&*err),
|
||||||
|
Parsing(ref err) => Some(&*err),
|
||||||
_ => None,
|
_ => None,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -94,6 +95,12 @@ impl From<native_tls::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<nom::simple_errors::Err> for Error {
|
||||||
|
fn from(err: nom::simple_errors::Err) -> Error {
|
||||||
|
Parsing(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl From<Response> for Error {
|
impl From<Response> for Error {
|
||||||
fn from(response: Response) -> Error {
|
fn from(response: Response) -> Error {
|
||||||
match response.code.severity {
|
match response.code.severity {
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
//! ESMTP features
|
//! ESMTP features
|
||||||
|
|
||||||
|
use hostname::get_hostname;
|
||||||
use smtp::authentication::Mechanism;
|
use smtp::authentication::Mechanism;
|
||||||
use smtp::error::Error;
|
use smtp::error::Error;
|
||||||
use smtp::response::Response;
|
use smtp::response::Response;
|
||||||
@@ -9,8 +10,12 @@ use std::fmt::{self, Display, Formatter};
|
|||||||
use std::net::{Ipv4Addr, Ipv6Addr};
|
use std::net::{Ipv4Addr, Ipv6Addr};
|
||||||
use std::result::Result;
|
use std::result::Result;
|
||||||
|
|
||||||
|
/// Default ehlo clinet id
|
||||||
|
pub const DEFAULT_EHLO_HOSTNAME: &str = "localhost";
|
||||||
|
|
||||||
/// Client identifier, the parameter to `EHLO`
|
/// Client identifier, the parameter to `EHLO`
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub enum ClientId {
|
pub enum ClientId {
|
||||||
/// A fully-qualified domain name
|
/// A fully-qualified domain name
|
||||||
Domain(String),
|
Domain(String),
|
||||||
@@ -35,10 +40,20 @@ impl ClientId {
|
|||||||
pub fn new(domain: String) -> ClientId {
|
pub fn new(domain: String) -> ClientId {
|
||||||
ClientId::Domain(domain)
|
ClientId::Domain(domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines a `ClientId` with the current hostname, of `localhost` if hostname could not be
|
||||||
|
/// found
|
||||||
|
pub fn hostname() -> ClientId {
|
||||||
|
ClientId::Domain(match get_hostname() {
|
||||||
|
Some(name) => name,
|
||||||
|
None => DEFAULT_EHLO_HOSTNAME.to_string(),
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Supported ESMTP keywords
|
/// Supported ESMTP keywords
|
||||||
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
|
#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub enum Extension {
|
pub enum Extension {
|
||||||
/// 8BITMIME keyword
|
/// 8BITMIME keyword
|
||||||
///
|
///
|
||||||
@@ -59,16 +74,17 @@ pub enum Extension {
|
|||||||
impl Display for Extension {
|
impl Display for Extension {
|
||||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||||
match *self {
|
match *self {
|
||||||
Extension::EightBitMime => write!(f, "{}", "8BITMIME"),
|
Extension::EightBitMime => write!(f, "8BITMIME"),
|
||||||
Extension::SmtpUtfEight => write!(f, "{}", "SMTPUTF8"),
|
Extension::SmtpUtfEight => write!(f, "SMTPUTF8"),
|
||||||
Extension::StartTls => write!(f, "{}", "STARTTLS"),
|
Extension::StartTls => write!(f, "STARTTLS"),
|
||||||
Extension::Authentication(ref mechanism) => write!(f, "{} {}", "AUTH", mechanism),
|
Extension::Authentication(ref mechanism) => write!(f, "AUTH {}", mechanism),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Contains information about an SMTP server
|
/// Contains information about an SMTP server
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct ServerInfo {
|
pub struct ServerInfo {
|
||||||
/// Server name
|
/// Server name
|
||||||
///
|
///
|
||||||
@@ -106,6 +122,10 @@ impl ServerInfo {
|
|||||||
let mut features: HashSet<Extension> = HashSet::new();
|
let mut features: HashSet<Extension> = HashSet::new();
|
||||||
|
|
||||||
for line in response.message.as_slice() {
|
for line in response.message.as_slice() {
|
||||||
|
if line.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
let splitted: Vec<&str> = line.split_whitespace().collect();
|
let splitted: Vec<&str> = line.split_whitespace().collect();
|
||||||
match splitted[0] {
|
match splitted[0] {
|
||||||
"8BITMIME" => {
|
"8BITMIME" => {
|
||||||
@@ -117,8 +137,7 @@ impl ServerInfo {
|
|||||||
"STARTTLS" => {
|
"STARTTLS" => {
|
||||||
features.insert(Extension::StartTls);
|
features.insert(Extension::StartTls);
|
||||||
}
|
}
|
||||||
"AUTH" => {
|
"AUTH" => for &mechanism in &splitted[1..] {
|
||||||
for &mechanism in &splitted[1..] {
|
|
||||||
match mechanism {
|
match mechanism {
|
||||||
"PLAIN" => {
|
"PLAIN" => {
|
||||||
features.insert(Extension::Authentication(Mechanism::Plain));
|
features.insert(Extension::Authentication(Mechanism::Plain));
|
||||||
@@ -132,15 +151,14 @@ impl ServerInfo {
|
|||||||
}
|
}
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}
|
|
||||||
_ => (),
|
_ => (),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(ServerInfo {
|
Ok(ServerInfo {
|
||||||
name: name.to_string(),
|
name: name.to_string(),
|
||||||
features: features,
|
features,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,14 +169,14 @@ impl ServerInfo {
|
|||||||
|
|
||||||
/// Checks if the server supports an ESMTP feature
|
/// Checks if the server supports an ESMTP feature
|
||||||
pub fn supports_auth_mechanism(&self, mechanism: Mechanism) -> bool {
|
pub fn supports_auth_mechanism(&self, mechanism: Mechanism) -> bool {
|
||||||
self.features.contains(
|
self.features
|
||||||
&Extension::Authentication(mechanism),
|
.contains(&Extension::Authentication(mechanism))
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A `MAIL FROM` extension parameter
|
/// A `MAIL FROM` extension parameter
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub enum MailParameter {
|
pub enum MailParameter {
|
||||||
/// `BODY` parameter
|
/// `BODY` parameter
|
||||||
Body(MailBodyParameter),
|
Body(MailBodyParameter),
|
||||||
@@ -194,7 +212,8 @@ impl Display for MailParameter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Values for the `BODY` parameter to `MAIL FROM`
|
/// Values for the `BODY` parameter to `MAIL FROM`
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug, Copy)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub enum MailBodyParameter {
|
pub enum MailBodyParameter {
|
||||||
/// `7BIT`
|
/// `7BIT`
|
||||||
SevenBit,
|
SevenBit,
|
||||||
@@ -213,6 +232,7 @@ impl Display for MailBodyParameter {
|
|||||||
|
|
||||||
/// A `RCPT TO` extension parameter
|
/// A `RCPT TO` extension parameter
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub enum RcptParameter {
|
pub enum RcptParameter {
|
||||||
/// Custom parameter
|
/// Custom parameter
|
||||||
Other {
|
Other {
|
||||||
@@ -241,11 +261,19 @@ impl Display for RcptParameter {
|
|||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
use super::{Extension, ServerInfo};
|
use super::{ClientId, Extension, ServerInfo};
|
||||||
use smtp::authentication::Mechanism;
|
use smtp::authentication::Mechanism;
|
||||||
use smtp::response::{Category, Code, Detail, Response, Severity};
|
use smtp::response::{Category, Code, Detail, Response, Severity};
|
||||||
use std::collections::HashSet;
|
use std::collections::HashSet;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_clientid_fmt() {
|
||||||
|
assert_eq!(
|
||||||
|
format!("{}", ClientId::new("test".to_string())),
|
||||||
|
"test".to_string()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_extension_fmt() {
|
fn test_extension_fmt() {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
@@ -308,7 +336,7 @@ mod test {
|
|||||||
Code::new(
|
Code::new(
|
||||||
Severity::PositiveCompletion,
|
Severity::PositiveCompletion,
|
||||||
Category::Unspecified4,
|
Category::Unspecified4,
|
||||||
Detail(1),
|
Detail::One,
|
||||||
),
|
),
|
||||||
vec![
|
vec![
|
||||||
"me".to_string(),
|
"me".to_string(),
|
||||||
@@ -336,7 +364,7 @@ mod test {
|
|||||||
Code::new(
|
Code::new(
|
||||||
Severity::PositiveCompletion,
|
Severity::PositiveCompletion,
|
||||||
Category::Unspecified4,
|
Category::Unspecified4,
|
||||||
Detail(1),
|
Detail::One,
|
||||||
),
|
),
|
||||||
vec![
|
vec![
|
||||||
"me".to_string(),
|
"me".to_string(),
|
||||||
@@ -348,13 +376,9 @@ mod test {
|
|||||||
|
|
||||||
let mut features2 = HashSet::new();
|
let mut features2 = HashSet::new();
|
||||||
assert!(features2.insert(Extension::EightBitMime));
|
assert!(features2.insert(Extension::EightBitMime));
|
||||||
assert!(features2.insert(
|
assert!(features2.insert(Extension::Authentication(Mechanism::Plain),));
|
||||||
Extension::Authentication(Mechanism::Plain),
|
|
||||||
));
|
|
||||||
#[cfg(feature = "crammd5-auth")]
|
#[cfg(feature = "crammd5-auth")]
|
||||||
assert!(features2.insert(
|
assert!(features2.insert(Extension::Authentication(Mechanism::CramMd5),));
|
||||||
Extension::Authentication(Mechanism::CramMd5),
|
|
||||||
));
|
|
||||||
|
|
||||||
let server_info2 = ServerInfo {
|
let server_info2 = ServerInfo {
|
||||||
name: "me".to_string(),
|
name: "me".to_string(),
|
||||||
|
|||||||
@@ -13,107 +13,17 @@
|
|||||||
//! * STARTTLS ([RFC 2487](http://tools.ietf.org/html/rfc2487))
|
//! * STARTTLS ([RFC 2487](http://tools.ietf.org/html/rfc2487))
|
||||||
//! * SMTPUTF8 ([RFC 6531](http://tools.ietf.org/html/rfc6531))
|
//! * SMTPUTF8 ([RFC 6531](http://tools.ietf.org/html/rfc6531))
|
||||||
//!
|
//!
|
||||||
//! #### Simple example
|
|
||||||
//!
|
|
||||||
//! This is the most basic example of usage:
|
|
||||||
//!
|
|
||||||
//! ```rust,no_run
|
|
||||||
//! use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress, SmtpTransport};
|
|
||||||
//!
|
|
||||||
//! let email = SimpleSendableEmail::new(
|
|
||||||
//! EmailAddress::new("user@localhost".to_string()),
|
|
||||||
//! vec![EmailAddress::new("root@localhost".to_string())],
|
|
||||||
//! "message_id".to_string(),
|
|
||||||
//! "Hello world".to_string(),
|
|
||||||
//! );
|
|
||||||
//!
|
|
||||||
//! // Open a local connection on port 25
|
|
||||||
//! let mut mailer =
|
|
||||||
//! SmtpTransport::builder_unencrypted_localhost().unwrap().build();
|
|
||||||
//! // Send the email
|
|
||||||
//! let result = mailer.send(&email);
|
|
||||||
//!
|
|
||||||
//! assert!(result.is_ok());
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! #### Complete example
|
|
||||||
//!
|
|
||||||
//! ```rust,no_run
|
|
||||||
//! use lettre::smtp::authentication::{Credentials, Mechanism};
|
|
||||||
//! use lettre::smtp::SUBMISSION_PORT;
|
|
||||||
//! use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress, SmtpTransport};
|
|
||||||
//! use lettre::smtp::extension::ClientId;
|
|
||||||
//! use lettre::smtp::ConnectionReuseParameters;
|
|
||||||
//!
|
|
||||||
//!
|
|
||||||
//! let email = SimpleSendableEmail::new(
|
|
||||||
//! EmailAddress::new("user@localhost".to_string()),
|
|
||||||
//! vec![EmailAddress::new("root@localhost".to_string())],
|
|
||||||
//! "message_id".to_string(),
|
|
||||||
//! "Hello world".to_string(),
|
|
||||||
//! );
|
|
||||||
//!
|
|
||||||
//! // Connect to a remote server on a custom port
|
|
||||||
//! let mut mailer = SmtpTransport::simple_builder("server.tld".to_string()).unwrap()
|
|
||||||
//! // Set the name sent during EHLO/HELO, default is `localhost`
|
|
||||||
//! .hello_name(ClientId::Domain("my.hostname.tld".to_string()))
|
|
||||||
//! // Add credentials for authentication
|
|
||||||
//! .credentials(Credentials::new("username".to_string(), "password".to_string()))
|
|
||||||
//! // Enable SMTPUTF8 if the server supports it
|
|
||||||
//! .smtp_utf8(true)
|
|
||||||
//! // Configure expected authentication mechanism
|
|
||||||
//! .authentication_mechanism(Mechanism::Plain)
|
|
||||||
//! // Enable connection reuse
|
|
||||||
//! .connection_reuse(ConnectionReuseParameters::ReuseUnlimited).build();
|
|
||||||
//!
|
|
||||||
//! let result_1 = mailer.send(&email);
|
|
||||||
//! assert!(result_1.is_ok());
|
|
||||||
//!
|
|
||||||
//! // The second email will use the same connection
|
|
||||||
//! let result_2 = mailer.send(&email);
|
|
||||||
//! assert!(result_2.is_ok());
|
|
||||||
//!
|
|
||||||
//! // Explicitly close the SMTP transaction as we enabled connection reuse
|
|
||||||
//! mailer.close();
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! #### Lower level
|
|
||||||
//!
|
|
||||||
//! You can also send commands, here is a simple email transaction without
|
|
||||||
//! error handling:
|
|
||||||
//!
|
|
||||||
//! ```rust
|
|
||||||
//! use lettre::EmailAddress;
|
|
||||||
//! use lettre::smtp::SMTP_PORT;
|
|
||||||
//! use lettre::smtp::client::Client;
|
|
||||||
//! use lettre::smtp::client::net::NetworkStream;
|
|
||||||
//! use lettre::smtp::extension::ClientId;
|
|
||||||
//! use lettre::smtp::commands::*;
|
|
||||||
//!
|
|
||||||
//! let mut email_client: Client<NetworkStream> = Client::new();
|
|
||||||
//! let _ = email_client.connect(&("localhost", SMTP_PORT), None);
|
|
||||||
//! let _ = email_client.smtp_command(EhloCommand::new(ClientId::new("my_hostname".to_string())));
|
|
||||||
//! let _ = email_client.smtp_command(
|
|
||||||
//! MailCommand::new(Some(EmailAddress::new("user@example.com".to_string())), vec![])
|
|
||||||
//! );
|
|
||||||
//! let _ = email_client.smtp_command(
|
|
||||||
//! RcptCommand::new(EmailAddress::new("user@example.org".to_string()), vec![])
|
|
||||||
//! );
|
|
||||||
//! let _ = email_client.smtp_command(DataCommand);
|
|
||||||
//! let _ = email_client.message(Box::new("Test email".as_bytes()));
|
|
||||||
//! let _ = email_client.smtp_command(QuitCommand);
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use EmailTransport;
|
use EmailTransport;
|
||||||
use SendableEmail;
|
use SendableEmail;
|
||||||
use native_tls::TlsConnector;
|
use native_tls::TlsConnector;
|
||||||
use smtp::authentication::{Credentials, DEFAULT_ENCRYPTED_MECHANISMS,
|
use smtp::authentication::{Credentials, Mechanism, DEFAULT_ENCRYPTED_MECHANISMS,
|
||||||
DEFAULT_UNENCRYPTED_MECHANISMS, Mechanism};
|
DEFAULT_UNENCRYPTED_MECHANISMS};
|
||||||
use smtp::client::Client;
|
use smtp::client::Client;
|
||||||
use smtp::client::net::ClientTlsParameters;
|
use smtp::client::net::ClientTlsParameters;
|
||||||
|
use smtp::client::net::DEFAULT_TLS_PROTOCOLS;
|
||||||
use smtp::commands::*;
|
use smtp::commands::*;
|
||||||
use smtp::error::{Error, SmtpResult};
|
use smtp::error::{Error, SmtpResult};
|
||||||
use smtp::client::net::DEFAULT_TLS_PROTOCOLS;
|
|
||||||
use smtp::extension::{ClientId, Extension, MailBodyParameter, MailParameter, ServerInfo};
|
use smtp::extension::{ClientId, Extension, MailBodyParameter, MailParameter, ServerInfo};
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
use std::net::{SocketAddr, ToSocketAddrs};
|
use std::net::{SocketAddr, ToSocketAddrs};
|
||||||
@@ -140,22 +50,23 @@ pub const SUBMISSION_PORT: u16 = 587;
|
|||||||
// Useful strings and characters
|
// Useful strings and characters
|
||||||
|
|
||||||
/// The word separator for SMTP transactions
|
/// The word separator for SMTP transactions
|
||||||
pub const SP: &'static str = " ";
|
pub const SP: &str = " ";
|
||||||
|
|
||||||
/// The line ending for SMTP transactions (carriage return + line feed)
|
/// The line ending for SMTP transactions (carriage return + line feed)
|
||||||
pub const CRLF: &'static str = "\r\n";
|
pub const CRLF: &str = "\r\n";
|
||||||
|
|
||||||
/// Colon
|
/// Colon
|
||||||
pub const COLON: &'static str = ":";
|
pub const COLON: &str = ":";
|
||||||
|
|
||||||
/// The ending of message content
|
/// The ending of message content
|
||||||
pub const MESSAGE_ENDING: &'static str = "\r\n.\r\n";
|
pub const MESSAGE_ENDING: &str = "\r\n.\r\n";
|
||||||
|
|
||||||
/// NUL unicode character
|
/// NUL unicode character
|
||||||
pub const NUL: &'static str = "\0";
|
pub const NUL: &str = "\0";
|
||||||
|
|
||||||
/// How to apply TLS to a client connection
|
/// How to apply TLS to a client connection
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
pub enum ClientSecurity {
|
pub enum ClientSecurity {
|
||||||
/// Insecure connection
|
/// Insecure connection
|
||||||
None,
|
None,
|
||||||
@@ -169,7 +80,8 @@ pub enum ClientSecurity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Configures connection reuse behavior
|
/// Configures connection reuse behavior
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug, Copy)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub enum ConnectionReuseParameters {
|
pub enum ConnectionReuseParameters {
|
||||||
/// Unlimitied connection reuse
|
/// Unlimitied connection reuse
|
||||||
ReuseUnlimited,
|
ReuseUnlimited,
|
||||||
@@ -180,6 +92,7 @@ pub enum ConnectionReuseParameters {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Contains client configuration
|
/// Contains client configuration
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct SmtpTransportBuilder {
|
pub struct SmtpTransportBuilder {
|
||||||
/// Enable connection reuse
|
/// Enable connection reuse
|
||||||
connection_reuse: ConnectionReuseParameters,
|
connection_reuse: ConnectionReuseParameters,
|
||||||
@@ -207,7 +120,6 @@ impl SmtpTransportBuilder {
|
|||||||
/// Defaults are:
|
/// Defaults are:
|
||||||
///
|
///
|
||||||
/// * No connection reuse
|
/// * No connection reuse
|
||||||
/// * "localhost" as EHLO name
|
|
||||||
/// * No authentication
|
/// * No authentication
|
||||||
/// * No SMTPUTF8 support
|
/// * No SMTPUTF8 support
|
||||||
/// * A 60 seconds timeout for smtp commands
|
/// * A 60 seconds timeout for smtp commands
|
||||||
@@ -218,18 +130,16 @@ impl SmtpTransportBuilder {
|
|||||||
let mut addresses = addr.to_socket_addrs()?;
|
let mut addresses = addr.to_socket_addrs()?;
|
||||||
|
|
||||||
match addresses.next() {
|
match addresses.next() {
|
||||||
Some(addr) => {
|
Some(addr) => Ok(SmtpTransportBuilder {
|
||||||
Ok(SmtpTransportBuilder {
|
|
||||||
server_addr: addr,
|
server_addr: addr,
|
||||||
security: security,
|
security,
|
||||||
smtp_utf8: false,
|
smtp_utf8: false,
|
||||||
credentials: None,
|
credentials: None,
|
||||||
connection_reuse: ConnectionReuseParameters::NoReuse,
|
connection_reuse: ConnectionReuseParameters::NoReuse,
|
||||||
hello_name: ClientId::Domain("localhost".to_string()),
|
hello_name: ClientId::hostname(),
|
||||||
authentication_mechanism: None,
|
authentication_mechanism: None,
|
||||||
timeout: Some(Duration::new(60, 0)),
|
timeout: Some(Duration::new(60, 0)),
|
||||||
})
|
}),
|
||||||
}
|
|
||||||
None => Err(Error::Resolution),
|
None => Err(Error::Resolution),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -291,6 +201,7 @@ struct State {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Structure that implements the high level SMTP client
|
/// Structure that implements the high level SMTP client
|
||||||
|
#[allow(missing_debug_implementations)]
|
||||||
pub struct SmtpTransport {
|
pub struct SmtpTransport {
|
||||||
/// Information about the server
|
/// Information about the server
|
||||||
/// Value is None before HELO/EHLO
|
/// Value is None before HELO/EHLO
|
||||||
@@ -310,7 +221,7 @@ macro_rules! try_smtp (
|
|||||||
Err(err) => {
|
Err(err) => {
|
||||||
if !$client.state.panic {
|
if !$client.state.panic {
|
||||||
$client.state.panic = true;
|
$client.state.panic = true;
|
||||||
$client.reset();
|
$client.close();
|
||||||
}
|
}
|
||||||
return Err(From::from(err))
|
return Err(From::from(err))
|
||||||
},
|
},
|
||||||
@@ -322,18 +233,15 @@ impl<'a> SmtpTransport {
|
|||||||
/// Simple and secure transport, should be used when possible.
|
/// Simple and secure transport, should be used when possible.
|
||||||
/// Creates an encrypted transport over submission port, using the provided domain
|
/// Creates an encrypted transport over submission port, using the provided domain
|
||||||
/// to validate TLS certificates.
|
/// to validate TLS certificates.
|
||||||
pub fn simple_builder(domain: String) -> Result<SmtpTransportBuilder, Error> {
|
pub fn simple_builder(domain: &str) -> Result<SmtpTransportBuilder, Error> {
|
||||||
|
|
||||||
let mut tls_builder = TlsConnector::builder()?;
|
let mut tls_builder = TlsConnector::builder()?;
|
||||||
tls_builder.supported_protocols(DEFAULT_TLS_PROTOCOLS)?;
|
tls_builder.supported_protocols(DEFAULT_TLS_PROTOCOLS)?;
|
||||||
|
|
||||||
let tls_parameters = ClientTlsParameters::new(
|
let tls_parameters =
|
||||||
domain.clone(),
|
ClientTlsParameters::new(domain.to_string(), tls_builder.build().unwrap());
|
||||||
tls_builder.build().unwrap(),
|
|
||||||
);
|
|
||||||
|
|
||||||
SmtpTransportBuilder::new(
|
SmtpTransportBuilder::new(
|
||||||
(domain.as_ref(), SUBMISSION_PORT),
|
(domain, SUBMISSION_PORT),
|
||||||
ClientSecurity::Required(tls_parameters),
|
ClientSecurity::Required(tls_parameters),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -355,11 +263,10 @@ impl<'a> SmtpTransport {
|
|||||||
///
|
///
|
||||||
/// It does not connect to the server, but only creates the `SmtpTransport`
|
/// It does not connect to the server, but only creates the `SmtpTransport`
|
||||||
pub fn new(builder: SmtpTransportBuilder) -> SmtpTransport {
|
pub fn new(builder: SmtpTransportBuilder) -> SmtpTransport {
|
||||||
|
|
||||||
let client = Client::new();
|
let client = Client::new();
|
||||||
|
|
||||||
SmtpTransport {
|
SmtpTransport {
|
||||||
client: client,
|
client,
|
||||||
server_info: None,
|
server_info: None,
|
||||||
client_info: builder,
|
client_info: builder,
|
||||||
state: State {
|
state: State {
|
||||||
@@ -370,12 +277,12 @@ impl<'a> SmtpTransport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the EHLO response and updates server information
|
/// Gets the EHLO response and updates server information
|
||||||
pub fn get_ehlo(&mut self) -> SmtpResult {
|
fn ehlo(&mut self) -> SmtpResult {
|
||||||
// Extended Hello
|
// Extended Hello
|
||||||
let ehlo_response = try_smtp!(
|
let ehlo_response = try_smtp!(
|
||||||
self.client.smtp_command(EhloCommand::new(
|
self.client.command(EhloCommand::new(ClientId::new(
|
||||||
ClientId::new(self.client_info.hello_name.to_string()),
|
self.client_info.hello_name.to_string()
|
||||||
)),
|
),)),
|
||||||
self
|
self
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -387,15 +294,10 @@ impl<'a> SmtpTransport {
|
|||||||
Ok(ehlo_response)
|
Ok(ehlo_response)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Closes the inner connection
|
|
||||||
pub fn close(&mut self) {
|
|
||||||
self.client.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Reset the client state
|
/// Reset the client state
|
||||||
pub fn reset(&mut self) {
|
pub fn close(&mut self) {
|
||||||
// Close the SMTP transaction if needed
|
// Close the SMTP transaction if needed
|
||||||
self.close();
|
self.client.close();
|
||||||
|
|
||||||
// Reset the client state
|
// Reset the client state
|
||||||
self.server_info = None;
|
self.server_info = None;
|
||||||
@@ -408,13 +310,13 @@ impl<'a, T: Read + 'a> EmailTransport<'a, T, SmtpResult> for SmtpTransport {
|
|||||||
/// Sends an email
|
/// Sends an email
|
||||||
#[cfg_attr(feature = "cargo-clippy", allow(match_same_arms, cyclomatic_complexity))]
|
#[cfg_attr(feature = "cargo-clippy", allow(match_same_arms, cyclomatic_complexity))]
|
||||||
fn send<U: SendableEmail<'a, T> + 'a>(&mut self, email: &'a U) -> SmtpResult {
|
fn send<U: SendableEmail<'a, T> + 'a>(&mut self, email: &'a U) -> SmtpResult {
|
||||||
|
|
||||||
// Extract email information
|
// Extract email information
|
||||||
let message_id = email.message_id();
|
let message_id = email.message_id();
|
||||||
|
let envelope = email.envelope();
|
||||||
|
|
||||||
// Check if the connection is still available
|
// Check if the connection is still available
|
||||||
if (self.state.connection_reuse_count > 0) && (!self.client.is_connected()) {
|
if (self.state.connection_reuse_count > 0) && (!self.client.is_connected()) {
|
||||||
self.reset();
|
self.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.state.connection_reuse_count == 0 {
|
if self.state.connection_reuse_count == 0 {
|
||||||
@@ -431,13 +333,14 @@ impl<'a, T: Read + 'a> EmailTransport<'a, T, SmtpResult> for SmtpTransport {
|
|||||||
// Log the connection
|
// Log the connection
|
||||||
info!("connection established to {}", self.client_info.server_addr);
|
info!("connection established to {}", self.client_info.server_addr);
|
||||||
|
|
||||||
self.get_ehlo()?;
|
self.ehlo()?;
|
||||||
|
|
||||||
match (
|
match (
|
||||||
&self.client_info.security.clone(),
|
&self.client_info.security.clone(),
|
||||||
self.server_info.as_ref().unwrap().supports_feature(
|
self.server_info
|
||||||
Extension::StartTls,
|
.as_ref()
|
||||||
),
|
.unwrap()
|
||||||
|
.supports_feature(Extension::StartTls),
|
||||||
) {
|
) {
|
||||||
(&ClientSecurity::Required(_), false) => {
|
(&ClientSecurity::Required(_), false) => {
|
||||||
return Err(From::from("Could not encrypt connection, aborting"))
|
return Err(From::from("Could not encrypt connection, aborting"))
|
||||||
@@ -445,15 +348,15 @@ impl<'a, T: Read + 'a> EmailTransport<'a, T, SmtpResult> for SmtpTransport {
|
|||||||
(&ClientSecurity::Opportunistic(_), false) => (),
|
(&ClientSecurity::Opportunistic(_), false) => (),
|
||||||
(&ClientSecurity::None, _) => (),
|
(&ClientSecurity::None, _) => (),
|
||||||
(&ClientSecurity::Wrapper(_), _) => (),
|
(&ClientSecurity::Wrapper(_), _) => (),
|
||||||
(&ClientSecurity::Opportunistic(ref tls_parameters), true) |
|
(&ClientSecurity::Opportunistic(ref tls_parameters), true)
|
||||||
(&ClientSecurity::Required(ref tls_parameters), true) => {
|
| (&ClientSecurity::Required(ref tls_parameters), true) => {
|
||||||
try_smtp!(self.client.smtp_command(StarttlsCommand), self);
|
try_smtp!(self.client.command(StarttlsCommand), self);
|
||||||
try_smtp!(self.client.upgrade_tls_stream(tls_parameters), self);
|
try_smtp!(self.client.upgrade_tls_stream(tls_parameters), self);
|
||||||
|
|
||||||
debug!("connection encrypted");
|
debug!("connection encrypted");
|
||||||
|
|
||||||
// Send EHLO again
|
// Send EHLO again
|
||||||
self.get_ehlo()?;
|
self.ehlo()?;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -473,16 +376,15 @@ impl<'a, T: Read + 'a> EmailTransport<'a, T, SmtpResult> for SmtpTransport {
|
|||||||
};
|
};
|
||||||
|
|
||||||
for mechanism in accepted_mechanisms {
|
for mechanism in accepted_mechanisms {
|
||||||
if self.server_info.as_ref().unwrap().supports_auth_mechanism(
|
if self.server_info
|
||||||
mechanism,
|
.as_ref()
|
||||||
)
|
.unwrap()
|
||||||
|
.supports_auth_mechanism(mechanism)
|
||||||
{
|
{
|
||||||
found = true;
|
found = true;
|
||||||
try_smtp!(
|
try_smtp!(
|
||||||
self.client.auth(
|
self.client
|
||||||
mechanism,
|
.auth(mechanism, self.client_info.credentials.as_ref().unwrap(),),
|
||||||
self.client_info.credentials.as_ref().unwrap(),
|
|
||||||
),
|
|
||||||
self
|
self
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
@@ -498,37 +400,43 @@ impl<'a, T: Read + 'a> EmailTransport<'a, T, SmtpResult> for SmtpTransport {
|
|||||||
// Mail
|
// Mail
|
||||||
let mut mail_options = vec![];
|
let mut mail_options = vec![];
|
||||||
|
|
||||||
if self.server_info.as_ref().unwrap().supports_feature(
|
if self.server_info
|
||||||
Extension::EightBitMime,
|
.as_ref()
|
||||||
)
|
.unwrap()
|
||||||
|
.supports_feature(Extension::EightBitMime)
|
||||||
{
|
{
|
||||||
mail_options.push(MailParameter::Body(MailBodyParameter::EightBitMime));
|
mail_options.push(MailParameter::Body(MailBodyParameter::EightBitMime));
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.server_info.as_ref().unwrap().supports_feature(
|
if self.server_info
|
||||||
Extension::SmtpUtfEight,
|
.as_ref()
|
||||||
) && self.client_info.smtp_utf8
|
.unwrap()
|
||||||
|
.supports_feature(Extension::SmtpUtfEight) && self.client_info.smtp_utf8
|
||||||
{
|
{
|
||||||
mail_options.push(MailParameter::SmtpUtfEight);
|
mail_options.push(MailParameter::SmtpUtfEight);
|
||||||
}
|
}
|
||||||
|
|
||||||
try_smtp!(
|
try_smtp!(
|
||||||
self.client.smtp_command(MailCommand::new(
|
self.client
|
||||||
Some(email.from().clone()),
|
.command(MailCommand::new(envelope.from().cloned(), mail_options,)),
|
||||||
mail_options,
|
|
||||||
)),
|
|
||||||
self
|
self
|
||||||
);
|
);
|
||||||
|
|
||||||
// Log the mail command
|
// Log the mail command
|
||||||
info!("{}: from=<{}>", message_id, email.from());
|
info!(
|
||||||
|
"{}: from=<{}>",
|
||||||
|
message_id,
|
||||||
|
match envelope.from() {
|
||||||
|
Some(address) => address.to_string(),
|
||||||
|
None => "".to_string(),
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
// Recipient
|
// Recipient
|
||||||
for to_address in &email.to() {
|
for to_address in envelope.to() {
|
||||||
try_smtp!(
|
try_smtp!(
|
||||||
self.client.smtp_command(
|
self.client
|
||||||
RcptCommand::new(to_address.clone(), vec![]),
|
.command(RcptCommand::new(to_address.clone(), vec![]),),
|
||||||
),
|
|
||||||
self
|
self
|
||||||
);
|
);
|
||||||
// Log the rcpt command
|
// Log the rcpt command
|
||||||
@@ -536,7 +444,7 @@ impl<'a, T: Read + 'a> EmailTransport<'a, T, SmtpResult> for SmtpTransport {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Data
|
// Data
|
||||||
try_smtp!(self.client.smtp_command(DataCommand), self);
|
try_smtp!(self.client.command(DataCommand), self);
|
||||||
|
|
||||||
// Message content
|
// Message content
|
||||||
let result = self.client.message(email.message());
|
let result = self.client.message(email.message());
|
||||||
@@ -564,8 +472,11 @@ impl<'a, T: Read + 'a> EmailTransport<'a, T, SmtpResult> for SmtpTransport {
|
|||||||
// Test if we can reuse the existing connection
|
// Test if we can reuse the existing connection
|
||||||
match self.client_info.connection_reuse {
|
match self.client_info.connection_reuse {
|
||||||
ConnectionReuseParameters::ReuseLimited(limit)
|
ConnectionReuseParameters::ReuseLimited(limit)
|
||||||
if self.state.connection_reuse_count >= limit => self.reset(),
|
if self.state.connection_reuse_count >= limit =>
|
||||||
ConnectionReuseParameters::NoReuse => self.reset(),
|
{
|
||||||
|
self.close()
|
||||||
|
}
|
||||||
|
ConnectionReuseParameters::NoReuse => self.close(),
|
||||||
_ => (),
|
_ => (),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,131 +1,91 @@
|
|||||||
//! SMTP response, containing a mandatory return code and an optional text
|
//! SMTP response, containing a mandatory return code and an optional text
|
||||||
//! message
|
//! message
|
||||||
|
|
||||||
use self::Category::*;
|
use nom::{crlf, ErrorKind as NomErrorKind, IResult as NomResult};
|
||||||
use self::Severity::*;
|
use nom::simple_errors::Err as NomError;
|
||||||
use smtp::error::{Error, SmtpResult};
|
|
||||||
use std::fmt::{Display, Formatter, Result};
|
use std::fmt::{Display, Formatter, Result};
|
||||||
use std::result;
|
use std::result;
|
||||||
use std::str::FromStr;
|
use std::str::{FromStr, from_utf8};
|
||||||
|
|
||||||
/// First digit indicates severity
|
/// First digit indicates severity
|
||||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub enum Severity {
|
pub enum Severity {
|
||||||
/// 2yx
|
/// 2yx
|
||||||
PositiveCompletion,
|
PositiveCompletion = 2,
|
||||||
/// 3yz
|
/// 3yz
|
||||||
PositiveIntermediate,
|
PositiveIntermediate = 3,
|
||||||
/// 4yz
|
/// 4yz
|
||||||
TransientNegativeCompletion,
|
TransientNegativeCompletion = 4,
|
||||||
/// 5yz
|
/// 5yz
|
||||||
PermanentNegativeCompletion,
|
PermanentNegativeCompletion = 5,
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Severity {
|
|
||||||
type Err = Error;
|
|
||||||
fn from_str(s: &str) -> result::Result<Severity, Error> {
|
|
||||||
match s {
|
|
||||||
"2" => Ok(PositiveCompletion),
|
|
||||||
"3" => Ok(PositiveIntermediate),
|
|
||||||
"4" => Ok(TransientNegativeCompletion),
|
|
||||||
"5" => Ok(PermanentNegativeCompletion),
|
|
||||||
_ => Err(Error::ResponseParsing(
|
|
||||||
"First digit must be between 2 and 5",
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Severity {
|
impl Display for Severity {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||||
write!(
|
write!(f, "{}", *self as u8)
|
||||||
f,
|
|
||||||
"{}",
|
|
||||||
match *self {
|
|
||||||
PositiveCompletion => 2,
|
|
||||||
PositiveIntermediate => 3,
|
|
||||||
TransientNegativeCompletion => 4,
|
|
||||||
PermanentNegativeCompletion => 5,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Second digit
|
/// Second digit
|
||||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub enum Category {
|
pub enum Category {
|
||||||
/// x0z
|
/// x0z
|
||||||
Syntax,
|
Syntax = 0,
|
||||||
/// x1z
|
/// x1z
|
||||||
Information,
|
Information = 1,
|
||||||
/// x2z
|
/// x2z
|
||||||
Connections,
|
Connections = 2,
|
||||||
/// x3z
|
/// x3z
|
||||||
Unspecified3,
|
Unspecified3 = 3,
|
||||||
/// x4z
|
/// x4z
|
||||||
Unspecified4,
|
Unspecified4 = 4,
|
||||||
/// x5z
|
/// x5z
|
||||||
MailSystem,
|
MailSystem = 5,
|
||||||
}
|
|
||||||
|
|
||||||
impl FromStr for Category {
|
|
||||||
type Err = Error;
|
|
||||||
fn from_str(s: &str) -> result::Result<Category, Error> {
|
|
||||||
match s {
|
|
||||||
"0" => Ok(Syntax),
|
|
||||||
"1" => Ok(Information),
|
|
||||||
"2" => Ok(Connections),
|
|
||||||
"3" => Ok(Unspecified3),
|
|
||||||
"4" => Ok(Unspecified4),
|
|
||||||
"5" => Ok(MailSystem),
|
|
||||||
_ => Err(Error::ResponseParsing(
|
|
||||||
"Second digit must be between 0 and 5",
|
|
||||||
)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Category {
|
impl Display for Category {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||||
write!(
|
write!(f, "{}", *self as u8)
|
||||||
f,
|
|
||||||
"{}",
|
|
||||||
match *self {
|
|
||||||
Syntax => 0,
|
|
||||||
Information => 1,
|
|
||||||
Connections => 2,
|
|
||||||
Unspecified3 => 3,
|
|
||||||
Unspecified4 => 4,
|
|
||||||
MailSystem => 5,
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The detail digit of a response code (third digit)
|
/// The detail digit of a response code (third digit)
|
||||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||||
pub struct Detail(pub u8);
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
|
pub enum Detail {
|
||||||
impl FromStr for Detail {
|
#[allow(missing_docs)]
|
||||||
type Err = Error;
|
Zero = 0,
|
||||||
fn from_str(s: &str) -> result::Result<Detail, Error> {
|
#[allow(missing_docs)]
|
||||||
match s.parse::<u8>() {
|
One = 1,
|
||||||
Ok(d) if d < 10 => Ok(Detail(d)),
|
#[allow(missing_docs)]
|
||||||
_ => Err(Error::ResponseParsing(
|
Two = 2,
|
||||||
"Third digit must be between 0 and 9",
|
#[allow(missing_docs)]
|
||||||
)),
|
Three = 3,
|
||||||
}
|
#[allow(missing_docs)]
|
||||||
}
|
Four = 4,
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
Five = 5,
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
Six = 6,
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
Seven = 7,
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
Eight = 8,
|
||||||
|
#[allow(missing_docs)]
|
||||||
|
Nine = 9,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Display for Detail {
|
impl Display for Detail {
|
||||||
fn fmt(&self, f: &mut Formatter) -> Result {
|
fn fmt(&self, f: &mut Formatter) -> Result {
|
||||||
write!(f, "{}", self.0)
|
write!(f, "{}", *self as u8)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a 3 digit SMTP response code
|
/// Represents a 3 digit SMTP response code
|
||||||
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
#[derive(PartialEq, Eq, Copy, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct Code {
|
pub struct Code {
|
||||||
/// First digit of the response code
|
/// First digit of the response code
|
||||||
pub severity: Severity,
|
pub severity: Severity,
|
||||||
@@ -141,99 +101,13 @@ impl Display for Code {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FromStr for Code {
|
|
||||||
type Err = Error;
|
|
||||||
|
|
||||||
#[inline]
|
|
||||||
fn from_str(s: &str) -> result::Result<Code, Error> {
|
|
||||||
if s.len() == 3 {
|
|
||||||
match (
|
|
||||||
s[0..1].parse::<Severity>(),
|
|
||||||
s[1..2].parse::<Category>(),
|
|
||||||
s[2..3].parse::<Detail>(),
|
|
||||||
) {
|
|
||||||
(Ok(severity), Ok(category), Ok(detail)) => {
|
|
||||||
Ok(Code {
|
|
||||||
severity: severity,
|
|
||||||
category: category,
|
|
||||||
detail: detail,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
_ => Err(Error::ResponseParsing("Could not parse response code")),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Err(Error::ResponseParsing(
|
|
||||||
"Wrong code length (should be 3 digit)",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Code {
|
impl Code {
|
||||||
/// Creates a new `Code` structure
|
/// Creates a new `Code` structure
|
||||||
pub fn new(severity: Severity, category: Category, detail: Detail) -> Code {
|
pub fn new(severity: Severity, category: Category, detail: Detail) -> Code {
|
||||||
if detail.0 > 9 {
|
|
||||||
panic!("The detail code must be between 0 and 9");
|
|
||||||
}
|
|
||||||
|
|
||||||
Code {
|
Code {
|
||||||
severity: severity,
|
severity,
|
||||||
category: category,
|
category,
|
||||||
detail: detail,
|
detail,
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Parses an SMTP response
|
|
||||||
#[derive(PartialEq, Eq, Clone, Debug, Default)]
|
|
||||||
pub struct ResponseParser {
|
|
||||||
/// Response code
|
|
||||||
code: Option<Code>,
|
|
||||||
/// Server response string (optional)
|
|
||||||
/// Handle multiline responses
|
|
||||||
message: Vec<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ResponseParser {
|
|
||||||
/// Parses a line and return a `bool` indicating if there are more lines to come
|
|
||||||
pub fn read_line(&mut self, line: &str) -> result::Result<bool, Error> {
|
|
||||||
|
|
||||||
if line.len() < 3 {
|
|
||||||
return Err(Error::ResponseParsing(
|
|
||||||
"Incorrect response code (should be 3 digits)",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
match self.code {
|
|
||||||
Some(ref code) => {
|
|
||||||
if code.to_string() != line[0..3] {
|
|
||||||
return Err(Error::ResponseParsing(
|
|
||||||
"Response code has changed during a \
|
|
||||||
reponse",
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None => self.code = Some(line[0..3].parse::<Code>()?),
|
|
||||||
}
|
|
||||||
|
|
||||||
if line.len() > 4 {
|
|
||||||
self.message.push(line[4..].to_string());
|
|
||||||
Ok(line.as_bytes()[3] == b'-')
|
|
||||||
} else {
|
|
||||||
Ok(false)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Builds a response from a `ResponseParser`
|
|
||||||
pub fn response(self) -> SmtpResult {
|
|
||||||
match self.code {
|
|
||||||
Some(code) => Ok(Response::new(code, self.message)),
|
|
||||||
None => {
|
|
||||||
Err(Error::ResponseParsing(
|
|
||||||
"Incomplete response, could not read response \
|
|
||||||
code",
|
|
||||||
))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -242,6 +116,7 @@ impl ResponseParser {
|
|||||||
///
|
///
|
||||||
/// The text message is optional, only the code is mandatory
|
/// The text message is optional, only the code is mandatory
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct Response {
|
pub struct Response {
|
||||||
/// Response code
|
/// Response code
|
||||||
pub code: Code,
|
pub code: Code,
|
||||||
@@ -250,33 +125,42 @@ pub struct Response {
|
|||||||
pub message: Vec<String>,
|
pub message: Vec<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl FromStr for Response {
|
||||||
|
type Err = NomError;
|
||||||
|
|
||||||
|
fn from_str(s: &str) -> result::Result<Response, NomError> {
|
||||||
|
match parse_response(s.as_bytes()) {
|
||||||
|
NomResult::Done(_, res) => Ok(res),
|
||||||
|
NomResult::Error(e) => Err(e),
|
||||||
|
NomResult::Incomplete(_) => Err(NomErrorKind::Complete),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl Response {
|
impl Response {
|
||||||
/// Creates a new `Response`
|
/// Creates a new `Response`
|
||||||
pub fn new(code: Code, message: Vec<String>) -> Response {
|
pub fn new(code: Code, message: Vec<String>) -> Response {
|
||||||
Response {
|
Response { code, message }
|
||||||
code: code,
|
|
||||||
message: message,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tells if the response is positive
|
/// Tells if the response is positive
|
||||||
pub fn is_positive(&self) -> bool {
|
pub fn is_positive(&self) -> bool {
|
||||||
match self.code.severity {
|
match self.code.severity {
|
||||||
PositiveCompletion | PositiveIntermediate => true,
|
Severity::PositiveCompletion | Severity::PositiveIntermediate => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tests code equality
|
/// Tests code equality
|
||||||
pub fn has_code(&self, code: u16) -> bool {
|
pub fn has_code(&self, code: u16) -> bool {
|
||||||
self.code.to_string() == format!("{}", code)
|
self.code.to_string() == code.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns only the first word of the message if possible
|
/// Returns only the first word of the message if possible
|
||||||
pub fn first_word(&self) -> Option<&str> {
|
pub fn first_word(&self) -> Option<&str> {
|
||||||
self.message.get(0).and_then(
|
self.message
|
||||||
|line| line.split_whitespace().next(),
|
.get(0)
|
||||||
)
|
.and_then(|line| line.split_whitespace().next())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns only the line of the message if possible
|
/// Returns only the line of the message if possible
|
||||||
@@ -285,36 +169,109 @@ impl Response {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parsers (originaly from tokio-smtp)
|
||||||
|
|
||||||
|
named!(
|
||||||
|
parse_code<Code>,
|
||||||
|
map!(
|
||||||
|
tuple!(parse_severity, parse_category, parse_detail),
|
||||||
|
|(severity, category, detail)| Code {
|
||||||
|
severity,
|
||||||
|
category,
|
||||||
|
detail,
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
named!(
|
||||||
|
parse_severity<Severity>,
|
||||||
|
alt!(
|
||||||
|
tag!("2") => { |_| Severity::PositiveCompletion } |
|
||||||
|
tag!("3") => { |_| Severity::PositiveIntermediate } |
|
||||||
|
tag!("4") => { |_| Severity::TransientNegativeCompletion } |
|
||||||
|
tag!("5") => { |_| Severity::PermanentNegativeCompletion }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
named!(
|
||||||
|
parse_category<Category>,
|
||||||
|
alt!(
|
||||||
|
tag!("0") => { |_| Category::Syntax } |
|
||||||
|
tag!("1") => { |_| Category::Information } |
|
||||||
|
tag!("2") => { |_| Category::Connections } |
|
||||||
|
tag!("3") => { |_| Category::Unspecified3 } |
|
||||||
|
tag!("4") => { |_| Category::Unspecified4 } |
|
||||||
|
tag!("5") => { |_| Category::MailSystem }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
named!(
|
||||||
|
parse_detail<Detail>,
|
||||||
|
alt!(
|
||||||
|
tag!("0") => { |_| Detail::Zero } |
|
||||||
|
tag!("1") => { |_| Detail::One } |
|
||||||
|
tag!("2") => { |_| Detail::Two } |
|
||||||
|
tag!("3") => { |_| Detail::Three } |
|
||||||
|
tag!("4") => { |_| Detail::Four} |
|
||||||
|
tag!("5") => { |_| Detail::Five } |
|
||||||
|
tag!("6") => { |_| Detail::Six} |
|
||||||
|
tag!("7") => { |_| Detail::Seven } |
|
||||||
|
tag!("8") => { |_| Detail::Eight } |
|
||||||
|
tag!("9") => { |_| Detail::Nine }
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
named!(
|
||||||
|
parse_response<Response>,
|
||||||
|
map_res!(
|
||||||
|
tuple!(
|
||||||
|
// Parse any number of continuation lines.
|
||||||
|
many0!(tuple!(
|
||||||
|
parse_code,
|
||||||
|
preceded!(char!('-'), take_until_and_consume!(b"\r\n".as_ref()))
|
||||||
|
)),
|
||||||
|
// Parse the final line.
|
||||||
|
tuple!(
|
||||||
|
parse_code,
|
||||||
|
terminated!(
|
||||||
|
opt!(preceded!(char!(' '), take_until!(b"\r\n".as_ref()))),
|
||||||
|
crlf
|
||||||
|
)
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|(lines, (last_code, last_line)): (Vec<_>, _)| {
|
||||||
|
// Check that all codes are equal.
|
||||||
|
if !lines.iter().all(|&(ref code, _)| *code == last_code) {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extract text from lines, and append last line.
|
||||||
|
let mut lines = lines.into_iter().map(|(_, text)| text).collect::<Vec<_>>();
|
||||||
|
if let Some(text) = last_line {
|
||||||
|
lines.push(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Response {
|
||||||
|
code: last_code,
|
||||||
|
message: lines
|
||||||
|
.into_iter()
|
||||||
|
.map(|line| from_utf8(line).map(|s| s.to_string()))
|
||||||
|
.collect::<result::Result<Vec<_>, _>>()
|
||||||
|
.map_err(|_| ())?,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
use super::{Category, Code, Detail, Response, ResponseParser, Severity};
|
use super::{Category, Code, Detail, Response, Severity};
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_severity_from_str() {
|
|
||||||
assert_eq!(
|
|
||||||
"2".parse::<Severity>().unwrap(),
|
|
||||||
Severity::PositiveCompletion
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
"4".parse::<Severity>().unwrap(),
|
|
||||||
Severity::TransientNegativeCompletion
|
|
||||||
);
|
|
||||||
assert!("1".parse::<Severity>().is_err());
|
|
||||||
assert!("51".parse::<Severity>().is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_severity_fmt() {
|
fn test_severity_fmt() {
|
||||||
assert_eq!(format!("{}", Severity::PositiveCompletion), "2");
|
assert_eq!(format!("{}", Severity::PositiveCompletion), "2");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_category_from_str() {
|
|
||||||
assert_eq!("2".parse::<Category>().unwrap(), Category::Connections);
|
|
||||||
assert_eq!("4".parse::<Category>().unwrap(), Category::Unspecified4);
|
|
||||||
assert!("6".parse::<Category>().is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_category_fmt() {
|
fn test_category_fmt() {
|
||||||
assert_eq!(format!("{}", Category::Unspecified4), "4");
|
assert_eq!(format!("{}", Category::Unspecified4), "4");
|
||||||
@@ -326,121 +283,37 @@ mod test {
|
|||||||
Code::new(
|
Code::new(
|
||||||
Severity::TransientNegativeCompletion,
|
Severity::TransientNegativeCompletion,
|
||||||
Category::Connections,
|
Category::Connections,
|
||||||
Detail(0),
|
Detail::Zero,
|
||||||
),
|
),
|
||||||
Code {
|
Code {
|
||||||
severity: Severity::TransientNegativeCompletion,
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: Category::Connections,
|
category: Category::Connections,
|
||||||
detail: Detail(0),
|
detail: Detail::Zero,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
#[should_panic]
|
|
||||||
fn test_code_new_panic() {
|
|
||||||
let _ = Code::new(
|
|
||||||
Severity::TransientNegativeCompletion,
|
|
||||||
Category::Connections,
|
|
||||||
Detail(11),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_code_from_str() {
|
|
||||||
assert_eq!(
|
|
||||||
"421".parse::<Code>().unwrap(),
|
|
||||||
Code {
|
|
||||||
severity: Severity::TransientNegativeCompletion,
|
|
||||||
category: Category::Connections,
|
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert!("2222".parse::<Code>().is_err());
|
|
||||||
assert!("aaa".parse::<Code>().is_err());
|
|
||||||
assert!("-32".parse::<Code>().is_err());
|
|
||||||
assert!("-333".parse::<Code>().is_err());
|
|
||||||
assert!("".parse::<Code>().is_err());
|
|
||||||
assert!("292".parse::<Code>().is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_code_display() {
|
fn test_code_display() {
|
||||||
let code = Code {
|
let code = Code {
|
||||||
severity: Severity::TransientNegativeCompletion,
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: Category::Connections,
|
category: Category::Connections,
|
||||||
detail: Detail(1),
|
detail: Detail::One,
|
||||||
};
|
};
|
||||||
|
|
||||||
assert_eq!(code.to_string(), "421");
|
assert_eq!(code.to_string(), "421");
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_response_new() {
|
fn test_response_from_str() {
|
||||||
|
let raw_response = "250-me\r\n250-8BITMIME\r\n250-SIZE 42\r\n250 AUTH PLAIN CRAM-MD5\r\n";
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
Response::new(
|
raw_response.parse::<Response>().unwrap(),
|
||||||
Code {
|
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
|
||||||
category: "4".parse::<Category>().unwrap(),
|
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
|
||||||
},
|
|
||||||
vec![
|
|
||||||
"me".to_string(),
|
|
||||||
"8BITMIME".to_string(),
|
|
||||||
"SIZE 42".to_string(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Response {
|
|
||||||
code: Code {
|
|
||||||
severity: Severity::PositiveCompletion,
|
|
||||||
category: Category::Unspecified4,
|
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
|
||||||
},
|
|
||||||
message: vec![
|
|
||||||
"me".to_string(),
|
|
||||||
"8BITMIME".to_string(),
|
|
||||||
"SIZE 42".to_string(),
|
|
||||||
],
|
|
||||||
}
|
|
||||||
);
|
|
||||||
assert_eq!(
|
|
||||||
Response::new(
|
|
||||||
Code {
|
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
|
||||||
category: "4".parse::<Category>().unwrap(),
|
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
|
||||||
},
|
|
||||||
vec![],
|
|
||||||
),
|
|
||||||
Response {
|
|
||||||
code: Code {
|
|
||||||
severity: Severity::PositiveCompletion,
|
|
||||||
category: Category::Unspecified4,
|
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
|
||||||
},
|
|
||||||
message: vec![],
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_response_parser() {
|
|
||||||
let mut parser = ResponseParser::default();
|
|
||||||
|
|
||||||
assert!(parser.read_line("250-me").unwrap());
|
|
||||||
assert!(parser.read_line("250-8BITMIME").unwrap());
|
|
||||||
assert!(parser.read_line("250-SIZE 42").unwrap());
|
|
||||||
assert!(!parser.read_line("250 AUTH PLAIN CRAM-MD5").unwrap());
|
|
||||||
|
|
||||||
let response = parser.response().unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
response,
|
|
||||||
Response {
|
Response {
|
||||||
code: Code {
|
code: Code {
|
||||||
severity: Severity::PositiveCompletion,
|
severity: Severity::PositiveCompletion,
|
||||||
category: Category::MailSystem,
|
category: Category::MailSystem,
|
||||||
detail: Detail(0),
|
detail: Detail::Zero,
|
||||||
},
|
},
|
||||||
message: vec![
|
message: vec![
|
||||||
"me".to_string(),
|
"me".to_string(),
|
||||||
@@ -450,6 +323,12 @@ mod test {
|
|||||||
],
|
],
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
let wrong_code = "2506-me\r\n250-8BITMIME\r\n250-SIZE 42\r\n250 AUTH PLAIN CRAM-MD5\r\n";
|
||||||
|
assert!(wrong_code.parse::<Response>().is_err());
|
||||||
|
|
||||||
|
let wrong_end = "250-me\r\n250-8BITMIME\r\n250-SIZE 42\r\n250-AUTH PLAIN CRAM-MD5\r\n";
|
||||||
|
assert!(wrong_end.parse::<Response>().is_err());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -457,9 +336,9 @@ mod test {
|
|||||||
assert!(
|
assert!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::PositiveCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::Zero,
|
||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
"me".to_string(),
|
"me".to_string(),
|
||||||
@@ -470,9 +349,9 @@ mod test {
|
|||||||
);
|
);
|
||||||
assert!(!Response::new(
|
assert!(!Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "5".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::Zero,
|
||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
"me".to_string(),
|
"me".to_string(),
|
||||||
@@ -487,29 +366,29 @@ mod test {
|
|||||||
assert!(
|
assert!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "4".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
"me".to_string(),
|
"me".to_string(),
|
||||||
"8BITMIME".to_string(),
|
"8BITMIME".to_string(),
|
||||||
"SIZE 42".to_string(),
|
"SIZE 42".to_string(),
|
||||||
],
|
],
|
||||||
).has_code(241)
|
).has_code(451)
|
||||||
);
|
);
|
||||||
assert!(!Response::new(
|
assert!(!Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "5".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
"me".to_string(),
|
"me".to_string(),
|
||||||
"8BITMIME".to_string(),
|
"8BITMIME".to_string(),
|
||||||
"SIZE 42".to_string(),
|
"SIZE 42".to_string(),
|
||||||
],
|
],
|
||||||
).has_code(241));
|
).has_code(251));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -517,9 +396,9 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
"me".to_string(),
|
"me".to_string(),
|
||||||
@@ -532,9 +411,9 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
"me mo".to_string(),
|
"me mo".to_string(),
|
||||||
@@ -547,9 +426,9 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec![],
|
vec![],
|
||||||
).first_word(),
|
).first_word(),
|
||||||
@@ -558,9 +437,9 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec![" ".to_string()],
|
vec![" ".to_string()],
|
||||||
).first_word(),
|
).first_word(),
|
||||||
@@ -569,9 +448,9 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec![" ".to_string()],
|
vec![" ".to_string()],
|
||||||
).first_word(),
|
).first_word(),
|
||||||
@@ -580,9 +459,9 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec!["".to_string()],
|
vec!["".to_string()],
|
||||||
).first_word(),
|
).first_word(),
|
||||||
@@ -595,9 +474,9 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
"me".to_string(),
|
"me".to_string(),
|
||||||
@@ -610,9 +489,9 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec![
|
vec![
|
||||||
"me mo".to_string(),
|
"me mo".to_string(),
|
||||||
@@ -625,9 +504,9 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec![],
|
vec![],
|
||||||
).first_line(),
|
).first_line(),
|
||||||
@@ -636,9 +515,9 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec![" ".to_string()],
|
vec![" ".to_string()],
|
||||||
).first_line(),
|
).first_line(),
|
||||||
@@ -647,9 +526,9 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec![" ".to_string()],
|
vec![" ".to_string()],
|
||||||
).first_line(),
|
).first_line(),
|
||||||
@@ -658,9 +537,9 @@ mod test {
|
|||||||
assert_eq!(
|
assert_eq!(
|
||||||
Response::new(
|
Response::new(
|
||||||
Code {
|
Code {
|
||||||
severity: "2".parse::<Severity>().unwrap(),
|
severity: Severity::TransientNegativeCompletion,
|
||||||
category: "3".parse::<Category>().unwrap(),
|
category: Category::MailSystem,
|
||||||
detail: "1".parse::<Detail>().unwrap(),
|
detail: Detail::One,
|
||||||
},
|
},
|
||||||
vec!["".to_string()],
|
vec!["".to_string()],
|
||||||
).first_line(),
|
).first_line(),
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ use std::fmt::{Display, Formatter, Result as FmtResult};
|
|||||||
|
|
||||||
/// Encode a string as xtext
|
/// Encode a string as xtext
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
#[cfg_attr(feature = "serde-impls", derive(Serialize, Deserialize))]
|
||||||
pub struct XText<'a>(pub &'a str);
|
pub struct XText<'a>(pub &'a str);
|
||||||
|
|
||||||
impl<'a> Display for XText<'a> {
|
impl<'a> Display for XText<'a> {
|
||||||
@@ -27,7 +28,6 @@ impl<'a> Display for XText<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::XText;
|
use super::XText;
|
||||||
@@ -39,8 +39,7 @@ mod tests {
|
|||||||
("bjørn", "bjørn"),
|
("bjørn", "bjørn"),
|
||||||
("Ø+= ❤️‰", "Ø+2B+3D+20❤️‰"),
|
("Ø+= ❤️‰", "Ø+2B+3D+20❤️‰"),
|
||||||
("+", "+2B"),
|
("+", "+2B"),
|
||||||
]
|
] {
|
||||||
{
|
|
||||||
assert_eq!(format!("{}", XText(input)), expect);
|
assert_eq!(format!("{}", XText(input)), expect);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,34 +1,13 @@
|
|||||||
//! The stub transport only logs message envelope and drops the content. It can be useful for
|
//! The stub transport only logs message envelope and drops the content. It can be useful for
|
||||||
//! testing purposes.
|
//! testing purposes.
|
||||||
//!
|
//!
|
||||||
//! ```rust
|
|
||||||
//! use lettre::stub::StubEmailTransport;
|
|
||||||
//! use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress};
|
|
||||||
//!
|
|
||||||
//! let email = SimpleSendableEmail::new(
|
|
||||||
//! EmailAddress::new("user@localhost".to_string()),
|
|
||||||
//! vec![EmailAddress::new("root@localhost".to_string())],
|
|
||||||
//! "message_id".to_string(),
|
|
||||||
//! "Hello world".to_string(),
|
|
||||||
//! );
|
|
||||||
//!
|
|
||||||
//! let mut sender = StubEmailTransport::new_positive();
|
|
||||||
//! let result = sender.send(&email);
|
|
||||||
//! assert!(result.is_ok());
|
|
||||||
//! ```
|
|
||||||
//!
|
|
||||||
//! Will log (when using a logger like `env_logger`):
|
|
||||||
//!
|
|
||||||
//! ```text
|
|
||||||
//! b7c211bc-9811-45ce-8cd9-68eab575d695: from=<user@localhost> to=<root@localhost>
|
|
||||||
//! ```
|
|
||||||
|
|
||||||
use EmailTransport;
|
use EmailTransport;
|
||||||
use SendableEmail;
|
use SendableEmail;
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
|
||||||
/// This transport logs the message envelope and returns the given response
|
/// This transport logs the message envelope and returns the given response
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub struct StubEmailTransport {
|
pub struct StubEmailTransport {
|
||||||
response: StubResult,
|
response: StubResult,
|
||||||
}
|
}
|
||||||
@@ -36,14 +15,12 @@ pub struct StubEmailTransport {
|
|||||||
impl StubEmailTransport {
|
impl StubEmailTransport {
|
||||||
/// Creates a new transport that always returns the given response
|
/// Creates a new transport that always returns the given response
|
||||||
pub fn new(response: StubResult) -> StubEmailTransport {
|
pub fn new(response: StubResult) -> StubEmailTransport {
|
||||||
StubEmailTransport { response: response }
|
StubEmailTransport { response }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a new transport that always returns a success response
|
/// Creates a new transport that always returns a success response
|
||||||
pub fn new_positive() -> StubEmailTransport {
|
pub fn new_positive() -> StubEmailTransport {
|
||||||
StubEmailTransport {
|
StubEmailTransport { response: Ok(()) }
|
||||||
response: Ok(()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,12 +29,15 @@ pub type StubResult = Result<(), ()>;
|
|||||||
|
|
||||||
impl<'a, T: Read + 'a> EmailTransport<'a, T, StubResult> for StubEmailTransport {
|
impl<'a, T: Read + 'a> EmailTransport<'a, T, StubResult> for StubEmailTransport {
|
||||||
fn send<U: SendableEmail<'a, T>>(&mut self, email: &'a U) -> StubResult {
|
fn send<U: SendableEmail<'a, T>>(&mut self, email: &'a U) -> StubResult {
|
||||||
|
let envelope = email.envelope();
|
||||||
info!(
|
info!(
|
||||||
"{}: from=<{}> to=<{:?}>",
|
"{}: from=<{}> to=<{:?}>",
|
||||||
email.message_id(),
|
email.message_id(),
|
||||||
email.from(),
|
match envelope.from() {
|
||||||
email.to()
|
Some(address) => address.to_string(),
|
||||||
|
None => "".to_string(),
|
||||||
|
},
|
||||||
|
envelope.to()
|
||||||
);
|
);
|
||||||
self.response
|
self.response
|
||||||
}
|
}
|
||||||
|
|||||||
62
lettre/tests/skeptic.rs
Normal file
62
lettre/tests/skeptic.rs
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
extern crate glob;
|
||||||
|
|
||||||
|
use self::glob::glob;
|
||||||
|
use std::env::consts::EXE_EXTENSION;
|
||||||
|
use std::env;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_readme() {
|
||||||
|
let readme = Path::new(file!())
|
||||||
|
.parent()
|
||||||
|
.unwrap()
|
||||||
|
.parent()
|
||||||
|
.unwrap()
|
||||||
|
.parent()
|
||||||
|
.unwrap()
|
||||||
|
.join("README.md");
|
||||||
|
|
||||||
|
skeptic_test(&readme);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn book_test() {
|
||||||
|
let mut book_path = env::current_dir().unwrap();
|
||||||
|
book_path.push(
|
||||||
|
Path::new(file!())
|
||||||
|
.parent()
|
||||||
|
.unwrap()
|
||||||
|
.parent()
|
||||||
|
.unwrap()
|
||||||
|
.parent()
|
||||||
|
.unwrap()
|
||||||
|
.join("../website/content/sending-messages"),
|
||||||
|
); // For some reasons, calling .parent() once more gives us None...
|
||||||
|
|
||||||
|
for md in glob(&format!("{}/*.md", book_path.to_str().unwrap())).unwrap() {
|
||||||
|
skeptic_test(&md.unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn skeptic_test(path: &Path) {
|
||||||
|
let rustdoc = Path::new("rustdoc").with_extension(EXE_EXTENSION);
|
||||||
|
let exe = env::current_exe().unwrap();
|
||||||
|
let depdir = exe.parent().unwrap();
|
||||||
|
|
||||||
|
let mut cmd = Command::new(rustdoc);
|
||||||
|
cmd.args(&["--verbose", "--test"])
|
||||||
|
.arg("-L")
|
||||||
|
.arg(&depdir)
|
||||||
|
.arg(path);
|
||||||
|
|
||||||
|
let result = cmd.spawn()
|
||||||
|
.expect("Failed to spawn process")
|
||||||
|
.wait()
|
||||||
|
.expect("Failed to run process");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
result.success(),
|
||||||
|
format!("Failed to run rustdoc tests on {:?}", path)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@ extern crate lettre;
|
|||||||
#[cfg(feature = "file-transport")]
|
#[cfg(feature = "file-transport")]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
use lettre::{EmailAddress, EmailTransport, SendableEmail, SimpleSendableEmail};
|
use lettre::{EmailTransport, SendableEmail, SimpleSendableEmail};
|
||||||
use lettre::file::FileEmailTransport;
|
use lettre::file::FileEmailTransport;
|
||||||
use std::env::temp_dir;
|
use std::env::temp_dir;
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
@@ -15,11 +15,11 @@ mod test {
|
|||||||
fn file_transport() {
|
fn file_transport() {
|
||||||
let mut sender = FileEmailTransport::new(temp_dir());
|
let mut sender = FileEmailTransport::new(temp_dir());
|
||||||
let email = SimpleSendableEmail::new(
|
let email = SimpleSendableEmail::new(
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
"user@localhost".to_string(),
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
&["root@localhost".to_string()],
|
||||||
"file_id".to_string(),
|
"file_id".to_string(),
|
||||||
"Hello file".to_string(),
|
"Hello file".to_string(),
|
||||||
);
|
).unwrap();
|
||||||
let result = sender.send(&email);
|
let result = sender.send(&email);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
|
||||||
@@ -31,8 +31,7 @@ mod test {
|
|||||||
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
buffer,
|
buffer,
|
||||||
"{\"to\":[\"root@localhost\"],\"from\":\"user@localhost\",\"message_id\":\
|
"{\"envelope\":{\"forward_path\":[\"root@localhost\"],\"reverse_path\":\"user@localhost\"},\"message_id\":\"file_id\",\"message\":[72,101,108,108,111,32,102,105,108,101]}"
|
||||||
\"file_id\",\"message\":[72,101,108,108,111,32,102,105,108,101]}"
|
|
||||||
);
|
);
|
||||||
|
|
||||||
remove_file(file).unwrap();
|
remove_file(file).unwrap();
|
||||||
|
|||||||
@@ -4,18 +4,18 @@ extern crate lettre;
|
|||||||
#[cfg(feature = "sendmail-transport")]
|
#[cfg(feature = "sendmail-transport")]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
use lettre::{EmailAddress, EmailTransport, SimpleSendableEmail};
|
use lettre::{EmailTransport, SimpleSendableEmail};
|
||||||
use lettre::sendmail::SendmailTransport;
|
use lettre::sendmail::SendmailTransport;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn sendmail_transport_simple() {
|
fn sendmail_transport_simple() {
|
||||||
let mut sender = SendmailTransport::new();
|
let mut sender = SendmailTransport::new();
|
||||||
let email = SimpleSendableEmail::new(
|
let email = SimpleSendableEmail::new(
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
"user@localhost".to_string(),
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
&["root@localhost".to_string()],
|
||||||
"sendmail_id".to_string(),
|
"sendmail_id".to_string(),
|
||||||
"Hello sendmail".to_string(),
|
"Hello sendmail".to_string(),
|
||||||
);
|
).unwrap();
|
||||||
|
|
||||||
let result = sender.send(&email);
|
let result = sender.send(&email);
|
||||||
println!("{:?}", result);
|
println!("{:?}", result);
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ extern crate lettre;
|
|||||||
#[cfg(feature = "smtp-transport")]
|
#[cfg(feature = "smtp-transport")]
|
||||||
mod test {
|
mod test {
|
||||||
|
|
||||||
use lettre::{ClientSecurity, EmailAddress, EmailTransport, SimpleSendableEmail, SmtpTransport};
|
use lettre::{ClientSecurity, EmailTransport, SimpleSendableEmail, SmtpTransport};
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn smtp_transport_simple() {
|
fn smtp_transport_simple() {
|
||||||
@@ -12,11 +12,11 @@ mod test {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.build();
|
.build();
|
||||||
let email = SimpleSendableEmail::new(
|
let email = SimpleSendableEmail::new(
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
"user@localhost".to_string(),
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
&["root@localhost".to_string()],
|
||||||
"smtp_id".to_string(),
|
"smtp_id".to_string(),
|
||||||
"Hello smtp".to_string(),
|
"Hello smtp".to_string(),
|
||||||
);
|
).unwrap();
|
||||||
|
|
||||||
sender.send(&email).unwrap();
|
sender.send(&email).unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
extern crate lettre;
|
extern crate lettre;
|
||||||
|
|
||||||
use lettre::{EmailAddress, EmailTransport, SimpleSendableEmail};
|
use lettre::{EmailTransport, SimpleSendableEmail};
|
||||||
use lettre::stub::StubEmailTransport;
|
use lettre::stub::StubEmailTransport;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn stub_transport() {
|
fn stub_transport() {
|
||||||
let mut sender_ok = StubEmailTransport::new_positive();
|
let mut sender_ok = StubEmailTransport::new_positive();
|
||||||
let mut sender_ko = StubEmailTransport::new(Err(()));
|
let mut sender_ko = StubEmailTransport::new(Err(()));
|
||||||
|
|
||||||
let email = SimpleSendableEmail::new(
|
let email = SimpleSendableEmail::new(
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
"user@localhost".to_string(),
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
&["root@localhost".to_string()],
|
||||||
"stub_id".to_string(),
|
"stub_id".to_string(),
|
||||||
"Hello stub".to_string(),
|
"Hello stub".to_string(),
|
||||||
);
|
).unwrap();
|
||||||
|
|
||||||
sender_ok.send(&email).unwrap();
|
sender_ok.send(&email).unwrap();
|
||||||
sender_ko.send(&email).unwrap_err();
|
sender_ko.send(&email).unwrap_err();
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
### v0.7.0 (2017-10-08)
|
|
||||||
|
|
||||||
#### Features
|
|
||||||
|
|
||||||
* **all**
|
|
||||||
* Split into the *lettre* and *lettre_email* crates
|
|
||||||
* A lot of small improvements
|
|
||||||
|
|
||||||
* **email**
|
|
||||||
* Initial (incomplete) attachments support
|
|
||||||
|
|
||||||
### v0.6.2 (2017-02-18)
|
|
||||||
|
|
||||||
#### Features
|
|
||||||
|
|
||||||
* **all**
|
|
||||||
* Update uuid crate to 0.4
|
|
||||||
|
|
||||||
### 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
|
|
||||||
1
lettre_email/CHANGELOG.md
Symbolic link
1
lettre_email/CHANGELOG.md
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../CHANGELOG.md
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
|
|
||||||
name = "lettre_email"
|
name = "lettre_email"
|
||||||
version = "0.7.0"
|
version = "0.8.1" # remember to update html_root_url
|
||||||
description = "Email builder"
|
description = "Email builder"
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
documentation = "https://docs.rs/lettre_email/"
|
documentation = "https://docs.rs/lettre_email/"
|
||||||
@@ -15,12 +15,13 @@ keywords = ["email", "mailer"]
|
|||||||
travis-ci = { repository = "lettre/lettre_email" }
|
travis-ci = { repository = "lettre/lettre_email" }
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
env_logger = "*"
|
lettre = { version = "^0.8", path = "../lettre", features = ["smtp-transport"] }
|
||||||
lettre = { path = "../lettre", features = ["smtp-transport"] }
|
glob = "0.2"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
email = "^0.0"
|
email = "^0.0"
|
||||||
mime = "^0.3"
|
mime = "^0.3"
|
||||||
time = "^0.1"
|
time = "^0.1"
|
||||||
uuid = { version = ">=0.4, <0.6", features = ["v4"] }
|
uuid = { version = "^0.6", features = ["v4"] }
|
||||||
lettre = { path = "../lettre", default-features = false }
|
lettre = { version = "^0.8", path = "../lettre", default-features = false }
|
||||||
|
base64 = "^0.9"
|
||||||
|
|||||||
@@ -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(Path::new("Cargo.toml"), None, &mime::TEXT_PLAIN).unwrap()
|
||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
../rustfmt.toml
|
|
||||||
@@ -2,16 +2,16 @@
|
|||||||
|
|
||||||
use self::Error::*;
|
use self::Error::*;
|
||||||
use std::error::Error as StdError;
|
use std::error::Error as StdError;
|
||||||
use std::io;
|
|
||||||
use std::fmt::{self, Display, Formatter};
|
use std::fmt::{self, Display, Formatter};
|
||||||
|
use std::io;
|
||||||
|
|
||||||
|
use lettre;
|
||||||
|
|
||||||
/// An enum of all error kinds.
|
/// An enum of all error kinds.
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum Error {
|
pub enum Error {
|
||||||
/// Missing sender
|
/// Envelope error
|
||||||
MissingFrom,
|
Email(lettre::Error),
|
||||||
/// Missing recipient
|
|
||||||
MissingTo,
|
|
||||||
/// Unparseable filename for attachment
|
/// Unparseable filename for attachment
|
||||||
CannotParseFilename,
|
CannotParseFilename,
|
||||||
/// IO error
|
/// IO error
|
||||||
@@ -27,8 +27,7 @@ impl Display for Error {
|
|||||||
impl StdError for Error {
|
impl StdError for Error {
|
||||||
fn description(&self) -> &str {
|
fn description(&self) -> &str {
|
||||||
match *self {
|
match *self {
|
||||||
MissingFrom => "the sender is missing",
|
Email(ref err) => err.description(),
|
||||||
MissingTo => "the recipient is missing",
|
|
||||||
CannotParseFilename => "the attachment filename could not be parsed",
|
CannotParseFilename => "the attachment filename could not be parsed",
|
||||||
Io(ref err) => err.description(),
|
Io(ref err) => err.description(),
|
||||||
}
|
}
|
||||||
@@ -41,3 +40,8 @@ impl From<io::Error> for Error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<lettre::Error> for Error {
|
||||||
|
fn from(err: lettre::Error) -> Error {
|
||||||
|
Email(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,76 +1,30 @@
|
|||||||
//! Lettre is a mailer written in Rust. It provides a simple email builder and several transports.
|
//! Lettre is a mailer written in Rust. lettre_email provides a simple email builder.
|
||||||
//!
|
|
||||||
//! ## 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::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.
|
|
||||||
//!
|
//!
|
||||||
|
|
||||||
#![deny(missing_docs, unsafe_code, unstable_features, warnings, missing_debug_implementations)]
|
#![doc(html_root_url = "https://docs.rs/lettre_email/0.8.1")]
|
||||||
|
#![deny(missing_docs, missing_debug_implementations, missing_copy_implementations, trivial_casts,
|
||||||
|
trivial_numeric_casts, unsafe_code, unstable_features, unused_import_braces,
|
||||||
|
unused_qualifications)]
|
||||||
|
|
||||||
|
extern crate base64;
|
||||||
|
extern crate email as email_format;
|
||||||
|
extern crate lettre;
|
||||||
extern crate mime;
|
extern crate mime;
|
||||||
extern crate time;
|
extern crate time;
|
||||||
extern crate uuid;
|
extern crate uuid;
|
||||||
extern crate email as email_format;
|
|
||||||
extern crate lettre;
|
|
||||||
|
|
||||||
pub mod error;
|
pub mod error;
|
||||||
|
|
||||||
pub use email_format::{Address, Header, Mailbox, MimeMessage, MimeMultipartType};
|
pub use email_format::{Address, Header, Mailbox, MimeMessage, MimeMultipartType};
|
||||||
use error::Error;
|
use error::Error;
|
||||||
use lettre::{EmailAddress, SendableEmail};
|
use lettre::{EmailAddress, Envelope, Error as EmailError, SendableEmail};
|
||||||
use mime::Mime;
|
use mime::Mime;
|
||||||
use time::{Tm, now};
|
|
||||||
use uuid::Uuid;
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::path::Path;
|
|
||||||
use std::io::Read;
|
use std::io::Read;
|
||||||
|
use std::path::Path;
|
||||||
|
use time::{now, Tm};
|
||||||
|
use uuid::Uuid;
|
||||||
|
use std::str::FromStr;
|
||||||
|
|
||||||
/// Converts an address or an address with an alias to a `Header`
|
/// Converts an address or an address with an alias to a `Header`
|
||||||
pub trait IntoHeader {
|
pub trait IntoHeader {
|
||||||
@@ -169,7 +123,6 @@ impl IntoEmail for SimpleEmail {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Simple representation of an email, useful for some transports
|
/// Simple representation of an email, useful for some transports
|
||||||
#[derive(PartialEq, Eq, Clone, Debug, Default)]
|
#[derive(PartialEq, Eq, Clone, Debug, Default)]
|
||||||
pub struct SimpleEmail {
|
pub struct SimpleEmail {
|
||||||
@@ -322,7 +275,6 @@ impl Default for PartBuilder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Builds an `Email` structure
|
/// Builds an `Email` structure
|
||||||
#[derive(PartialEq, Eq, Clone, Debug, Default)]
|
#[derive(PartialEq, Eq, Clone, Debug, Default)]
|
||||||
pub struct EmailBuilder {
|
pub struct EmailBuilder {
|
||||||
@@ -346,43 +298,6 @@ pub struct EmailBuilder {
|
|||||||
date_issued: bool,
|
date_issued: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Simple email enveloppe representation
|
|
||||||
#[derive(PartialEq, Eq, Clone, Debug, Default)]
|
|
||||||
pub struct Envelope {
|
|
||||||
/// The envelope recipients' addresses
|
|
||||||
pub to: Vec<String>,
|
|
||||||
/// The envelope sender address
|
|
||||||
pub from: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Envelope {
|
|
||||||
/// Constructs an envelope with no receivers and an empty sender
|
|
||||||
pub fn new() -> Self {
|
|
||||||
Envelope {
|
|
||||||
to: vec![],
|
|
||||||
from: String::new(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// Adds a receiver
|
|
||||||
pub fn to<S: Into<String>>(mut self, address: S) -> Self {
|
|
||||||
self.add_to(address);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
/// Adds a receiver
|
|
||||||
pub fn add_to<S: Into<String>>(&mut self, address: S) {
|
|
||||||
self.to.push(address.into());
|
|
||||||
}
|
|
||||||
/// Sets the sender
|
|
||||||
pub fn from<S: Into<String>>(mut self, address: S) -> Self {
|
|
||||||
self.set_from(address);
|
|
||||||
self
|
|
||||||
}
|
|
||||||
/// Sets the sender
|
|
||||||
pub fn set_from<S: Into<String>>(&mut self, address: S) {
|
|
||||||
self.from = address.into();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Simple email representation
|
/// Simple email representation
|
||||||
#[derive(PartialEq, Eq, Clone, Debug)]
|
#[derive(PartialEq, Eq, Clone, Debug)]
|
||||||
pub struct Email {
|
pub struct Email {
|
||||||
@@ -397,7 +312,9 @@ pub struct Email {
|
|||||||
impl PartBuilder {
|
impl PartBuilder {
|
||||||
/// Creates a new empty part
|
/// Creates a new empty part
|
||||||
pub fn new() -> PartBuilder {
|
pub fn new() -> PartBuilder {
|
||||||
PartBuilder { message: MimeMessage::new_blank_message() }
|
PartBuilder {
|
||||||
|
message: MimeMessage::new_blank_message(),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a generic header
|
/// Adds a generic header
|
||||||
@@ -434,13 +351,13 @@ impl PartBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a `ContentType` header with the given MIME type
|
/// Adds a `ContentType` header with the given MIME type
|
||||||
pub fn content_type(mut self, content_type: Mime) -> PartBuilder {
|
pub fn content_type(mut self, content_type: &Mime) -> PartBuilder {
|
||||||
self.set_content_type(content_type);
|
self.set_content_type(content_type);
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a `ContentType` header with the given MIME type
|
/// Adds a `ContentType` header with the given MIME type
|
||||||
pub fn set_content_type(&mut self, content_type: Mime) {
|
pub fn set_content_type(&mut self, content_type: &Mime) {
|
||||||
self.add_header(("Content-Type", format!("{}", content_type).as_ref()));
|
self.add_header(("Content-Type", format!("{}", content_type).as_ref()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -580,9 +497,8 @@ impl EmailBuilder {
|
|||||||
|
|
||||||
/// Adds a `Subject` header
|
/// Adds a `Subject` header
|
||||||
pub fn set_subject<S: Into<String>>(&mut self, subject: S) {
|
pub fn set_subject<S: Into<String>>(&mut self, subject: S) {
|
||||||
self.message.add_header(
|
self.message
|
||||||
("Subject".to_string(), subject.into()),
|
.add_header(("Subject".to_string(), subject.into()));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds a `Date` header with the given date
|
/// Adds a `Date` header with the given date
|
||||||
@@ -593,26 +509,35 @@ impl EmailBuilder {
|
|||||||
|
|
||||||
/// Adds a `Date` header with the given date
|
/// Adds a `Date` header with the given date
|
||||||
pub fn set_date(&mut self, date: &Tm) {
|
pub fn set_date(&mut self, date: &Tm) {
|
||||||
self.message.add_header(
|
self.message
|
||||||
("Date", Tm::rfc822z(date).to_string()),
|
.add_header(("Date", Tm::rfc822z(date).to_string()));
|
||||||
);
|
|
||||||
self.date_issued = true;
|
self.date_issued = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds an attachment to the email
|
/// Adds an attachment to the email
|
||||||
pub fn attachment(mut self, path: &Path, filename: Option<&str>, content_type: Mime) -> Result<EmailBuilder, Error> {
|
pub fn attachment(
|
||||||
|
mut self,
|
||||||
|
path: &Path,
|
||||||
|
filename: Option<&str>,
|
||||||
|
content_type: &Mime,
|
||||||
|
) -> Result<EmailBuilder, Error> {
|
||||||
self.set_attachment(path, filename, content_type)?;
|
self.set_attachment(path, filename, content_type)?;
|
||||||
Ok(self)
|
Ok(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds an attachment to the email
|
/// Adds an attachment to the email
|
||||||
/// If filename is not provided, the name of the file will be used.
|
/// If filename is not provided, the name of the file will be used.
|
||||||
pub fn set_attachment(&mut self, path: &Path, filename: Option<&str>, content_type: Mime) -> Result<(), Error> {
|
pub fn set_attachment(
|
||||||
|
&mut self,
|
||||||
|
path: &Path,
|
||||||
|
filename: Option<&str>,
|
||||||
|
content_type: &Mime,
|
||||||
|
) -> Result<(), Error> {
|
||||||
let file = File::open(path);
|
let file = File::open(path);
|
||||||
let body = match file {
|
let body = match file {
|
||||||
Ok(mut f) => {
|
Ok(mut f) => {
|
||||||
let mut data = String::new();
|
let mut data = Vec::new();
|
||||||
let read = f.read_to_string(&mut data);
|
let read = f.read_to_end(&mut data);
|
||||||
match read {
|
match read {
|
||||||
Ok(_) => data,
|
Ok(_) => data,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
@@ -636,10 +561,15 @@ impl EmailBuilder {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let encoded_body = base64::encode(&body);
|
||||||
let content = PartBuilder::new()
|
let content = PartBuilder::new()
|
||||||
.body(body)
|
.body(encoded_body)
|
||||||
.header(("Content-Disposition", format!("attachment; filename=\"{}\"", actual_filename)))
|
.header((
|
||||||
|
"Content-Disposition",
|
||||||
|
format!("attachment; filename=\"{}\"", actual_filename),
|
||||||
|
))
|
||||||
.header(("Content-Type", content_type.to_string()))
|
.header(("Content-Type", content_type.to_string()))
|
||||||
|
.header(("Content-Transfer-Encoding", "base64"))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
self.set_message_type(MimeMultipartType::Mixed);
|
self.set_message_type(MimeMultipartType::Mixed);
|
||||||
@@ -678,11 +608,14 @@ impl EmailBuilder {
|
|||||||
|
|
||||||
/// Sets the email body to plain text content
|
/// Sets the email body to plain text content
|
||||||
pub fn set_text<S: Into<String>>(&mut self, body: S) {
|
pub fn set_text<S: Into<String>>(&mut self, body: S) {
|
||||||
self.message.set_body(body);
|
let text = PartBuilder::new()
|
||||||
self.message.add_header((
|
.body(body)
|
||||||
|
.header((
|
||||||
"Content-Type",
|
"Content-Type",
|
||||||
format!("{}", mime::TEXT_PLAIN_UTF_8).as_ref(),
|
format!("{}", mime::TEXT_PLAIN_UTF_8).as_ref(),
|
||||||
));
|
))
|
||||||
|
.build();
|
||||||
|
self.add_child(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the email body to HTML content
|
/// Sets the email body to HTML content
|
||||||
@@ -693,11 +626,14 @@ impl EmailBuilder {
|
|||||||
|
|
||||||
/// Sets the email body to HTML content
|
/// Sets the email body to HTML content
|
||||||
pub fn set_html<S: Into<String>>(&mut self, body: S) {
|
pub fn set_html<S: Into<String>>(&mut self, body: S) {
|
||||||
self.message.set_body(body);
|
let html = PartBuilder::new()
|
||||||
self.message.add_header((
|
.body(body)
|
||||||
|
.header((
|
||||||
"Content-Type",
|
"Content-Type",
|
||||||
format!("{}", mime::TEXT_HTML).as_ref(),
|
format!("{}", mime::TEXT_HTML_UTF_8).as_ref(),
|
||||||
));
|
))
|
||||||
|
.build();
|
||||||
|
self.add_child(html);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets the email content
|
/// Sets the email content
|
||||||
@@ -729,7 +665,10 @@ impl EmailBuilder {
|
|||||||
|
|
||||||
let html = PartBuilder::new()
|
let html = PartBuilder::new()
|
||||||
.body(body_html)
|
.body(body_html)
|
||||||
.header(("Content-Type", format!("{}", mime::TEXT_HTML).as_ref()))
|
.header((
|
||||||
|
"Content-Type",
|
||||||
|
format!("{}", mime::TEXT_HTML_UTF_8).as_ref(),
|
||||||
|
))
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
alternate.add_child(text);
|
alternate.add_child(text);
|
||||||
@@ -780,25 +719,21 @@ impl EmailBuilder {
|
|||||||
Some(e) => e,
|
Some(e) => e,
|
||||||
None => {
|
None => {
|
||||||
// we need to generate the envelope
|
// we need to generate the envelope
|
||||||
let mut e = Envelope::new();
|
let mut e = Envelope::builder();
|
||||||
// add all receivers in to_header and cc_header
|
// add all receivers in to_header and cc_header
|
||||||
for receiver in self.to_header.iter().chain(self.cc_header.iter()).chain(
|
for receiver in self.to_header
|
||||||
self.bcc_header.iter(),
|
.iter()
|
||||||
)
|
.chain(self.cc_header.iter())
|
||||||
|
.chain(self.bcc_header.iter())
|
||||||
{
|
{
|
||||||
match *receiver {
|
match *receiver {
|
||||||
Address::Mailbox(ref m) => e.add_to(m.address.clone()),
|
Address::Mailbox(ref m) => e.add_to(EmailAddress::from_str(&m.address)?),
|
||||||
Address::Group(_, ref ms) => {
|
Address::Group(_, ref ms) => for m in ms.iter() {
|
||||||
for m in ms.iter() {
|
e.add_to(EmailAddress::from_str(&m.address.clone())?);
|
||||||
e.add_to(m.address.clone());
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
e.set_from(EmailAddress::from_str(&match self.sender_header {
|
||||||
}
|
|
||||||
if e.to.is_empty() {
|
|
||||||
return Err(Error::MissingTo);
|
|
||||||
}
|
|
||||||
e.set_from(match self.sender_header {
|
|
||||||
Some(x) => x.address.clone(), // if we have a sender_header, use it
|
Some(x) => x.address.clone(), // if we have a sender_header, use it
|
||||||
None => {
|
None => {
|
||||||
// use a from header
|
// use a from header
|
||||||
@@ -811,41 +746,36 @@ impl EmailBuilder {
|
|||||||
// if it's an author group, use the first author
|
// if it's an author group, use the first author
|
||||||
Some(mailbox) => mailbox.address.clone(),
|
Some(mailbox) => mailbox.address.clone(),
|
||||||
// for an empty author group (the rarest of the rare cases)
|
// for an empty author group (the rarest of the rare cases)
|
||||||
None => return Err(Error::MissingFrom), // empty envelope sender
|
None => return Err(Error::Email(EmailError::MissingFrom)), // empty envelope sender
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// if we don't have a from header
|
// if we don't have a from header
|
||||||
None => return Err(Error::MissingFrom), // empty envelope sender
|
None => return Err(Error::Email(EmailError::MissingFrom)), // empty envelope sender
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
})?);
|
||||||
e
|
e.build()?
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
// Add the collected addresses as mailbox-list all at once.
|
// Add the collected addresses as mailbox-list all at once.
|
||||||
// The unwraps are fine because the conversions for Vec<Address> never errs.
|
// The unwraps are fine because the conversions for Vec<Address> never errs.
|
||||||
if !self.to_header.is_empty() {
|
if !self.to_header.is_empty() {
|
||||||
self.message.add_header(
|
self.message
|
||||||
Header::new_with_value(
|
.add_header(Header::new_with_value("To".into(), self.to_header).unwrap());
|
||||||
"To".into(),
|
|
||||||
self.to_header,
|
|
||||||
).unwrap(),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
if !self.from_header.is_empty() {
|
if !self.from_header.is_empty() {
|
||||||
self.message.add_header(
|
self.message
|
||||||
Header::new_with_value("From".into(), self.from_header).unwrap(),
|
.add_header(Header::new_with_value("From".into(), self.from_header).unwrap());
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
return Err(Error::MissingFrom);
|
return Err(Error::Email(EmailError::MissingFrom));
|
||||||
}
|
}
|
||||||
if !self.cc_header.is_empty() {
|
if !self.cc_header.is_empty() {
|
||||||
self.message.add_header(
|
self.message
|
||||||
Header::new_with_value(
|
.add_header(Header::new_with_value("Cc".into(), self.cc_header).unwrap());
|
||||||
"Cc".into(),
|
}
|
||||||
self.cc_header,
|
if !self.bcc_header.is_empty() {
|
||||||
).unwrap(),
|
self.message
|
||||||
);
|
.add_header(Header::new_with_value("Bcc".into(), self.bcc_header).unwrap());
|
||||||
}
|
}
|
||||||
if !self.reply_to_header.is_empty() {
|
if !self.reply_to_header.is_empty() {
|
||||||
self.message.add_header(
|
self.message.add_header(
|
||||||
@@ -854,10 +784,8 @@ impl EmailBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !self.date_issued {
|
if !self.date_issued {
|
||||||
self.message.add_header((
|
self.message
|
||||||
"Date",
|
.add_header(("Date", Tm::rfc822z(&now()).to_string().as_ref()));
|
||||||
Tm::rfc822z(&now()).to_string().as_ref(),
|
|
||||||
));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
self.message.add_header(("MIME-Version", "1.0"));
|
self.message.add_header(("MIME-Version", "1.0"));
|
||||||
@@ -867,34 +795,25 @@ impl EmailBuilder {
|
|||||||
if let Ok(header) = Header::new_with_value(
|
if let Ok(header) = Header::new_with_value(
|
||||||
"Message-ID".to_string(),
|
"Message-ID".to_string(),
|
||||||
format!("<{}.lettre@localhost>", message_id),
|
format!("<{}.lettre@localhost>", message_id),
|
||||||
)
|
) {
|
||||||
{
|
|
||||||
self.message.add_header(header)
|
self.message.add_header(header)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Email {
|
Ok(Email {
|
||||||
message: self.message.build().as_string().into_bytes(),
|
message: self.message.build().as_string().into_bytes(),
|
||||||
envelope: envelope,
|
envelope,
|
||||||
message_id: message_id,
|
message_id,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SendableEmail<'a, &'a [u8]> for Email {
|
impl<'a> SendableEmail<'a, &'a [u8]> for Email {
|
||||||
fn to(&self) -> Vec<EmailAddress> {
|
fn envelope(&self) -> Envelope {
|
||||||
self.envelope
|
self.envelope.clone()
|
||||||
.to
|
|
||||||
.iter()
|
|
||||||
.map(|x| EmailAddress::new(x.clone()))
|
|
||||||
.collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn from(&self) -> EmailAddress {
|
|
||||||
EmailAddress::new(self.envelope.from.clone())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn message_id(&self) -> String {
|
fn message_id(&self) -> String {
|
||||||
format!("{}", self.message_id)
|
self.message_id.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn message(&'a self) -> Box<&[u8]> {
|
fn message(&'a self) -> Box<&[u8]> {
|
||||||
@@ -926,45 +845,12 @@ pub trait ExtractableEmail {
|
|||||||
fn text(self) -> String;
|
fn text(self) -> String;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod test {
|
mod test {
|
||||||
|
use super::EmailBuilder;
|
||||||
use super::{EmailBuilder, IntoEmail, SimpleEmail};
|
|
||||||
use lettre::{EmailAddress, SendableEmail};
|
use lettre::{EmailAddress, SendableEmail};
|
||||||
use time::now;
|
use time::now;
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_simple_email_builder() {
|
|
||||||
let email_builder = SimpleEmail::default();
|
|
||||||
let date_now = now();
|
|
||||||
|
|
||||||
let email = email_builder
|
|
||||||
.to("user@localhost")
|
|
||||||
.from("user@localhost")
|
|
||||||
.cc(("cc@localhost", "Alias"))
|
|
||||||
.reply_to("reply@localhost")
|
|
||||||
.text("Hello World!")
|
|
||||||
.date(date_now.clone())
|
|
||||||
.subject("Hello")
|
|
||||||
.header(("X-test", "value"))
|
|
||||||
.into_email()
|
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
assert_eq!(
|
|
||||||
format!("{}", String::from_utf8_lossy(email.message().as_ref())),
|
|
||||||
format!(
|
|
||||||
"Subject: Hello\r\nContent-Type: text/plain; \
|
|
||||||
charset=utf-8\r\nX-test: value\r\nTo: <user@localhost>\r\nFrom: \
|
|
||||||
<user@localhost>\r\nCc: \"Alias\" <cc@localhost>\r\nReply-To: \
|
|
||||||
<reply@localhost>\r\nDate: {}\r\nMIME-Version: 1.0\r\nMessage-ID: \
|
|
||||||
<{}.lettre@localhost>\r\n\r\nHello World!\r\n",
|
|
||||||
date_now.rfc822z(),
|
|
||||||
email.message_id()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_multiple_from() {
|
fn test_multiple_from() {
|
||||||
let email_builder = EmailBuilder::new();
|
let email_builder = EmailBuilder::new();
|
||||||
@@ -1000,6 +886,7 @@ mod test {
|
|||||||
.to("user@localhost")
|
.to("user@localhost")
|
||||||
.from("user@localhost")
|
.from("user@localhost")
|
||||||
.cc(("cc@localhost", "Alias"))
|
.cc(("cc@localhost", "Alias"))
|
||||||
|
.bcc("bcc@localhost")
|
||||||
.reply_to("reply@localhost")
|
.reply_to("reply@localhost")
|
||||||
.sender("sender@localhost")
|
.sender("sender@localhost")
|
||||||
.body("Hello World!")
|
.body("Hello World!")
|
||||||
@@ -1014,8 +901,9 @@ mod test {
|
|||||||
format!(
|
format!(
|
||||||
"Date: {}\r\nSubject: Hello\r\nX-test: value\r\nSender: \
|
"Date: {}\r\nSubject: Hello\r\nX-test: value\r\nSender: \
|
||||||
<sender@localhost>\r\nTo: <user@localhost>\r\nFrom: \
|
<sender@localhost>\r\nTo: <user@localhost>\r\nFrom: \
|
||||||
<user@localhost>\r\nCc: \"Alias\" <cc@localhost>\r\nReply-To: \
|
<user@localhost>\r\nCc: \"Alias\" <cc@localhost>\r\n\
|
||||||
<reply@localhost>\r\nMIME-Version: 1.0\r\nMessage-ID: \
|
Bcc: <bcc@localhost>\r\nReply-To: <reply@localhost>\r\n\
|
||||||
|
MIME-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()
|
||||||
@@ -1042,14 +930,17 @@ mod test {
|
|||||||
.build()
|
.build()
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
assert_eq!(email.from().to_string(), "sender@localhost".to_string());
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
email.to(),
|
email.envelope().from().unwrap().to_string(),
|
||||||
|
"sender@localhost".to_string()
|
||||||
|
);
|
||||||
|
assert_eq!(
|
||||||
|
email.envelope().to(),
|
||||||
vec![
|
vec![
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
EmailAddress::new("user@localhost".to_string()).unwrap(),
|
||||||
EmailAddress::new("cc@localhost".to_string()),
|
EmailAddress::new("cc@localhost".to_string()).unwrap(),
|
||||||
EmailAddress::new("bcc@localhost".to_string()),
|
EmailAddress::new("bcc@localhost".to_string()).unwrap(),
|
||||||
]
|
].as_slice()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
48
lettre_email/tests/skeptic.rs
Normal file
48
lettre_email/tests/skeptic.rs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
extern crate glob;
|
||||||
|
|
||||||
|
use self::glob::glob;
|
||||||
|
use std::env::consts::EXE_EXTENSION;
|
||||||
|
use std::env;
|
||||||
|
use std::path::Path;
|
||||||
|
use std::process::Command;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn book_test() {
|
||||||
|
let mut book_path = env::current_dir().unwrap();
|
||||||
|
book_path.push(
|
||||||
|
Path::new(file!())
|
||||||
|
.parent()
|
||||||
|
.unwrap()
|
||||||
|
.parent()
|
||||||
|
.unwrap()
|
||||||
|
.parent()
|
||||||
|
.unwrap()
|
||||||
|
.join("../website/content/creating-messages"),
|
||||||
|
); // For some reasons, calling .parent() once more gives us None...
|
||||||
|
|
||||||
|
for md in glob(&format!("{}/*.md", book_path.to_str().unwrap())).unwrap() {
|
||||||
|
skeptic_test(&md.unwrap());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn skeptic_test(path: &Path) {
|
||||||
|
let rustdoc = Path::new("rustdoc").with_extension(EXE_EXTENSION);
|
||||||
|
let exe = env::current_exe().unwrap();
|
||||||
|
let depdir = exe.parent().unwrap();
|
||||||
|
|
||||||
|
let mut cmd = Command::new(rustdoc);
|
||||||
|
cmd.args(&["--verbose", "--test"])
|
||||||
|
.arg("-L")
|
||||||
|
.arg(&depdir)
|
||||||
|
.arg(path);
|
||||||
|
|
||||||
|
let result = cmd.spawn()
|
||||||
|
.expect("Failed to spawn process")
|
||||||
|
.wait()
|
||||||
|
.expect("Failed to run process");
|
||||||
|
|
||||||
|
assert!(
|
||||||
|
result.success(),
|
||||||
|
format!("Failed to run rustdoc tests on {:?}!", path)
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
write_mode = "Overwrite"
|
|
||||||
reorder_imports = true
|
|
||||||
reorder_imported_names = true
|
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
hugo
|
hugo
|
||||||
lunr-hugo -i "content/**/*.md" -o ../docs/json/search.json -l toml
|
lunr-hugo -i "content/**/*.md" -o ../docs/index.json -l toml
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
baseURL = "https://lettre.github.io/lettre/"
|
baseURL = "http://docs.lettre.at/"
|
||||||
languageCode = "en-us"
|
languageCode = "en-us"
|
||||||
title = "Lettre site"
|
title = "Lettre site"
|
||||||
theme = "hugo-theme-learn"
|
theme = "hugo-theme-learn"
|
||||||
|
|||||||
@@ -7,3 +7,5 @@ weight = 2
|
|||||||
+++
|
+++
|
||||||
|
|
||||||
### Creating messages
|
### Creating messages
|
||||||
|
|
||||||
|
This section explains how to create emails.
|
||||||
69
website/content/creating-messages/email.md
Normal file
69
website/content/creating-messages/email.md
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
+++
|
||||||
|
date = "2018-01-21T23:46:17+02:00"
|
||||||
|
title = "Email creation"
|
||||||
|
toc = true
|
||||||
|
weight = 4
|
||||||
|
|
||||||
|
+++
|
||||||
|
|
||||||
|
#### Simple example
|
||||||
|
|
||||||
|
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
|
||||||
|
extern crate lettre_email;
|
||||||
|
|
||||||
|
use lettre_email::EmailBuilder;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
// 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.
|
||||||
|
|
||||||
|
#### Complete example
|
||||||
|
|
||||||
|
Below is a more complete example, not using method chaining:
|
||||||
|
|
||||||
|
```rust
|
||||||
|
extern crate lettre_email;
|
||||||
|
|
||||||
|
use lettre_email::EmailBuilder;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
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.
|
||||||
|
|
||||||
@@ -7,8 +7,8 @@ weight = 1
|
|||||||
+++
|
+++
|
||||||
|
|
||||||
{{% notice note %}}
|
{{% notice note %}}
|
||||||
This documentation is written for lettre 0.7.
|
This documentation is written for lettre 0.8.
|
||||||
Please use https://docs.rs/lettre/0.6.2/lettre/ for lettre 0.6.
|
Please use https://docs.rs/lettre/0.7.0/lettre/ for lettre 0.7.
|
||||||
{{% /notice%}}
|
{{% /notice%}}
|
||||||
|
|
||||||
Lettre is an email library that allows creating and sending messages. It provides:
|
Lettre is an email library that allows creating and sending messages. It provides:
|
||||||
|
|||||||
@@ -11,22 +11,26 @@ The file transport writes the emails to the given directory. The name of the fil
|
|||||||
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.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
|
extern crate lettre;
|
||||||
|
|
||||||
use std::env::temp_dir;
|
use std::env::temp_dir;
|
||||||
|
|
||||||
use lettre::file::FileEmailTransport;
|
use lettre::file::FileEmailTransport;
|
||||||
use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress};
|
use lettre::{SimpleSendableEmail, EmailTransport};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
// Write to the local temp directory
|
// Write to the local temp directory
|
||||||
let mut sender = FileEmailTransport::new(temp_dir());
|
let mut sender = FileEmailTransport::new(temp_dir());
|
||||||
let email = SimpleSendableEmail::new(
|
let email = SimpleSendableEmail::new(
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
"user@localhost".to_string(),
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
&["root@localhost".to_string()],
|
||||||
"message_id".to_string(),
|
"message_id".to_string(),
|
||||||
"Hello world".to_string(),
|
"Hello world".to_string(),
|
||||||
);
|
).unwrap();
|
||||||
|
|
||||||
let result = sender.send(&email);
|
let result = sender.send(&email);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Example result in `/tmp/b7c211bc-9811-45ce-8cd9-68eab575d695.txt`:
|
Example result in `/tmp/b7c211bc-9811-45ce-8cd9-68eab575d695.txt`:
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ emails have to implement `SendableEmail`, which is the case for emails created w
|
|||||||
The following transports are available:
|
The following transports are available:
|
||||||
|
|
||||||
* The `SmtpTransport` uses the SMTP protocol to send the message over the network. It is
|
* The `SmtpTransport` uses the SMTP protocol to send the message over the network. It is
|
||||||
the prefered way of sending emails.
|
the preferred way of sending emails.
|
||||||
* The `SendmailTransport` uses the sendmail command to send messages. It is an alternative to
|
* The `SendmailTransport` uses the sendmail command to send messages. It is an alternative to
|
||||||
the SMTP transport.
|
the SMTP transport.
|
||||||
* The `FileTransport` creates a file containing the email content to be sent. It can be used
|
* The `FileTransport` creates a file containing the email content to be sent. It can be used
|
||||||
|
|||||||
@@ -8,18 +8,22 @@ weight = 3
|
|||||||
|
|
||||||
The sendmail transport sends the email using the local sendmail command.
|
The sendmail transport sends the email using the local sendmail command.
|
||||||
|
|
||||||
``` rust
|
```rust,no_run
|
||||||
use lettre::sendmail::SendmailTransport;
|
extern crate lettre;
|
||||||
use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress};
|
|
||||||
|
|
||||||
|
use lettre::sendmail::SendmailTransport;
|
||||||
|
use lettre::{SimpleSendableEmail, EmailTransport};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
let email = SimpleSendableEmail::new(
|
let email = SimpleSendableEmail::new(
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
"user@localhost".to_string(),
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
&["root@localhost".to_string()],
|
||||||
"message_id".to_string(),
|
"message_id".to_string(),
|
||||||
"Hello world".to_string(),
|
"Hello world".to_string(),
|
||||||
);
|
).unwrap();
|
||||||
|
|
||||||
let mut sender = SendmailTransport::new();
|
let mut sender = SendmailTransport::new();
|
||||||
let result = sender.send(&email);
|
let result = sender.send(&email);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -8,10 +8,10 @@ weight = 2
|
|||||||
|
|
||||||
This transport uses the SMTP protocol to send emails over the network (locally or remotely).
|
This transport uses the SMTP protocol to send emails over the network (locally or remotely).
|
||||||
|
|
||||||
It is desinged to be:
|
It is designed to be:
|
||||||
|
|
||||||
* Secured: email are encrypted by default
|
* Secured: email are encrypted by default
|
||||||
* Modern: Unicode support for email content and sender/recipient adresses when compatible
|
* Modern: Unicode support for email content and sender/recipient addresses when compatible
|
||||||
* Fast: supports tcp connection reuse
|
* Fast: supports tcp connection reuse
|
||||||
|
|
||||||
This client is designed to send emails to a relay server, and should *not* be used to send
|
This client is designed to send emails to a relay server, and should *not* be used to send
|
||||||
@@ -23,15 +23,18 @@ The relay server can be the local email server, a specific host or a third-party
|
|||||||
|
|
||||||
This is the most basic example of usage:
|
This is the most basic example of usage:
|
||||||
|
|
||||||
``` rust
|
```rust,no_run
|
||||||
use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress, SmtpTransport};
|
extern crate lettre;
|
||||||
|
|
||||||
|
use lettre::{SimpleSendableEmail, EmailTransport, SmtpTransport};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
let email = SimpleSendableEmail::new(
|
let email = SimpleSendableEmail::new(
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
"user@localhost".to_string(),
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
&["root@localhost".to_string()],
|
||||||
"message_id".to_string(),
|
"message_id".to_string(),
|
||||||
"Hello world".to_string(),
|
"Hello world".to_string(),
|
||||||
);
|
).unwrap();
|
||||||
|
|
||||||
// Open a local connection on port 25
|
// Open a local connection on port 25
|
||||||
let mut mailer =
|
let mut mailer =
|
||||||
@@ -40,27 +43,29 @@ SmtpTransport::builder_unencrypted_localhost().unwrap().build();
|
|||||||
let result = mailer.send(&email);
|
let result = mailer.send(&email);
|
||||||
|
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Complete example
|
#### Complete example
|
||||||
|
|
||||||
``` rust
|
```rust,no_run
|
||||||
|
extern crate lettre;
|
||||||
|
|
||||||
use lettre::smtp::authentication::{Credentials, Mechanism};
|
use lettre::smtp::authentication::{Credentials, Mechanism};
|
||||||
use lettre::smtp::SUBMISSION_PORT;
|
use lettre::{SimpleSendableEmail, EmailTransport, SmtpTransport};
|
||||||
use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress, SmtpTransport};
|
|
||||||
use lettre::smtp::extension::ClientId;
|
use lettre::smtp::extension::ClientId;
|
||||||
use lettre::smtp::ConnectionReuseParameters;
|
use lettre::smtp::ConnectionReuseParameters;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
let email = SimpleSendableEmail::new(
|
let email = SimpleSendableEmail::new(
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
"user@localhost".to_string(),
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
&["root@localhost".to_string()],
|
||||||
"message_id".to_string(),
|
"message_id".to_string(),
|
||||||
"Hello world".to_string(),
|
"Hello world".to_string(),
|
||||||
);
|
).unwrap();
|
||||||
|
|
||||||
// Connect to a remote server on a custom port
|
// Connect to a remote server on a custom port
|
||||||
let mut mailer = SmtpTransport::simple_builder("server.tld".to_string()).unwrap()
|
let mut mailer = SmtpTransport::simple_builder("server.tld").unwrap()
|
||||||
// Set the name sent during EHLO/HELO, default is `localhost`
|
// Set the name sent during EHLO/HELO, default is `localhost`
|
||||||
.hello_name(ClientId::Domain("my.hostname.tld".to_string()))
|
.hello_name(ClientId::Domain("my.hostname.tld".to_string()))
|
||||||
// Add credentials for authentication
|
// Add credentials for authentication
|
||||||
@@ -81,6 +86,7 @@ assert!(result_2.is_ok());
|
|||||||
|
|
||||||
// Explicitly close the SMTP transaction as we enabled connection reuse
|
// Explicitly close the SMTP transaction as we enabled connection reuse
|
||||||
mailer.close();
|
mailer.close();
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Lower level
|
#### Lower level
|
||||||
@@ -88,7 +94,9 @@ mailer.close();
|
|||||||
You can also send commands, here is a simple email transaction without
|
You can also send commands, here is a simple email transaction without
|
||||||
error handling:
|
error handling:
|
||||||
|
|
||||||
``` rust
|
```rust,no_run
|
||||||
|
extern crate lettre;
|
||||||
|
|
||||||
use lettre::EmailAddress;
|
use lettre::EmailAddress;
|
||||||
use lettre::smtp::SMTP_PORT;
|
use lettre::smtp::SMTP_PORT;
|
||||||
use lettre::smtp::client::Client;
|
use lettre::smtp::client::Client;
|
||||||
@@ -96,17 +104,19 @@ use lettre::smtp::client::net::NetworkStream;
|
|||||||
use lettre::smtp::extension::ClientId;
|
use lettre::smtp::extension::ClientId;
|
||||||
use lettre::smtp::commands::*;
|
use lettre::smtp::commands::*;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
let mut email_client: Client<NetworkStream> = Client::new();
|
let mut email_client: Client<NetworkStream> = Client::new();
|
||||||
let _ = email_client.connect(&("localhost", SMTP_PORT), None);
|
let _ = email_client.connect(&("localhost", SMTP_PORT), None);
|
||||||
let _ = email_client.smtp_command(EhloCommand::new(ClientId::new("my_hostname".to_string())));
|
let _ = email_client.command(EhloCommand::new(ClientId::new("my_hostname".to_string())));
|
||||||
let _ = email_client.smtp_command(
|
let _ = email_client.command(
|
||||||
MailCommand::new(Some(EmailAddress::new("user@example.com".to_string())), vec![])
|
MailCommand::new(Some(EmailAddress::new("user@example.com".to_string()).unwrap()), vec![])
|
||||||
);
|
);
|
||||||
let _ = email_client.smtp_command(
|
let _ = email_client.command(
|
||||||
RcptCommand::new(EmailAddress::new("user@example.org".to_string()), vec![])
|
RcptCommand::new(EmailAddress::new("user@example.org".to_string()).unwrap(), vec![])
|
||||||
);
|
);
|
||||||
let _ = email_client.smtp_command(DataCommand);
|
let _ = email_client.command(DataCommand);
|
||||||
let _ = email_client.message(Box::new("Test email".as_bytes()));
|
let _ = email_client.message(Box::new("Test email".as_bytes()));
|
||||||
let _ = email_client.smtp_command(QuitCommand);
|
let _ = email_client.command(QuitCommand);
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -10,19 +10,23 @@ The stub transport only logs message envelope and drops the content. It can be u
|
|||||||
testing purposes.
|
testing purposes.
|
||||||
|
|
||||||
```rust
|
```rust
|
||||||
use lettre::stub::StubEmailTransport;
|
extern crate lettre;
|
||||||
use lettre::{SimpleSendableEmail, EmailTransport, EmailAddress};
|
|
||||||
|
|
||||||
|
use lettre::stub::StubEmailTransport;
|
||||||
|
use lettre::{SimpleSendableEmail, EmailTransport};
|
||||||
|
|
||||||
|
fn main() {
|
||||||
let email = SimpleSendableEmail::new(
|
let email = SimpleSendableEmail::new(
|
||||||
EmailAddress::new("user@localhost".to_string()),
|
"user@localhost".to_string(),
|
||||||
vec![EmailAddress::new("root@localhost".to_string())],
|
&["root@localhost".to_string()],
|
||||||
"message_id".to_string(),
|
"message_id".to_string(),
|
||||||
"Hello world".to_string(),
|
"Hello world".to_string(),
|
||||||
);
|
).unwrap();
|
||||||
|
|
||||||
let mut sender = StubEmailTransport::new_positive();
|
let mut sender = StubEmailTransport::new_positive();
|
||||||
let result = sender.send(&email);
|
let result = sender.send(&email);
|
||||||
assert!(result.is_ok());
|
assert!(result.is_ok());
|
||||||
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
Will log (when using a logger like `env_logger`):
|
Will log (when using a logger like `env_logger`):
|
||||||
|
|||||||
1
website/themes/hugo-theme-learn/.gitignore
vendored
1
website/themes/hugo-theme-learn/.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
.DS_Store
|
.DS_Store
|
||||||
public/
|
public/
|
||||||
|
exampleSite/public
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user