lettre / lettre Goto Github PK
View Code? Open in Web Editor NEWa mailer library for Rust
Home Page: https://lettre.rs
License: MIT License
a mailer library for Rust
Home Page: https://lettre.rs
License: MIT License
I have some code that sometimes I have an email address along with the real name: "Bill Gates" with "[email protected]". And sometimes I have just the email address.
I need to construct a list of addresses to send an email to, since the types for my data are heterogeneous, I need to merge them into a list of addresses in a homogeneous type, and the natural type is lettre's Mailbox
type. I can't do this because Mailbox is never exported.
Add SSL/TLS support to the client.
Is that something you'd be interested in this repository?
Rust-smtp fails to compile on the fresh Rust nightly.
I did a quick upgrade: https://github.com/ArtemGr/rust-smtp/commit/f7e205e637eb31bc295849b561153abda9e5b247
Not creating a pull request because you might want to fix things differently.
Support AUTH extension.
Add multipart support to Email
.
Thanks a lot @amousset for providing this library!
I think the most common use case of this library is to simply send an email. In my opinion this API to achieve that should be simplified. In detail I'd imagine providing a (perhaps additional) API which uses TcpStream
stream by default and a simpler client API like the following:
Client::new("localhost:1025");
Please let me know what you think about these changes.
office365.com (among others) supports neither AUTH PLAIN nor AUTH CRAMMD5. They only support the (older but more popular?) AUTH LOGIN.
I think it should be pretty simple to support.
Hello,
I am compiling my project with docker FROM scorpil/rust:1.12-onbuild
But when I add letter
in the dependencies I get the following error :
error: linking with `cc` failed: exit code: 1
|
= note: "cc" "-Wl,--as-needed" "-Wl,-z,noexecstack" "-m64" "-L" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib" "/rust/app/target/release/lettret.0.o" "-o" "/rust/app/target/release/lettret" "-Wl,--gc-sections" "-pie" "-Wl,-O1" "-nodefaultlibs" "-L" "/rust/app/target/release/deps" "-L" "/rust/app/target/release/build/rust-crypto-ed6f35bcd4283630/out" "-L" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib" "-Wl,-Bstatic" "-Wl,-Bdynamic" "/rust/app/target/release/deps/libenv_logger-c716af707f2027e1.rlib" "/rust/app/target/release/deps/libregex-a99351f81f55a22d.rlib" "/rust/app/target/release/deps/libthread_local-a3c0092e9fb6507d.rlib" "/rust/app/target/release/deps/libthread_id-bcd46c79a620a618.rlib" "/rust/app/target/release/deps/libaho_corasick-d1dfd931d7cac82f.rlib" "/rust/app/target/release/deps/libregex_syntax-f9926a4b1f08df13.rlib" "/rust/app/target/release/deps/liblettre-5fc3dbb1af4066d5.rlib" "/rust/app/target/release/deps/libopenssl-569a830afc4ba42a.rlib" "/rust/app/target/release/deps/liblazy_static-359f5533c970cd71.rlib" "/rust/app/target/release/deps/libbitflags-0e272044714c8076.rlib" "/rust/app/target/release/deps/libuuid-41f66b8ddc6c6059.rlib" "/rust/app/target/release/deps/libmime-3c32775eb368d3f0.rlib" "/rust/app/target/release/deps/liblog-bf16bb9a4912b11d.rlib" "/rust/app/target/release/deps/libmemchr-c555f740a543880f.rlib" "/rust/app/target/release/deps/libcrypto-ccca7bf8b1baef5f.rlib" "/rust/app/target/release/deps/libutf8_ranges-5c6a6dacba3be7ce.rlib" "/rust/app/target/release/deps/libbufstream-78c23396232c62da.rlib" "/rust/app/target/release/deps/libemail-e9674eb0c3ecbee7.rlib" "/rust/app/target/release/deps/librand-49a08859d086fffe.rlib" "/rust/app/target/release/deps/libchrono-7342810e34d1c30d.rlib" "/rust/app/target/release/deps/libnum-1fa4854b44bb6a54.rlib" "/rust/app/target/release/deps/libnum_iter-50df698bc905252c.rlib" "/rust/app/target/release/deps/libnum_integer-52fdddf28cd8e924.rlib" "/rust/app/target/release/deps/libnum_traits-92bb90166cd1857c.rlib" "/rust/app/target/release/deps/libtime-750bfdd52feafcb7.rlib" "/rust/app/target/release/deps/libencoding-804c203c6e9b8b1a.rlib" "/rust/app/target/release/deps/libencoding_index_tradchinese-e8f10363b7df0da9.rlib" "/rust/app/target/release/deps/libencoding_index_simpchinese-39a3c36ebacf921b.rlib" "/rust/app/target/release/deps/libencoding_index_japanese-a7b78b0f5f4679cd.rlib" "/rust/app/target/release/deps/libencoding_index_korean-830683894d2ddf26.rlib" "/rust/app/target/release/deps/libencoding_index_singlebyte-12a9a0167990b7ae.rlib" "/rust/app/target/release/deps/librustc_serialize-3561541d79c18212.rlib" "/rust/app/target/release/deps/liblazy_static-3a04918be71c80ee.rlib" "/rust/app/target/release/deps/libopenssl_sys-a4f86492ba1e2f09.rlib" "/rust/app/target/release/deps/liblibc-ad32fde1bd850538.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libstd-c6a52fb7.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libpanic_unwind-c6a52fb7.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libunwind-c6a52fb7.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/librand-c6a52fb7.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcollections-c6a52fb7.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc-c6a52fb7.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liballoc_jemalloc-c6a52fb7.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/liblibc-c6a52fb7.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/librustc_unicode-c6a52fb7.rlib" "/usr/local/lib/rustlib/x86_64-unknown-linux-gnu/lib/libcore-c6a52fb7.rlib" "-l" "ssl" "-l" "crypto" "-l" "util" "-l" "dl" "-l" "pthread" "-l" "gcc_s" "-l" "pthread" "-l" "c" "-l" "m" "-l" "rt" "-l" "util" "-l" "compiler-rt"
= note: /usr/bin/ld: cannot find -lssl
/usr/bin/ld: cannot find -lcrypto
collect2: error: ld returned 1 exit status
error: aborting due to previous error
error: Could not compile `lettret`.
To learn more, run the command again with --verbose.
The command '/bin/sh -c cargo build --release' returned a non-zero code: 101
The library uses misspelled "Mecanism" in some places.
Please please keep the RFC SMTP methods available!
( Here's what I'm talking about: https://github.com/ArtemGr/rust-smtp/commit/b412ef4375cb376d8d9eb9a12023d0f6290e8591 ).
There is a lot of very important things one can do with SMTP which one can't do with the high-level interface. (For example, I'm using it to get the message ID from the underlying SMTP server, which then can be used to track the message in the logs and to check the message delivery in unit tests. I'm also using it to properly check the email address before commiting to send the message).
Currently, the SmtpTransportBuilder has a field called authentication_mechanisms that allows for an Vec of mechanisms.
This caught my eye because it seemed like an unnecessary wasteful Vec allocation, but then I notice that you allow for multiple assignments to check them in priority order as seen here.
I cannot think of a scenario in which I would be targeting an email relay without being sure of how to authenticate. For example, if the relay server expects CramMd5 and that fails, it seems weird that I would also want to check for Plain, just in case it would magically go through. But that is what is allowed if I specify multiple mechanisms in the Vec. If Plain went through, even though the server was expecting CramMd5, it would actually be dangerous, because it would hide the authentication problem from me, since the emails would be sent successfully during the Plain fallback.
Hello,
For how long letter will keep connection open if connection_reuse
is true
? Will it reconnect if remote server will drop the connection?
Remove the rust-email dependency in lettre, and use https://github.com/mikedilger/email-format instead.
Consider improving integration with https://github.com/mikedilger/mailstrom which looks very promising, and maybe completely remove the email part when it's ready.
I wanted to write a small example that sends a mail through smtp.fastmail.com:465
with STARTTLS
but the call to send
always panics.
// ...
let email = EmailBuilder::new()
.to(get!(section, "sender"))
.from(get!(section, "receiver"))
.subject("Hello from lettre!")
.body("Hi,
this mail was send via github.com/lettre/lettre.
Best,
Andreas")
.build()
.expect("could not build message");
let host_url = Url::parse(get!(section, "host")).expect("bad host format");
let (host, port) = (host_url.host_str().unwrap(), host_url.port().unwrap());
let mut mailer = smtp::SmtpTransportBuilder::new((host, port))
.expect("bad host")
.credentials(get!(section, "username"), get!(section, "password"))
.security_level(smtp::SecurityLevel::AlwaysEncrypt)
.smtp_utf8(true)
.build();
mailer.send(email).expect("sending mail failed");
// ...
This is the traceback (I used Rust 1.11 stable):
$ cargo run --example smtp
Running `target/debug/examples/smtp`
thread 'main' panicked at 'sending mail failed: ResponseParsingError("Wrong code length (should be 3 digit)")', ../src/libcore/result.rs:788
stack backtrace:
1: 0x557fee5ad04f - std::sys::backtrace::tracing::imp::write::h46e546df6e4e4fe6
2: 0x557fee5b034b - std::panicking::default_hook::_$u7b$$u7b$closure$u7d$$u7d$::h077deeda8b799591
3: 0x557fee5affcf - std::panicking::default_hook::heb8b6fd640571a4f
4: 0x557fee5a68ce - std::panicking::rust_panic_with_hook::hd7b83626099d3416
5: 0x557fee5b0591 - std::panicking::begin_panic::h941ea76fc945d925
6: 0x557fee5a725a - std::panicking::begin_panic_fmt::h30280d4dd3f149f5
7: 0x557fee5b052e - rust_begin_unwind
8: 0x557fee5e5d0f - core::panicking::panic_fmt::h2d3cc8234dde51b4
9: 0x557fee4bfd34 - core::result::unwrap_failed::hbd4ff128f4415426
at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libcore/macros.rs:29
10: 0x557fee4c165d - _<core..result..Result<T, E>>::expect::hd77a54b9d211770f
at /buildslave/rust-buildbot/slave/stable-dist-rustc-linux/build/obj/../src/libcore/result.rs:750
11: 0x557fee4b30a8 - smtp::main::hc2479c24f2b349b4
at /home/andreas/personal/dev/rust/weblab/examples/smtp.rs:50
12: 0x557fee5afc08 - std::panicking::try::call::hca715a47aa047c49
13: 0x557fee5b7bab - __rust_try
14: 0x557fee5b7b4e - __rust_maybe_catch_panic
15: 0x557fee5af6ae - std::rt::lang_start::h162055cb2e4b9fe7
16: 0x557fee4d4599 - main
17: 0x7efded264290 - __libc_start_main
18: 0x557fee4b2609 - _start
19: 0x0 - <unknown>
error: Process didn't exit successfully: `target/debug/examples/smtp` (exit code: 101)
shell returned 101
How to add attachments in lettre?
Check the string encodings:
If I want to use the newest OpenSSL, I have to depend on the master branch. Are you planning on doing a release soon?
I'm trying to use this crate in a project I'm working on, and I can't get the examples to compile. They cause panics.
My code (the example code):
use lettre::transport::smtp::{SmtpTransport, SmtpTransportBuilder};
use lettre::email::EmailBuilder;
use lettre::transport::EmailTransport;
let email = EmailBuilder::new()
.to("root@localhost")
.from("user@localhost")
.body("Hello World!")
.subject("Hello")
.build()
.unwrap();
// Open a local connection on port 25
let mut mailer =
SmtpTransportBuilder::localhost().unwrap().build();
// Send the email
let result = mailer.send(email);
assert!(result.is_ok());
The error:
thread '<main>' panicked at 'assertion failed: result.is_ok()', main.rs:26
note: Run with `RUST_BACKTRACE=1` for a backtrace.
Process didn't exit successfully: `/path/to/code` (exit code: 101)
A complete example with a real usecase would be useful.
Split long lines in the headers and the message.
There should be a way to show a email to the EmailBuilder
s.t. it sets the In-Reply-To
and Reference
headers accordingly.
This will improve portability on Windows and OS X
It's natural to do writeln!(stderr(), "{}", e)
on a lettre error. Unfortunately, the description()
(and thus the actual error) that is outputted is highly inadequate for identifying the cause. It's also a lot of work to write a match
block against every kind of lettre Error
, when simply a textual printout of it is what's needed.
It would be very helpful if a complete Display
were implemented for lettre's Error
type or if Error::description()
outputted the Error
's content.
I wonder if it's worth it to create a streaming interface, streaming DATA directly to SMTP server, but with the proper escaping in place and done by the library.
Would you consider making such an enhancement?
Currently, lettre's Cargo.toml specifies using Rust-OpenSSL version 0.7.x
. At the time of this writing, the latest release is version 0.8.2
, which includes a number of bug fixes that, in some applications has resolved some functional failings.
I'd like to ask for lettre to adopt these changes and upgrade to the latest version.
This may be a problem more with the 'time' crate, but the Tm::rfc822()
, at least for me, doesn't include a timezone at the end, resulting in incorrect times displayed.
I have found it to work correctly if I replace the rfc822()
in the code with rfc822z()
.
I'd like to ask that lettre update to the 0.9.4 release of Rust-OpenSSL. While it includes some bigger changes, this seems to be a version that developers may stick with for a while.
Add support for one (or several) transports based on a Web API. See https://github.com/gsquire/sendgrid-rs/ for example.
I am brand new to rust, but FYI, I get this error when installing.
Sorry if I am doing something wrong myself!
Compiling smtp v0.3.0
/root/.cargo/registry/src/github.com-88ac128001ac3a9a/smtp-0.3.0/src/client/net.rs:14:5: 14:89 error: the trait bound `Self: std::marker::Sized` is not satisfied [E0277]
/root/.cargo/registry/src/github.com-88ac128001ac3a9a/smtp-0.3.0/src/client/net.rs:14 fn connect(addr: &SocketAddr, ssl_context: Option<&SslContext>) -> io::Result<Self>;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/root/.cargo/registry/src/github.com-88ac128001ac3a9a/smtp-0.3.0/src/client/net.rs:14:5: 14:89 help: run `rustc --explain E0277` to see a detailed explanation
/root/.cargo/registry/src/github.com-88ac128001ac3a9a/smtp-0.3.0/src/client/net.rs:14:5: 14:89 help: consider adding a `where Self: std::marker::Sized` bound
/root/.cargo/registry/src/github.com-88ac128001ac3a9a/smtp-0.3.0/src/client/net.rs:14:5: 14:89 note: required by `std::result::Result`
error: aborting due to previous error
error: failed to compile `receive_email v0.1.0 (file:///root/go/src/receive_email)`, intermediate artifacts can be found at `/root/go/src/receive_email/target`
Caused by:
Could not compile `smtp`.
To learn more, run the command again with --verbose.
I am using rust 1.9.0
Openssl is currently a dependency, it could be an optional feature at compilation.
Some design decisions have to be made.
There is the case where the user adds multiple "from" to an email, but doesn't add a sender. In the case of multiple "from" headers, the RFC dictates that there must be a "sender" header. We can
There is the case where the user does not add a "from" header, but manually takes care for the envelope from. The RFC dictates, that there must be exactly one from header and it can't be empty. We can
Currently, in the former case, we do the former and in the latter case the latter. But I think none of the solutions can always fit. Maybe we should add a flag to disable enforcement of the RFC compliance.
In compliant mode, the choices could then be: second, first
In non-compliant mode: third, second
What do you think?
From https://tools.ietf.org/html/rfc5322
"To:" address-list CRLF
The document also states, that there is to be at most one To
header.
The EmailBuilder
currently just puts multiple To
headers if add_to
is called multiple times. Instead it should keep track of the headers and merge them into a mailbox-list to create one To
header. This also applies to these headers: Reply-To, From (yes, multiple authors are defined in the standard), Cc and more.
Furthermore in case of a list of authors in From
, the Sender
header becomes obligatory. So if it is not set by the user, there must be either an error or a safe default (e.g. pick the first or last mailbox passed to add_from
).
Regarding client support (I only tested Thunderbird): Thunderbird parses multiple To
headers gracefully, but fails at multiple From
headers (it picks the first).
Would you be willing to accept a PR splitting the transports to a separate crate (which the lettre
crate then would depend upon), e.g. lettre-transports
?
lettre
currently is the only crate (I know of) with email transport functionality. But you don't need an EmailBuilder when you just want to send an Email.lettre::EmailBuilder
, but still send them at some point.lettre
seems pretty stable already. Maybe the transports part of lettre
can become stable (1.0) more quickly. Keep in mind that adding new transports would not break backward compatibility.I was trying to create a system where an email ready for being sent was sent to a mailer thread, but it seems that Email
doesn't implement Send
because it contains the field MimeMessage
which contains std::rc::Rc<email::header::Header>
.
Is there any work around this? Except for building emails in one thread only. (I need then re-implement a struct that contains all the information for building the email, which seems like re-inventing the wheel.)
Check the RFC compliance of the input data, for example :
We need to set the timeouts and expose this to the user.
Based on https://github.com/gsquire/sendgrid-rs/.
Maybe with docker.
Give access to verify modes and cert/key configuration through the sender.
Currently the EmailBuilder
's build
function creates the envelope from the To
and From
headers. I propose the EmailBuilder
should allow for this to be customised, e.g. like this:
impl EmailBuilder {
fn set_envelope(&mut self, e: Envelope) {…}
fn envelope(mut self, e: Envelope) -> Self {…}
}
If no envelope is set, the current behaviour should stay the default. Of course for this to work, There needs to be a useful constructor or builder for Envelope
.
Make rust-smtp easily usable with rust-email and remove the mailer from rust-smtp.
It's common on Linux servers to have local MTA configured, and sendmail binary present to be used for mail delivery. It would be nice to have a transport to send mails via sendmail executable. Thank you!
Building off of master works. Please consider releasing a new version to crates.
$ rustc --version
rustc 1.8.0-nightly (4b615854f 2016-01-26)
The error was this:
Compiling lettre v0.5.0
/home/zmbush/.cargo/registry/src/github.com-88ac128001ac3a9a/lettre-0.5.0/src/transport/smtp/client/net.rs:15:5: 15:89 error: the trait `core::marker::Sized` is not implemented for the type `Self` [E0277]
/home/zmbush/.cargo/registry/src/github.com-88ac128001ac3a9a/lettre-0.5.0/src/transport/smtp/client/net.rs:15 fn connect(addr: &SocketAddr, ssl_context: Option<&SslContext>) -> io::Result<Self>;
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/zmbush/.cargo/registry/src/github.com-88ac128001ac3a9a/lettre-0.5.0/src/transport/smtp/client/net.rs:15:5: 15:89 help: run `rustc --explain E0277` to see a detailed explanation
/home/zmbush/.cargo/registry/src/github.com-88ac128001ac3a9a/lettre-0.5.0/src/transport/smtp/client/net.rs:15:5: 15:89 note: `Self` does not have a constant size known at compile-time
/home/zmbush/.cargo/registry/src/github.com-88ac128001ac3a9a/lettre-0.5.0/src/transport/smtp/client/net.rs:15:5: 15:89 note: required by `core::result::Result`
error: aborting due to previous error
Could not compile `lettre`.
When I use this function to send emails with lettre 0.5.1, 'ß' appears as 'ß'.
How can I send the email as UTF-8?
fn send_email(to_addr: &str, subject: &str, body: &str) -> Result<(), &'static str> {
let send_email = EmailBuilder::new()
.to(to_addr)
.from(CFG.mail_sender_address.as_str())
.body(body)
.subject(subject)
.build().unwrap();
let mut mailer = SmtpTransportBuilder::new(
(CFG.mail_smtp_host.as_str(), SUBMISSION_PORT)).unwrap()
.hello_name(&CFG.mail_domain)
.credentials(&CFG.mail_name, &CFG.mail_password)
.security_level(SecurityLevel::AlwaysEncrypt)
.smtp_utf8(true)
.authentication_mechanisms(vec![Mechanism::Plain])
.build();
if let Err(e) = mailer.send(send_email) {
warn!("error sending mail: {}", e.to_string());
Err("mail sending failed")
} else {
Ok(())
}
}
(I can't use a newer version of lettre because of openssl linking conflicts on Windows because request/hyper need to link to a different version...)
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.