E-mail delivery library for Rust with DKIM support

Overview

mail-send

crates.io build docs.rs crates.io

mail-send is a Rust library to build, sign and send e-mail messages via SMTP. It includes the following features:

  • Generates e-mail messages conforming to the Internet Message Format standard (RFC 5322).
  • Full MIME support (RFC 2045 - 2049) with automatic selection of the most optimal encoding for each message body part.
  • DomainKeys Identified Mail (DKIM) Signatures (RFC 6376) with ED25519-SHA256, RSA-SHA256 and RSA-SHA1 support.
  • Simple Mail Transfer Protocol (SMTP; RFC 5321) delivery.
  • SMTP Service Extension for Secure SMTP over TLS (RFC 3207).
  • SMTP Service Extension for Authentication (RFC 4954) with automatic mechanism negotiation (from most secure to least secure):
    • CRAM-MD5 (RFC 2195)
    • DIGEST-MD5 (RFC 2831; obsolete but still supported)
    • XOAUTH2 (Google proprietary)
    • LOGIN
    • PLAIN
  • Full async (requires Tokio).

Usage Example

Send a message via an SMTP server that requires authentication:

    // Build a simple multipart message
    let message = MessageBuilder::new()
        .from(("John Doe", "[email protected]"))
        .to(vec![
            ("Jane Doe", "[email protected]"),
            ("James Smith", "[email protected]"),
        ])
        .subject("Hi!")
        .html_body("<h1>Hello, world!</h1>")
        .text_body("Hello world!");

    // Connect to the SMTP submissions port, upgrade to TLS and
    // authenticate using the provided credentials.
    SmtpClientBuilder::new("smtp.gmail.com", 587)
        .implicit_tls(false)
        .credentials(("john", "p4ssw0rd"))
        .connect()
        .await
        .unwrap()
        .send(message)
        .await
        .unwrap();

Sign a message with DKIM and send it via an SMTP relay server:

    // Build a simple text message with a single attachment
    let message = MessageBuilder::new()
        .from(("John Doe", "[email protected]"))
        .to("[email protected]")
        .subject("Howdy!")
        .text_body("These pretzels are making me thirsty.")
        .attachment("image/png", "pretzels.png", [1, 2, 3, 4].as_ref());

    // Sign an e-mail message using RSA-SHA256
    let pk_rsa = RsaKey::<Sha256>::from_rsa_pem(TEST_KEY).unwrap();
    let signer = DkimSigner::from_key(pk_rsa)
        .domain("example.com")
        .selector("default")
        .headers(["From", "To", "Subject"])
        .expiration(60 * 60 * 7); // Number of seconds before this signature expires (optional)

    // Connect to an SMTP relay server over TLS.
    // Signs each message with the configured DKIM signer.
    SmtpClientBuilder::new("smtp.gmail.com", 465)
        .connect()
        .await
        .unwrap()
        .send_signed(message, &signer)
        .await
        .unwrap();

More examples of how to build messages are available in the mail-builder crate. Please note that this library does not support parsing e-mail messages as this functionality is provided separately by the mail-parser crate.

Testing

To run the testsuite:

 $ cargo test --all-features

or, to run the testsuite with MIRI:

 $ cargo +nightly miri test --all-features

License

Licensed under either of

at your option.

Copyright (C) 2020-2022, Stalwart Labs Ltd.

Comments
  • Send gets stuck when the message has a binary attachment

    Send gets stuck when the message has a binary attachment

    Adding a binary attachment makes the sent command get stuck and never finish until the server ends the connection. Sending a text attachment works fine. The binary attachment is only 98Kb.

    opened by arturoc 10
  • thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: MissingStartTls

    thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: MissingStartTls

    version: mail-send = "0.3.0"

    when not connect to stmp with tls: match SmtpClientBuilder::new(email_host,25) .implicit_tls(false) .credentials((email_username, email_password)) .timeout(Duration::from_secs(3)) .connect() .await .unwrap() .send(message) .await { Ok(_) => println!("Email sent successfully!"), Err(e) => panic!("Could not send email: {:?}", e), }

    thread 'main' panicked at 'called Result::unwrap() on an Err value: MissingStartTls',

    opened by awol2005ex 7
  • `UnparseableReply`: Bug in `impl<T: AsyncRead + AsyncWrite + Unpin> SmtpClient<T>`. (Fixed by #13)

    `UnparseableReply`: Bug in `impl SmtpClient`. (Fixed by #13)

    Hi!

    I am experiencing some weird SMTP failures.

    I have a mailhog (https://github.com/mailhog/MailHog / https://registry.hub.docker.com/r/mailhog/mailhog/) set up behind a traefik (https://registry.hub.docker.com/_/traefik) reverse proxy. The entire thing is happening within a docker environment on my local machine - no remote network failures.

    The setup is simple: MailHog just exposes port 1025 for plain SMTP; Traefik does the TLS and exposes port 587. (TLS is self-signed; using allow_invalid_certs().)

    The Traefik config for the TLS & TCP setup is basically the same as the one shown here: https://docker-mailserver.github.io/docker-mailserver/edge/examples/tutorials/mailserver-behind-proxy/#configuration-of-the-used-proxy-software

    Most of the time, I can send mail just fine. However, every now and then I receive an UnparseableReply error.

    I can reproduce it by just running the test again and again. It does not matter if I run it in quick succession or wait for a second or more before retrying.

    In these cases, mailhog logs:

    Starting session
    [PROTO: INVALID] Started session, switching to ESTABLISH state
    Sent 45 bytes: '220 mail.some-host.berlin ESMTP MailHog\r\n'
    Received 15 bytes: 'EHLO felicity\r\n'
    [PROTO: ESTABLISH] Processing line: EHLO felicity
    [PROTO: ESTABLISH] In state 1, got command 'EHLO', args 'felicity'
    [PROTO: ESTABLISH] In ESTABLISH state
    [PROTO: ESTABLISH] Got EHLO command, switching to MAIL state
    Sent 20 bytes: '250-Hello felicity\r\n'
    Sent 16 bytes: '250-PIPELINING\r\n'
    Sent 16 bytes: '250 AUTH PLAIN\r\n'
    Connection closed by remote host
    Session ended
    

    Note: Connection closed by remote host (by mail-send.)

    The SmtpClientBuilder's timeout is set to 30 seconds. The test sending, however, fails immediately.

    Note that this test is done without Credentials.

    Where Connection closed by remote host occurs, commonly MailHog should receive the first header: Received 30 bytes: 'MAIL FROM:<[email protected]>\r\n'. See below for a full (elided message body) example of a successful send.

    And my test shows:

    running 2 tests
    test tests::renders_full_newsletter ... ok
    test mail::tests::mailer_sends_smtp_tls_mail ... FAILED
    
    failures:
    
    ---- mail::tests::mailer_sends_smtp_tls_mail stdout ----
    Error: SendMail(UnparseableReply)
    
    
    failures:
        mail::tests::mailer_sends_smtp_tls_mail
    
    test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 0 filtered out; finished in 0.01s
    
    error: test failed, to rerun pass `--lib`
    
    

    SendMail is my own error enum variant. UnparseableReply is mail_send::Error.

    Traefik writes nothing special to the log (log level Debug):

    Handling connection from 172.254.1.1:48226
    

    In contrast, here's the MailHog logs from a good mail send:

    Starting session
    [PROTO: INVALID] Started session, switching to ESTABLISH state
    Sent 45 bytes: '220 mail.some-host.berlin ESMTP MailHog\r\n'
    Received 15 bytes: 'EHLO felicity\r\n'
    [PROTO: ESTABLISH] Processing line: EHLO felicity
    [PROTO: ESTABLISH] In state 1, got command 'EHLO', args 'felicity'
    [PROTO: ESTABLISH] In ESTABLISH state
    [PROTO: ESTABLISH] Got EHLO command, switching to MAIL state
    Sent 20 bytes: '250-Hello felicity\r\n'
    Sent 16 bytes: '250-PIPELINING\r\n'
    Sent 16 bytes: '250 AUTH PLAIN\r\n'
    Received 30 bytes: 'MAIL FROM:<[email protected]>\r\n'
    [PROTO: MAIL] Processing line: MAIL FROM:<[email protected]>
    [PROTO: MAIL] In state 6, got command 'MAIL', args 'FROM:<[email protected]>'
    [PROTO: MAIL] In MAIL state
    [PROTO: MAIL] Got MAIL command, switching to RCPT state
    Sent 32 bytes: '250 Sender [email protected] ok\r\n'
    Received 26 bytes: 'RCPT TO:<[email protected]>\r\n'
    [PROTO: RCPT] Processing line: RCPT TO:<[email protected]>
    [PROTO: RCPT] In state 7, got command 'RCPT', args 'TO:<[email protected]>'
    [PROTO: RCPT] In RCPT state
    [PROTO: RCPT] Got RCPT command
    Sent 33 bytes: '250 Recipient [email protected] ok\r\n'
    Received 6 bytes: 'DATA\r\n'
    [PROTO: RCPT] Processing line: DATA
    [PROTO: RCPT] In state 7, got command 'DATA', args ''
    [PROTO: RCPT] In RCPT state
    [PROTO: RCPT] Got DATA command, switching to DATA state
    Sent 37 bytes: '354 End data with <CR><LF>.<CR><LF>\r\n'
    Received 1024 bytes: 'From: <[email protected]>\r\nTo: <[email protected]>\r\nSubject: Test mail\r\nReply-To: <[email protected]>\r\nMessage-ID: <174421ede9d619d9.fbb0693af3efc5c7.146ed3f42bb856b@felicity>\r\nDate: Wed, 15 Feb 2023 23:04:27 +0000\r\nContent-Type: text/html; charset="utf-8"\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\n<!doctype html><html xmlns=3D"http://www.w3.org/1999/xhtml" xmlns:v=3D"urn:s=\r\nchemas-microsoft-com:vml" xmlns:o=3D"urn:schemas-microsoft-com:office:office=\r\n"> [... AND SO ON, receiving the entire mail in chunks of up to 1024 B]'
    [PROTO: DATA] Got EOF, storing message and switching to MAIL state
    Parsing Content from string: 'From: <[email protected]>
    To: <[email protected]>
    Subject: Test mail
    Reply-To: <[email protected]>
    Message-ID: <174421ede9d619d9.fbb0693af3efc5c7.146ed3f42bb856b@felicity>
    Date: Wed, 15 Feb 2023 23:04:27 +0000
    Content-Type: text/html; charset="utf-8"
    Content-Transfer-Encoding: quoted-printable
    
    <!doctype html><html xmlns=3D"http://www.w3.org/1999/xhtml" xmlns:v=3D"urn:s=
    chemas-microsoft-com:vml" xmlns:o=3D"urn:schemas-microsoft-com:office:office=
    ">[AND SO ON... rest of the mail - not relevant to the bug report]'
    Storing message ZjsPQpZCLXvLR44_7SWRBJpCTy9AfPV4JL_CvweyeoU=@mail.some-host.berlin
    Sent 90 bytes: '250 Ok: queued as ZjsPQpZCLXvLR44_7SWRBJpCTy9AfPV4JL_CvweyeoU=@mail.some-host.berlin\r\n'
    Got message in APIv2 websocket channel
    [APIv2] BROADCAST /api/v2/websocket
    Got message in APIv1 event stream
    Connection closed by remote host
    Session ended
    

    PS: "Jim, the Chaos Monkey" (a MailHog feature intended to test application resilience in the face of failure) is disabled.

    opened by LeoniePhiline 5
  • Add an `impl std::error::Error` for `mail_send::Error`

    Add an `impl std::error::Error` for `mail_send::Error`

    Hello!

    I've been using thiserror and stumbled upon this when trying to integrate mail_send:

    mail_send::Error (and also mail_auth::Error) do not implement the std::error::Error trait. That's why they cannot be simply integrated into other error-frameworks which all build on the std lib's Error trait.

    mail_send and mail_auth could also opt into using the thiserror crate. thiserror::Error is entirely transparent to the library user, and takes some boilerplate away from you.

    Here's how this could look like: https://github.com/jolimail/mrml-core/pull/38/files#diff-c08afca406e15cd665ef6c443014a8472bb79435231a21463239333886aed304

    A pure std::error::Error implementation, without #[derive(thiserror::Error)] might look like this: https://docs.rs/askama_shared/0.12.2/src/askama_shared/error.rs.html#43-54

    opened by LeoniePhiline 4
  • Integration with mail-parser

    Integration with mail-parser

    Hi, it's me again

    What I'm trying to build requires to store mails on disk, before reading them back and sending them.

    Storing them on disk using mail-parser is easy thanks to serde. An alternative could be to store them raw which is trivial too.

    However, sending them through mail-send seems to be a bit of a pain point. Indeed, the IntoMessage trait that Transport.send expects is implemented for mail-parser's Message and mail-builder MessageBuilder.

    However, neither mail-parser::Message nor mail-builder::MessageBuilder support building the structure from the raw text or through Deserialize.

    I guess implementing IntoMessage for mail-parser::Message could work, but it feels like both mail-parser::Message and mail-send::smtp::message::Message could be the same structure, that would implement Serialize/Deserialize?

    Thanks!

    opened by mripard 3
  • Sample Usage using XOAuth2 for SMTP Sending of Email

    Sample Usage using XOAuth2 for SMTP Sending of Email

    Hello

    Do you have a sample in your code that will successfully email using SMPT XOAUTH2?

    Url and scopes used to get token.

        AuthUrl::new("https://accounts.google.com/o/oauth2/v2/auth".to_string())?,
        TokenUrl::new("https://oauth2.googleapis.com/token".to_string())?,
    
        Scope::new("https://www.googleapis.com/auth/gmail.send".to_string()),
        Scope::new("email".to_string()),
        Scope::new("profile".to_string()),
    

    This is the sample code I created

    let auth_code_grant = AuthCodeGrant::new(
        ClientId::new(client_id.to_string()),
        client_secret,
    let message = MessageBuilder::new()
        .from((sender_name.as_ref(), sender_email.as_ref()))
        .to(vec![(receiver_name.as_ref(), receiver_email.as_ref())])
        .subject("Microsoft - Test XOAUTH2 SMTP!")
        .html_body("<h1>Hello, world!</h1>")
        .text_body("Hello world!");
    
    let credentials =
        Credentials::new_xoauth2(sender_email.as_ref(), access_token.secret().as_str());
    log::info!("Authenticating SMTP XOAUTH2 Credentials....");
    let email_connect = SmtpClientBuilder::new("smtp.gmail.com", 587)
        .implicit_tls(false)
        .credentials(credentials)
        .connect()
        .await;
    
    match email_connect {
        Ok(mut result) => {
            log::info!("Sending SMTP XOAUTH2 Email....");
            let send = result.send(message).await;
            match send {
                Ok(_result) => {}
                Err(err) => {
                    log::error!("SMTP Sending Error: {err:?}");
                }
            }
        }
        Err(err) => {
            log::error!("SMTP Connecting Error: {err:?}");
        }
    }
    

    But I got this error. AuthenticationFailed(Response { code: 535, esc: [5, 7, 8], message: "Username and Password not accepted. Learn more at\n https://support.google.com/mail/?p=BadCredentials p5-20020a1709028a8500b001ab0d815dbbsm2483183plo.23 - gsmtp" })

    I there any lacking in building the email?

    opened by LorenzoLeonardo 2
  • Disable SSL/TLS

    Disable SSL/TLS

    Is there a way to totally disable SSL/TLS? I am replacing lettre by mail-send, and I don't see how to do it. The equivalent with lettre is:

    SmtpTransport::relay(&config.host)?.tls(Tls::None);
    
    opened by soywod 1
  • fix: Extend buffer from bytes read while reading EHLO

    fix: Extend buffer from bytes read while reading EHLO

    Fixes #12

    (You only need to read the very bottom of https://github.com/stalwartlabs/mail-send/issues/12#issuecomment-1432226194 - the rest above that is explorative debugging.)

    The above linked comment explains what is fixed here:

    When a single chunk is not enough, then the here-corrected method previously dumped the entire zeroed buffer into a vector. It then appended to the end of the full 1024 bytes on the next loop iteration.

    This PR fixes this behavior by only dumping the bytes read into the concatenation vec.

    opened by LeoniePhiline 1
  • fix: Remove dead link to COPYING file

    fix: Remove dead link to COPYING file

    Removed a dead link from README.md. The "License" section just above should suffice.

    List-style was auto-adjusted. I kept that in the PR, because it matches the rest of the file.

    opened by LeoniePhiline 1
  • Fails to compile (Even in hello world)

    Fails to compile (Even in hello world)

    Adding this crate to even cargo's default hello world program causes it to fail to compile:

    error[E0599]: &HeaderType<'_> is not an iterator --> /home/westly/.cargo/registry/src/github.com-1ecc6299db9ec823/mail-send-0.2.0/src/smtp/message.rs:160:91 | 160 | if let Some(HeaderType::Address(address::Address::Address(addr))) = value.last() { | ^^^^ &HeaderType<'_> is not an iterator | ::: /home/westly/.cargo/registry/src/github.com-1ecc6299db9ec823/mail-builder-0.2.1/src/headers/mod.rs:32:1 | 32 | pub enum HeaderType<'x> { | ----------------------- doesn't satisfy HeaderType<'_>: Iterator | = note: the following trait bounds were not satisfied: &HeaderType<'_>: Iterator which is required by &mut &HeaderType<'_>: Iterator HeaderType<'_>: Iterator which is required by &mut HeaderType<'_>: Iterator

    error[E0277]: &HeaderType<'_> is not an iterator --> /home/westly/.cargo/registry/src/github.com-1ecc6299db9ec823/mail-send-0.2.0/src/smtp/message.rs:170:29 | 170 | for addr in value { | ^^^^^ &HeaderType<'_> is not an iterator | = help: the trait Iterator is not implemented for &HeaderType<'_> = note: required because of the requirements on the impl of IntoIterator for &HeaderType<'_>

    Some errors have detailed explanations: E0277, E0599. For more information about an error, try rustc --explain E0277. error: could not compile mail-send due to 2 previous errors warning: build failed, waiting for other jobs to finish...

    opened by sonicrules1234 1
  • Remove skip-ehlo feature, replace with config option

    Remove skip-ehlo feature, replace with config option

    Hi, I love the work on Stalwart mail server!

    Depending on the mesg-send crate across a larger codebase sometimes requires skipping EHLO and sometimes doesn't. Using compile-time flags results in accidental behaviour where all usage either skips or doesn't skip, or care is needed to compile and use two separate dependencies, with some other headaches potentially requiring multiple mail-builder deps.

    This PR removes the skip-ehlo compile-time feature in favour of a config option in the SmtpClientBuilder for usability. If you're happy to include this PR, I can make a matching PR to fix usages in mail-server and any other stalwart repos that use the skip-ehlo feature.

    Let me know if there's anything else I can do to make this an easy change.

    Matching PR: https://github.com/stalwartlabs/mail-server/pull/121

    Cheers, Liam

    opened by hoxxep 0
  • Refactor message, send_msg(), sign()

    Refactor message, send_msg(), sign()

    • New send_msg(&mut self, message: &Message<'x>) to send message which was already transformed using IntoMessage. Now you can have owned Message, so if any error occurs, you don't loose the entire message, so you can send it again.
    • New sign(&mut self, signer: &DkimSigner<_>) method on Message, which signs message in place, and then message can be sent using usual send().
    • Couple #[inline], because compiler does not inline by default, as far as I know, so you need to tell it which function you think may be inlined. It improves performance.
    • Sized traits
    opened by RoDmitry 0
  • Non-async support?

    Non-async support?

    Hi,

    Thanks for publishing this crate and all the other, related, ones.

    I'd like to use it in a small program that wouldn't use async or tokio, and it's not clear to me whether it can be done.

    The doc says:

    Full async (requires Tokio).

    which is a bit ambiguous to me. Does it support async with a dependency on tokio if it is enabled, or is the crate only designed to support async?

    If the latter, do you have any plans on supporting non-async?

    opened by mripard 4
  • ✨ Feature request: OpenPGP encryption support

    ✨ Feature request: OpenPGP encryption support

    Introduction

    Hi! I love this project idea and really appreciate the dedication to modern security standards (such as DKIM support) as well as mail-send's RFC compliance. The current feature set would serve as a fantastic base for a security-oriented Rust-written mail client if that is something Stalwart Labs would be interested in pursuing.

    The final component of mail-send that would make it a serious security contender (in terms of client features) to the likes of ProtonMail and Tutanota would be support for OpenPGP, the open standard for email encryption.

    Proposal

    Standards

    mail-send could implement OpenPGP support by following these Internet Message Format standards:

    • [ ] RFC 4880 OpenPGP Message Format
    • [ ] RFC 3156 MIME* Security with OpenPGP

    There are two strong libraries that have implemented RFC 4880: rpgp and sequoia.

    *Comparison of OpenPGP vs. PGP/MIME and a table of major email client support for them

    Implementation

    The loading of a public PGP key could be done in a similar syntax to the implementation of DKIM in this crate:

    // Set up DKIM signer
    let pgp_key = PGP::from_pkcs1_asc_file("./key.asc")
        .unwrap()
    

    ^ I'm not very familiar with PGP so not sure if any other inputs besides the file path should be provided

    // Build a encrypted text message with a single attachment
    let message = MessageBuilder::new()
        .from(("John Doe", "[email protected]"))
        .to("[email protected]")
        .subject("Howdy!")
        .text_body("These pretzels are making me thirsty.")
        .binary_attachment("image/png", "pretzels.png", [1, 2, 3, 4].as_ref())
        .pgp_encrypt(pgp_key);
    

    Interested to hear your thoughts! Let me know if this issue would be better suited at mail-builder.

    opened by spikecodes 6
Releases(0.3.2)
Owner
Stalwart Labs
We're building a modern mail server in Rust
Stalwart Labs
Rust library to parse mail files

mailparse A simple parser for MIME email messages. API The primary entry point for this library is the following function: parse_mail(&[u8]) -> Re

Kartikaya Gupta (kats) 150 Dec 27, 2022
Fast and robust e-mail parsing library for Rust

mail-parser mail-parser is an e-mail parsing library written in Rust that fully conforms to the Internet Message Format standard (RFC 5322), the Multi

Stalwart Labs 158 Jan 1, 2023
A mail suite written in rust meant to be easy to use.

Erooster A mail suite written in rust meant to be easy to use. Getting started Currently the setup is quite rough. You need some certificates for your

Marcel 33 Dec 19, 2022
Unofficial Rust library for the SendGrid API

sendgrid-rs Unofficial Rust library for the SendGrid API. This crate requires Rust 1.15 or higher as it uses a crate that has a custom derive implemen

Garrett Squire 88 Dec 27, 2022
a mailer library for Rust

lettre A mailer library for Rust NOTE: this readme refers to the 0.10 version of lettre, which is still being worked on. The master branch and the alp

lettre 1.3k Jan 4, 2023
An ESMTP server library written in Rust.

rs-smtp An ESMTP server library written in Rust. Features ESMTP client & server implementing RFC 5321 Support for SMTP AUTH and PIPELINING UTF-8 suppo

DUNEF 3 Apr 15, 2023
A small unofficial library to send emails using Sendgrid.

sendgrid_thin A thin wrapper around the SendGrid V3 API. It does not use the crate tokio or hyper and is therefore very lightweight and do not interfe

Reinaldo Rozato Junior 3 Nov 17, 2022
新しい IMAP client in Rust

新しい IMAP client 新しい (atarashii/new) IMAP client in Rust. It supports plain and secure connections. In progress It's under development... Usage Put thi

Alex Maslakov 39 Sep 13, 2020
Implementation of mjml in rust

MRML Introduction This project is a reimplementation of the nice MJML markup language in Rust. How to use it use mrml; fn main() { match mrml::to

Jérémie Drouet 228 Dec 28, 2022
Rust implementation of catapulte email sender

Catapulte What is catapulte? Catapulte is an open source mailer you can host yourself. You can use it to quickly catapult your transactionnal emails t

Jérémie Drouet 108 Dec 14, 2022
📫Himalaya: CLI email client written in Rust.

??Himalaya: CLI email client written in Rust.

Clément DOUIN 2.1k Jan 7, 2023
Check if an email address exists without sending any email, written in Rust.

Check if an email address exists without sending any email, written in Rust.

Reacher 3.5k Dec 31, 2022
A rewrite of the server side parts of emersion/go-smtp package into rust.

rust-smtp-server A rust smtp server library. It's mainly a rewrite of the server side parts of the emersion/go-smtp library. Features Usage Add this t

Nick Westendorf 3 Apr 26, 2023
mail-builder is a flexible e-mail builder library written in Rust that generates RFC5322 compliant e-mail messages

mail-builder mail-builder is a flexible e-mail builder library written in Rust that generates RFC5322 compliant e-mail messages. The library has full

Stalwart Labs 37 Dec 19, 2022
Easy c̵̰͠r̵̛̠ö̴̪s̶̩̒s̵̭̀-t̶̲͝h̶̯̚r̵̺͐e̷̖̽ḁ̴̍d̶̖̔ ȓ̵͙ė̶͎ḟ̴͙e̸̖͛r̶̖͗ë̶̱́ṉ̵̒ĉ̷̥e̷͚̍ s̷̹͌h̷̲̉a̵̭͋r̷̫̊ḭ̵̊n̷̬͂g̵̦̃ f̶̻̊ơ̵̜ṟ̸̈́ R̵̞̋ù̵̺s̷̖̅ţ̸͗!̸̼͋

Rust S̵̓i̸̓n̵̉ I̴n̴f̶e̸r̵n̷a̴l mutability! Howdy, friendly Rust developer! Ever had a value get m̵̯̅ð̶͊v̴̮̾ê̴̼͘d away right under your nose just when

null 294 Dec 23, 2022
DKIM (RFC6376) implementation

cfdkim DKIM (RFC6376) implementation Features Verifying email signatures Example: let res: DKIMResult = cfdkim::verify_email(&logger, &from_domain, &p

Cloudflare 22 Dec 3, 2022
Rust library to parse mail files

mailparse A simple parser for MIME email messages. API The primary entry point for this library is the following function: parse_mail(&[u8]) -> Re

Kartikaya Gupta (kats) 150 Dec 27, 2022
Fast and robust e-mail parsing library for Rust

mail-parser mail-parser is an e-mail parsing library written in Rust that fully conforms to the Internet Message Format standard (RFC 5322), the Multi

Stalwart Labs 158 Jan 1, 2023
A static mail HTML archive for the 21st century, written in Rust

?? Crabmail ?? self-hosted / github mirror A static mail HTML archive for the 21st century, written in Rust. Includes helpful "modern" features that e

Alex Wennerberg 18 Oct 11, 2022
A mail suite written in rust meant to be easy to use.

Erooster A mail suite written in rust meant to be easy to use. Getting started Currently the setup is quite rough. You need some certificates for your

Marcel 33 Dec 19, 2022