This commit is contained in:
Jon Gjengset 2018-04-03 13:01:35 -04:00
parent 6e47ceb171
commit 1d4d6288c1
No known key found for this signature in database
GPG key ID: D64AC9D67176DC71
8 changed files with 35 additions and 40 deletions

View file

@ -1,8 +1,8 @@
extern crate imap; extern crate imap;
extern crate native_tls; extern crate native_tls;
use native_tls::TlsConnector;
use imap::client::Client; use imap::client::Client;
use native_tls::TlsConnector;
// To connect to the gmail IMAP server with this you will need to allow unsecure apps access. // To connect to the gmail IMAP server with this you will need to allow unsecure apps access.
// See: https://support.google.com/accounts/answer/6010255?hl=en // See: https://support.google.com/accounts/answer/6010255?hl=en

View file

@ -2,10 +2,10 @@ extern crate base64;
extern crate imap; extern crate imap;
extern crate native_tls; extern crate native_tls;
use native_tls::TlsConnector;
use base64::encode; use base64::encode;
use imap::client::Client;
use imap::authenticator::Authenticator; use imap::authenticator::Authenticator;
use imap::client::Client;
use native_tls::TlsConnector;
struct GmailOAuth2 { struct GmailOAuth2 {
user: String, user: String,
@ -18,8 +18,7 @@ impl Authenticator for GmailOAuth2 {
encode( encode(
format!( format!(
"user={}\x01auth=Bearer {}\x01\x01", "user={}\x01auth=Bearer {}\x01\x01",
self.user, self.user, self.access_token
self.access_token
).as_bytes(), ).as_bytes(),
) )
} }

View file

@ -1,15 +1,15 @@
use std::net::{TcpStream, ToSocketAddrs};
use native_tls::{TlsConnector, TlsStream};
use std::io::{self, Read, Write};
use std::time::Duration;
use bufstream::BufStream; use bufstream::BufStream;
use native_tls::{TlsConnector, TlsStream};
use nom::IResult; use nom::IResult;
use std::io::{self, Read, Write};
use std::net::{TcpStream, ToSocketAddrs};
use std::time::Duration;
use super::types::*;
use super::authenticator::Authenticator; use super::authenticator::Authenticator;
use super::error::{Error, ParseError, Result, ValidateError};
use super::parse::{parse_authenticate_response, parse_capabilities, parse_fetches, parse_mailbox, use super::parse::{parse_authenticate_response, parse_capabilities, parse_fetches, parse_mailbox,
parse_names}; parse_names};
use super::error::{Error, ParseError, Result, ValidateError}; use super::types::*;
static TAG_PREFIX: &'static str = "a"; static TAG_PREFIX: &'static str = "a";
const INITIAL_TAG: u32 = 0; const INITIAL_TAG: u32 = 0;
@ -17,9 +17,9 @@ const CR: u8 = 0x0d;
const LF: u8 = 0x0a; const LF: u8 = 0x0a;
macro_rules! quote { macro_rules! quote {
($x: expr) => ( ($x:expr) => {
format!("\"{}\"", $x.replace(r"\", r"\\").replace("\"", "\\\"")) format!("\"{}\"", $x.replace(r"\", r"\\").replace("\"", "\\\""))
) };
} }
fn validate_str(value: &str) -> Result<String> { fn validate_str(value: &str) -> Result<String> {
@ -447,9 +447,7 @@ impl<T: Read + Write> Client<T> {
/// The APPEND command adds a mail to a mailbox. /// The APPEND command adds a mail to a mailbox.
pub fn append(&mut self, folder: &str, content: &[u8]) -> Result<()> { pub fn append(&mut self, folder: &str, content: &[u8]) -> Result<()> {
try!(self.run_command( try!(self.run_command(&format!("APPEND \"{}\" {{{}}}", folder, content.len())));
&format!("APPEND \"{}\" {{{}}}", folder, content.len())
));
let mut v = Vec::new(); let mut v = Vec::new();
try!(self.readline(&mut v)); try!(self.readline(&mut v));
if !v.starts_with(b"+") { if !v.starts_with(b"+") {
@ -538,14 +536,14 @@ impl<T: Read + Write> Client<T> {
use imap_proto::Status; use imap_proto::Status;
match status { match status {
Status::Bad => { Status::Bad => {
break Err(Error::BadResponse( break Err(Error::BadResponse(expl.unwrap_or(
expl.unwrap_or("no explanation given".to_string()), "no explanation given".to_string(),
)) )))
} }
Status::No => { Status::No => {
break Err(Error::NoResponse( break Err(Error::NoResponse(expl.unwrap_or(
expl.unwrap_or("no explanation given".to_string()), "no explanation given".to_string(),
)) )))
} }
_ => break Err(Error::Parse(ParseError::Invalid(data.split_off(0)))), _ => break Err(Error::Parse(ParseError::Invalid(data.split_off(0)))),
} }
@ -597,9 +595,9 @@ impl<T: Read + Write> Client<T> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*;
use super::super::mock_stream::MockStream;
use super::super::error::Result; use super::super::error::Result;
use super::super::mock_stream::MockStream;
use super::*;
#[test] #[test]
fn read_response() { fn read_response() {
@ -610,7 +608,6 @@ mod tests {
assert_eq!(Vec::<u8>::new(), actual_response); assert_eq!(Vec::<u8>::new(), actual_response);
} }
#[test] #[test]
fn fetch_body() { fn fetch_body() {
let response = "a0 OK Logged in.\r\n\ let response = "a0 OK Logged in.\r\n\
@ -622,7 +619,6 @@ mod tests {
client.read_response().unwrap(); client.read_response().unwrap();
} }
#[test] #[test]
fn read_greeting() { fn read_greeting() {
let greeting = "* OK Dovecot ready.\r\n"; let greeting = "* OK Dovecot ready.\r\n";

View file

@ -1,14 +1,14 @@
use std::io::Error as IoError;
use std::result;
use std::fmt;
use std::error::Error as StdError; use std::error::Error as StdError;
use std::fmt;
use std::io::Error as IoError;
use std::net::TcpStream; use std::net::TcpStream;
use std::result;
use std::string::FromUtf8Error; use std::string::FromUtf8Error;
use imap_proto::Response;
use native_tls::HandshakeError as TlsHandshakeError;
use native_tls::Error as TlsError;
use bufstream::IntoInnerError as BufError; use bufstream::IntoInnerError as BufError;
use imap_proto::Response;
use native_tls::Error as TlsError;
use native_tls::HandshakeError as TlsHandshakeError;
pub type Result<T> = result::Result<T, Error>; pub type Result<T> = result::Result<T, Error>;

View file

@ -9,8 +9,8 @@ extern crate native_tls;
extern crate nom; extern crate nom;
extern crate regex; extern crate regex;
mod types;
mod parse; mod parse;
mod types;
pub mod authenticator; pub mod authenticator;
pub mod client; pub mod client;

View file

@ -1,5 +1,5 @@
use std::io::{Error, ErrorKind, Read, Result, Write};
use std::cmp::min; use std::cmp::min;
use std::io::{Error, ErrorKind, Read, Result, Write};
#[derive(Clone, Debug, Eq, PartialEq, Hash)] #[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct MockStream { pub struct MockStream {

View file

@ -1,9 +1,9 @@
use regex::Regex;
use nom::IResult;
use imap_proto::{self, Response}; use imap_proto::{self, Response};
use nom::IResult;
use regex::Regex;
use super::types::*;
use super::error::{Error, ParseError, Result}; use super::error::{Error, ParseError, Result};
use super::types::*;
pub fn parse_authenticate_response(line: String) -> Result<String> { pub fn parse_authenticate_response(line: String) -> Result<String> {
let authenticate_regex = Regex::new("^+(.*)\r\n").unwrap(); let authenticate_regex = Regex::new("^+(.*)\r\n").unwrap();
@ -59,8 +59,8 @@ pub fn parse_names(lines: Vec<u8>) -> ZeroCopyResult<Vec<Name>> {
flags, flags,
delimiter, delimiter,
name, name,
}) | })
Response::MailboxData(MailboxDatum::SubList { | Response::MailboxData(MailboxDatum::SubList {
flags, flags,
delimiter, delimiter,
name, name,

View file

@ -4,8 +4,8 @@ use std::collections::HashSet;
use std::collections::hash_set::Iter; use std::collections::hash_set::Iter;
pub struct Capabilities(pub(crate) HashSet<&'static str>); pub struct Capabilities(pub(crate) HashSet<&'static str>);
use std::hash::Hash;
use std::borrow::Borrow; use std::borrow::Borrow;
use std::hash::Hash;
impl Capabilities { impl Capabilities {
pub fn has<S: ?Sized>(&self, s: &S) -> bool pub fn has<S: ?Sized>(&self, s: &S) -> bool
where where