Skip to content

Commit c8288ea

Browse files
authored
Merge pull request #138 from brycefisher/feat/rustls-support
(feat) Provide example integration with Rustls crate
2 parents 281d2eb + 76bcf02 commit c8288ea

File tree

5 files changed

+70
-2
lines changed

5 files changed

+70
-2
lines changed

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,4 @@ lazy_static = "1.4"
3434
[dev-dependencies]
3535
lettre = "0.9"
3636
lettre_email = "0.9"
37+
rustls-connector = "0.8.0"

azure-pipelines.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,12 @@ stages:
99
# This represents the minimum Rust version supported.
1010
# Tests are not run as tests may require newer versions of rust.
1111
- stage: msrv
12-
displayName: "Minimum supported Rust version: 1.32.0"
12+
displayName: "Minimum supported Rust version: 1.36.0"
1313
dependsOn: []
1414
jobs:
1515
- template: azure/cargo-check.yml@templates
1616
parameters:
17-
rust: 1.32.0
17+
rust: 1.36.0
1818
- stage: test
1919
displayName: Test suite
2020
dependsOn: check

examples/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ This directory contains examples of working with the IMAP client.
66
Examples:
77
* basic - This is a very basic example of using the client.
88
* gmail_oauth2 - This is an example using oauth2 for logging into gmail as a secure appplication.
9+
* rustls - This demonstrates how to use Rustls instead of Openssl for secure connections (helpful for cross compilation).

examples/rustls.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
extern crate imap;
2+
extern crate rustls_connector;
3+
4+
use std::{env, error::Error, net::TcpStream};
5+
6+
use rustls_connector::RustlsConnector;
7+
8+
fn main() -> Result<(), Box<dyn Error>> {
9+
// Read config from environment or .env file
10+
let host = env::var("HOST").expect("missing envvar host");
11+
let user = env::var("MAILUSER").expect("missing envvar USER");
12+
let password = env::var("PASSWORD").expect("missing envvar password");
13+
let port = 993;
14+
15+
if let Some(email) = fetch_inbox_top(host, user, password, port)? {
16+
println!("{}", &email);
17+
}
18+
19+
Ok(())
20+
}
21+
22+
fn fetch_inbox_top(
23+
host: String,
24+
user: String,
25+
password: String,
26+
port: u16,
27+
) -> Result<Option<String>, Box<dyn Error>> {
28+
// Setup Rustls TcpStream
29+
let stream = TcpStream::connect((host.as_ref(), port))?;
30+
let tls = RustlsConnector::default();
31+
let tlsstream = tls.connect(&host, stream)?;
32+
33+
// we pass in the domain twice to check that the server's TLS
34+
// certificate is valid for the domain we're connecting to.
35+
let client = imap::Client::new(tlsstream);
36+
37+
// the client we have here is unauthenticated.
38+
// to do anything useful with the e-mails, we need to log in
39+
let mut imap_session = client.login(&user, &password).map_err(|e| e.0)?;
40+
41+
// we want to fetch the first email in the INBOX mailbox
42+
imap_session.select("INBOX")?;
43+
44+
// fetch message number 1 in this mailbox, along with its RFC822 field.
45+
// RFC 822 dictates the format of the body of e-mails
46+
let messages = imap_session.fetch("1", "RFC822")?;
47+
let message = if let Some(m) = messages.iter().next() {
48+
m
49+
} else {
50+
return Ok(None);
51+
};
52+
53+
// extract the message's body
54+
let body = message.body().expect("message did not have a body!");
55+
let body = std::str::from_utf8(body)
56+
.expect("message was not valid utf-8")
57+
.to_string();
58+
59+
// be nice to the server and log out
60+
imap_session.logout()?;
61+
62+
Ok(Some(body))
63+
}

src/client.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,9 @@ macro_rules! ok_or_unauth_client_err {
222222
impl<T: Read + Write> Client<T> {
223223
/// Creates a new client over the given stream.
224224
///
225+
/// For an example of how to use this method to provide a pure-Rust TLS integration, see the
226+
/// rustls.rs in the examples/ directory.
227+
///
225228
/// This method primarily exists for writing tests that mock the underlying transport, but can
226229
/// also be used to support IMAP over custom tunnels.
227230
pub fn new(stream: T) -> Client<T> {

0 commit comments

Comments
 (0)