Skip to content

Commit

Permalink
Version 2.0
Browse files Browse the repository at this point in the history
Remove connection setup and all the "transports" except SMTP.

Now the user is responsible for providing a stream with
TLS, read and write timeouts, buffering, SOCKS5 etc.

This makes it possible to have proper read and write
timeouts instead of per-command timeouts,
use alternative TLS implementations such as Rustls
and use SMTP over other proxies, such as HTTP CONNECT,
without modifying the library.
  • Loading branch information
link2xt committed Jan 27, 2023
1 parent 671a74c commit f03cc78
Show file tree
Hide file tree
Showing 33 changed files with 587 additions and 2,866 deletions.
24 changes: 2 additions & 22 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,44 +31,24 @@ jobs:
command: check
args: --all --bins --examples --tests

- name: check bench
uses: actions-rs/cargo@v1
if: matrix.rust == 'nightly'
with:
command: check
args: --benches

- name: tests tokio
uses: actions-rs/cargo@v1
with:
command: test
args: --all --no-default-features --features file-transport,smtp-transport,runtime-tokio

- name: tests tokio with socks5
uses: actions-rs/cargo@v1
with:
command: test
args: --all --no-default-features --features file-transport,smtp-transport,runtime-tokio,socks5
args: --all --no-default-features --features runtime-tokio

- name: tests async-std
uses: actions-rs/cargo@v1
with:
command: test
args: --all --no-default-features --features file-transport,smtp-transport,runtime-async-std
args: --all --no-default-features --features runtime-async-std

check_fmt_and_docs:
name: Checking fmt and docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@master

- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: nightly
override: true
components: rustfmt

- name: fmt
run: cargo fmt --all -- --check

Expand Down
52 changes: 10 additions & 42 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[package]

name = "async-smtp"
version = "0.6.0"
version = "2.0.0"
description = "SMTP client"
readme = "README.md"
homepage = "https://github.com/async-email/async-smtp"
Expand All @@ -18,25 +18,18 @@ is-it-maintained-issue-resolution = { repository = "async-email/async-smtp" }
is-it-maintained-open-issues = { repository = "async-email/async-smtp" }

[dependencies]
log = "^0.4"
async-trait = "0.1.17"
pin-project = "1"
pin-utils = "0.1.0"
thiserror = "1.0.9"
futures = "0.3.21"

nom = { version = "^7.0", optional = true }
bufstream = { version = "^0.1", optional = true }
base64 = { version = "^0.13", optional = true }
hostname = { version = "0.3.1", optional = true }
serde = { version = "^1.0", optional = true }
serde_json = { version = "^1.0", optional = true }
serde_derive = { version = "^1.0", optional = true }
fast-socks5 = { version = "^0.8", optional = true }

anyhow = "1"
async-native-tls = { version = "0.4", default-features = false }
async-std = { version = "1.11", features = ["unstable"], optional = true }
base64 = "^0.13"
bufstream = "^0.1"
futures = "0.3.21"
hostname = "0.3.1"
log = "^0.4"
nom = "^7.0"
thiserror = "1"
tokio = { version = "1", features = ["fs", "rt", "time", "net"], optional = true }
async-native-tls = { version = "0.4", default-features = false }


[dev-dependencies]
Expand All @@ -46,36 +39,11 @@ criterion = "^0.3"
async-std = { version = "1.11", features = ["unstable", "attributes"] }
tokio = { version = "1", features = ["fs", "rt", "time", "net", "macros"] }

[[bench]]
name = "transport_smtp"
harness = false

[features]
default = [
"file-transport",
"smtp-transport",
"sendmail-transport",
"runtime-tokio"
]

serde-impls = ["serde", "serde_derive"]
file-transport = ["serde-impls", "serde_json"]
smtp-transport = ["bufstream", "base64", "nom", "hostname"]
sendmail-transport = []
native-tls-vendored = ["async-native-tls/vendored"]
socks5 = ["fast-socks5"]
runtime-async-std = ["async-std", "async-native-tls/runtime-async-std"]
runtime-tokio = ["tokio", "async-native-tls/runtime-tokio"]


[[example]]
name = "smtp"
required-features = ["smtp-transport"]

[[example]]
name = "smtp_gmail"
required-features = ["smtp-transport"]

[[example]]
name = "socks5"
required-features = ["smtp-transport", "socks5"]
73 changes: 0 additions & 73 deletions benches/transport_smtp.rs

This file was deleted.

29 changes: 0 additions & 29 deletions examples/smtp.rs

This file was deleted.

37 changes: 0 additions & 37 deletions examples/smtp_gmail.rs

This file was deleted.

38 changes: 0 additions & 38 deletions examples/socks5.rs

This file was deleted.

1 change: 0 additions & 1 deletion rustfmt.toml

This file was deleted.

16 changes: 4 additions & 12 deletions src/smtp/authentication.rs → src/authentication.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! Provides limited SASL authentication mechanisms

use crate::smtp::error::Error;
use crate::error::Error;
use std::fmt::{self, Display, Formatter};

/// Accepted authentication mechanisms on an encrypted connection
Expand Down Expand Up @@ -31,10 +31,6 @@ impl<S: Into<String>, T: Into<String>> IntoCredentials for (S, T) {

/// Contains user credentials
#[derive(PartialEq, Eq, Clone, Hash, Debug)]
#[cfg_attr(
feature = "serde-impls",
derive(serde_derive::Serialize, serde_derive::Deserialize)
)]
pub struct Credentials {
authentication_identity: String,
secret: String,
Expand All @@ -52,20 +48,16 @@ impl Credentials {

/// Represents authentication mechanisms
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
#[cfg_attr(
feature = "serde-impls",
derive(serde_derive::Serialize, serde_derive::Deserialize)
)]
pub enum Mechanism {
/// PLAIN authentication mechanism
/// RFC 4616: https://tools.ietf.org/html/rfc4616
/// RFC 4616: <https://tools.ietf.org/html/rfc4616>
Plain,
/// LOGIN authentication mechanism
/// Obsolete but needed for some providers (like office365)
/// https://www.ietf.org/archive/id/draft-murchison-sasl-login-00.txt
/// <https://www.ietf.org/archive/id/draft-murchison-sasl-login-00.txt>
Login,
/// Non-standard XOAUTH2 mechanism
/// https://developers.google.com/gmail/imap/xoauth2-protocol
/// <https://developers.google.com/gmail/imap/xoauth2-protocol>
Xoauth2,
}

Expand Down
29 changes: 25 additions & 4 deletions src/smtp/client/codec.rs → src/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,6 @@ use futures::io;

/// The codec used for transparency
#[derive(Default, Clone, Copy, Debug)]
#[cfg_attr(
feature = "serde-impls",
derive(serde_derive::Serialize, serde_derive::Deserialize)
)]
pub struct ClientCodec {
escape_count: u8,
}
Expand Down Expand Up @@ -68,3 +64,28 @@ impl ClientCodec {
}
}
}

#[cfg(test)]
mod test {
use super::*;
use crate::async_test;

async_test! { test_codec, {
let mut codec = ClientCodec::new();
let mut buf: Vec<u8> = vec![];

assert!(codec.encode(b"test\r\n", &mut buf).await.is_ok());
assert!(codec.encode(b".\r\n", &mut buf).await.is_ok());
assert!(codec.encode(b"\r\ntest", &mut buf).await.is_ok());
assert!(codec.encode(b"te\r\n.\r\nst", &mut buf).await.is_ok());
assert!(codec.encode(b"test", &mut buf).await.is_ok());
assert!(codec.encode(b"test.", &mut buf).await.is_ok());
assert!(codec.encode(b"test\n", &mut buf).await.is_ok());
assert!(codec.encode(b".test\n", &mut buf).await.is_ok());
assert!(codec.encode(b"test", &mut buf).await.is_ok());
assert_eq!(
String::from_utf8(buf).unwrap(),
"test\r\n..\r\n\r\ntestte\r\n..\r\nsttesttest.test\n.test\ntest"
);
}}
}
Loading

0 comments on commit f03cc78

Please sign in to comment.