From f7fca7b293b9c5affbdcf331801447638f1cc356 Mon Sep 17 00:00:00 2001 From: k8scat Date: Sun, 19 Sep 2021 21:53:59 +0800 Subject: [PATCH 1/9] update: release 1.0.7 --- Cargo.toml | 15 +- README.md | 3 + src/pop3.rs | 856 ++++++++++++++++++++++++++-------------------------- 3 files changed, 438 insertions(+), 436 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 79901fea..e2b08130 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,22 +1,17 @@ [package] - -name = "pop3" -version = "1.0.6" +name = "rs-pop3" +version = "1.0.7" authors = ["Matt McCoy "] -homepage = "https://github.com/mattnenterprise/rust-pop3" -repository = "https://github.com/mattnenterprise/rust-pop3" +homepage = "https://github.com/k8scat/rust-pop3" +repository = "https://github.com/k8scat/rust-pop3" description = "POP3 client for Rust" readme = "README.md" license = "MIT" [lib] -name = "pop3" +name = "rs_pop3" path = "src/pop3.rs" -[[bin]] -name = "example" -path = "example.rs" - [dependencies] openssl = "0.10" regex = "1" diff --git a/README.md b/README.md index 907181f5..961eacc7 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ rust-pop3 ================ + +**Forked https://github.com/mattnenterprise/rust-pop3** + POP3 Client for Rust This client has SSL support. SSL is configured using an SSLContext that is passed into the connect method of a POP3Stream. If no SSL diff --git a/src/pop3.rs b/src/pop3.rs index faa1824c..1070d075 100644 --- a/src/pop3.rs +++ b/src/pop3.rs @@ -1,4 +1,4 @@ -#![crate_name = "pop3"] +#![crate_name = "rs_pop3"] #![crate_type = "lib"] extern crate openssl; @@ -7,141 +7,153 @@ extern crate regex; #[macro_use] extern crate lazy_static; -use POP3StreamTypes::{Basic, Ssl}; -use POP3Command::{Greet, User, Pass, Stat, UidlAll, UidlOne, ListAll, ListOne, Retr, Dele, Noop, Rset, Quit}; -use std::string::String; +use openssl::ssl::{SslConnector, SslStream}; +use regex::Regex; use std::io::prelude::*; use std::io::{Error, ErrorKind, Result}; -use std::net::{ToSocketAddrs,TcpStream}; -use openssl::ssl::{SslConnector, SslStream}; -use std::str::FromStr; +use std::net::{TcpStream, ToSocketAddrs}; use std::str; -use regex::Regex; +use std::str::FromStr; +use std::string::String; +use POP3Command::{ + Dele, Greet, ListAll, ListOne, Noop, Pass, Quit, Retr, Rset, Stat, UidlAll, UidlOne, User, +}; +use POP3StreamTypes::{Basic, Ssl}; lazy_static! { static ref ENDING_REGEX: Regex = Regex::new(r"^\.\r\n$").unwrap(); static ref OK_REGEX: Regex = Regex::new(r"\+OK(.*)").unwrap(); static ref ERR_REGEX: Regex = Regex::new(r"-ERR(.*)").unwrap(); static ref STAT_REGEX: Regex = Regex::new(r"\+OK (\d+) (\d+)\r\n").unwrap(); - static ref MESSAGE_DATA_UIDL_ALL_REGEX: Regex = Regex::new(r"(\d+) ([\x21-\x7e]+)\r\n").unwrap(); - static ref MESSAGE_DATA_UIDL_ONE_REGEX: Regex = Regex::new(r"\+OK (\d+) ([\x21-\x7e]+)\r\n").unwrap(); + static ref MESSAGE_DATA_UIDL_ALL_REGEX: Regex = + Regex::new(r"(\d+) ([\x21-\x7e]+)\r\n").unwrap(); + static ref MESSAGE_DATA_UIDL_ONE_REGEX: Regex = + Regex::new(r"\+OK (\d+) ([\x21-\x7e]+)\r\n").unwrap(); static ref MESSAGE_DATA_LIST_ALL_REGEX: Regex = Regex::new(r"(\d+) (\d+)\r\n").unwrap(); } /// Wrapper for a regular TcpStream or a SslStream. #[derive(Debug)] enum POP3StreamTypes { - Basic(TcpStream), - Ssl(SslStream) + Basic(TcpStream), + Ssl(SslStream), } /// The stream to use for interfacing with the POP3 Server. #[derive(Debug)] pub struct POP3Stream { - stream: POP3StreamTypes, - pub is_authenticated: bool + stream: POP3StreamTypes, + pub is_authenticated: bool, } /// List of POP3 Commands #[derive(Clone)] enum POP3Command { - Greet, - User, - Pass, - Stat, + Greet, + User, + Pass, + Stat, UidlAll, UidlOne, - ListAll, - ListOne, - Retr, - Dele, - Noop, - Rset, - Quit + ListAll, + ListOne, + Retr, + Dele, + Noop, + Rset, + Quit, } impl POP3Stream { - - /// Creates a new POP3Stream. - pub fn connect(addr: A,ssl_context: Option,domain: &str) -> Result { - let tcp_stream = TcpStream::connect(addr)?; - let mut socket = match ssl_context { - Some(context) => POP3Stream { - stream: Ssl(SslConnector::connect(&context, domain,tcp_stream).unwrap()), - is_authenticated: false}, - None => POP3Stream { + /// Creates a new POP3Stream. + pub fn connect( + addr: A, + ssl_context: Option, + domain: &str, + ) -> Result { + let tcp_stream = TcpStream::connect(addr)?; + let mut socket = match ssl_context { + Some(context) => POP3Stream { + stream: Ssl(SslConnector::connect(&context, domain, tcp_stream).unwrap()), + is_authenticated: false, + }, + None => POP3Stream { stream: Basic(tcp_stream), - is_authenticated: false}, - }; - match socket.read_response(Greet) { - Ok(_) => (), - Err(_) => return Err(Error::new(ErrorKind::Other, "Failed to read greet response")) - } - Ok(socket) - } - - fn write_str(&mut self, s: &str) -> Result<()> { - match self.stream { - Ssl(ref mut stream) => stream.write_fmt(format_args!("{}", s)), - Basic(ref mut stream) => stream.write_fmt(format_args!("{}", s)), - } - } - - fn read(&mut self, buf: &mut [u8]) -> Result { - match self.stream { - Ssl(ref mut stream) => stream.read(buf), - Basic(ref mut stream) => stream.read(buf), - } - } - - /// Login to the POP3 server. - pub fn login(&mut self, username: &str, password: &str) -> POP3Result { - let user_command = format!("USER {}\r\n", username); - let pass_command = format!("PASS {}\r\n", password); - //Send user command - match self.write_str(&user_command) { - Ok(_) => {}, - Err(_) => panic!("Error writing"), - } - match self.read_response(User) { - Ok(_) => { - match self.write_str(&pass_command) { - Ok(_) => self.is_authenticated = true, - Err(_) => panic!("Error writing"), - } - match self.read_response(Pass) { - Ok(res) => match res.result { - Some(s) => s, - None => POP3Result::POP3Err, - }, - Err(_) => panic!("Failure to use PASS") - } - }, - Err(_) => panic!("Failure to use USER") - } - } - - /// Gives the current number of messages in the mailbox and the total size in bytes of the mailbox. - pub fn stat(&mut self) -> POP3Result { - if !self.is_authenticated { - panic!("login"); - } - - let stat_command = "STAT\r\n"; - match self.write_str(&stat_command) { - Ok(_) => {}, - Err(_) => panic!("Error writing"), - } - match self.read_response(Stat) { - Ok(res) => { - match res.result { - Some(s) => s, - None => POP3Result::POP3Err - } - }, - Err(_) => POP3Result::POP3Err - } - } + is_authenticated: false, + }, + }; + match socket.read_response(Greet) { + Ok(_) => (), + Err(_) => { + return Err(Error::new( + ErrorKind::Other, + "Failed to read greet response", + )) + } + } + Ok(socket) + } + + fn write_str(&mut self, s: &str) -> Result<()> { + match self.stream { + Ssl(ref mut stream) => stream.write_fmt(format_args!("{}", s)), + Basic(ref mut stream) => stream.write_fmt(format_args!("{}", s)), + } + } + + fn read(&mut self, buf: &mut [u8]) -> Result { + match self.stream { + Ssl(ref mut stream) => stream.read(buf), + Basic(ref mut stream) => stream.read(buf), + } + } + + /// Login to the POP3 server. + pub fn login(&mut self, username: &str, password: &str) -> POP3Result { + let user_command = format!("USER {}\r\n", username); + let pass_command = format!("PASS {}\r\n", password); + //Send user command + match self.write_str(&user_command) { + Ok(_) => {} + Err(_) => panic!("Error writing"), + } + match self.read_response(User) { + Ok(_) => { + match self.write_str(&pass_command) { + Ok(_) => self.is_authenticated = true, + Err(_) => panic!("Error writing"), + } + match self.read_response(Pass) { + Ok(res) => match res.result { + Some(s) => s, + None => POP3Result::POP3Err, + }, + Err(_) => panic!("Failure to use PASS"), + } + } + Err(_) => panic!("Failure to use USER"), + } + } + + /// Gives the current number of messages in the mailbox and the total size in bytes of the mailbox. + pub fn stat(&mut self) -> POP3Result { + if !self.is_authenticated { + panic!("login"); + } + + let stat_command = "STAT\r\n"; + match self.write_str(&stat_command) { + Ok(_) => {} + Err(_) => panic!("Error writing"), + } + match self.read_response(Stat) { + Ok(res) => match res.result { + Some(s) => s, + None => POP3Result::POP3Err, + }, + Err(_) => POP3Result::POP3Err, + } + } pub fn uidl(&mut self, message_number: Option) -> POP3Result { if !self.is_authenticated { @@ -158,380 +170,372 @@ impl POP3Stream { }; match self.write_str(&uidl_command) { - Ok(_) => {}, + Ok(_) => {} Err(_) => panic!("Error writing"), } match self.read_response(command_type) { - Ok(res) => { - match res.result { - Some(s) => s, - None => POP3Result::POP3Err - } + Ok(res) => match res.result { + Some(s) => s, + None => POP3Result::POP3Err, + }, + Err(_) => POP3Result::POP3Err, + } + } + + /// List displays a summary of messages where each message number is shown and the size of the message in bytes. + pub fn list(&mut self, message_number: Option) -> POP3Result { + if !self.is_authenticated { + panic!("login"); + } + + let list_command = match message_number { + Some(i) => format!("LIST {}\r\n", i), + None => format!("LIST\r\n"), + }; + let command_type = match message_number { + Some(_) => ListOne, + None => ListAll, + }; + + match self.write_str(&list_command) { + Ok(_) => {} + Err(_) => panic!("Error writing"), + } + + match self.read_response(command_type) { + Ok(res) => match res.result { + Some(s) => s, + None => POP3Result::POP3Err, + }, + Err(_) => POP3Result::POP3Err, + } + } + + /// retrieves the message of the message id given. + pub fn retr(&mut self, message_id: i32) -> POP3Result { + if !self.is_authenticated { + panic!("login"); + } + + let retr_command = format!("RETR {}\r\n", message_id); + + match self.write_str(&retr_command) { + Ok(_) => {} + Err(_) => panic!("Error writing"), + } + + match self.read_response(Retr) { + Ok(res) => match res.result { + Some(s) => s, + None => POP3Result::POP3Err, + }, + Err(_) => POP3Result::POP3Err, + } + } + + /// Delete the message with the given message id. + pub fn dele(&mut self, message_id: i32) -> POP3Result { + if !self.is_authenticated { + panic!("login"); + } + + let dele_command = format!("DELE {}\r\n", message_id); + + match self.write_str(&dele_command) { + Ok(_) => {} + Err(_) => panic!("Error writing"), + } + + match self.read_response(Dele) { + Ok(res) => match res.result { + Some(s) => s, + None => POP3Result::POP3Err, + }, + Err(_) => POP3Result::POP3Err, + } + } + + /// This resets the session to its original state. + pub fn rset(&mut self) -> POP3Result { + if !self.is_authenticated { + panic!("Not Logged In"); + } + + let retr_command = format!("RETR\r\n"); + + match self.write_str(&retr_command) { + Ok(_) => {} + Err(_) => panic!("Error writing"), + } + + match self.read_response(Rset) { + Ok(res) => match res.result { + Some(s) => s, + None => POP3Result::POP3Err, + }, + Err(_) => POP3Result::POP3Err, + } + } + + /// Quits the current session. + pub fn quit(&mut self) -> POP3Result { + let quit_command = "QUIT\r\n"; + + match self.write_str(&quit_command) { + Ok(_) => {} + Err(_) => panic!("Error writing"), + } + + match self.read_response(Quit) { + Ok(res) => match res.result { + Some(s) => s, + None => POP3Result::POP3Err, + }, + Err(_) => POP3Result::POP3Err, + } + } + + /// Doesn't do anything. This is usually just used to keep the connection open. + pub fn noop(&mut self) -> POP3Result { + if !self.is_authenticated { + panic!("Not Logged In"); + } + + let noop_command = "noop\r\n"; + + match self.write_str(noop_command) { + Ok(_) => {} + Err(_) => panic!("Error writing"), + } + + match self.read_response(Noop) { + Ok(res) => match res.result { + Some(s) => s, + None => POP3Result::POP3Err, }, - Err(_) => POP3Result::POP3Err + Err(_) => panic!("Error noop"), } } - /// List displays a summary of messages where each message number is shown and the size of the message in bytes. - pub fn list(&mut self, message_number: Option) -> POP3Result { - if !self.is_authenticated { - panic!("login"); - } - - let list_command = match message_number { - Some(i) => format!("LIST {}\r\n", i), - None => format!("LIST\r\n"), - }; - let command_type = match message_number { - Some(_) => ListOne, - None => ListAll, - }; - - match self.write_str(&list_command) { - Ok(_) => {}, - Err(_) => panic!("Error writing"), - } - - match self.read_response(command_type) { - Ok(res) => { - match res.result { - Some(s) => s, - None => POP3Result::POP3Err - } - }, - Err(_) => POP3Result::POP3Err - } - } - - /// retrieves the message of the message id given. - pub fn retr(&mut self, message_id: i32) -> POP3Result { - if !self.is_authenticated { - panic!("login"); - } - - let retr_command = format!("RETR {}\r\n", message_id); - - match self.write_str(&retr_command) { - Ok(_) => {}, - Err(_) => panic!("Error writing"), - } - - match self.read_response(Retr) { - Ok(res) => { - match res.result { - Some(s) => s, - None => POP3Result::POP3Err - } - }, - Err(_) => POP3Result::POP3Err - } - } - - /// Delete the message with the given message id. - pub fn dele(&mut self, message_id: i32) -> POP3Result { - if !self.is_authenticated { - panic!("login"); - } - - let dele_command = format!("DELE {}\r\n", message_id); - - match self.write_str(&dele_command) { - Ok(_) => {}, - Err(_) => panic!("Error writing"), - } - - match self.read_response(Dele) { - Ok(res) => { - match res.result { - Some(s) => s, - None => POP3Result::POP3Err - } - }, - Err(_) => POP3Result::POP3Err - } - } - - /// This resets the session to its original state. - pub fn rset(&mut self) -> POP3Result { - if !self.is_authenticated { - panic!("Not Logged In"); - } - - let retr_command = format!("RETR\r\n"); - - match self.write_str(&retr_command) { - Ok(_) => {}, - Err(_) => panic!("Error writing"), - } - - match self.read_response(Rset) { - Ok(res) => { - match res.result { - Some(s) => s, - None => POP3Result::POP3Err - } - }, - Err(_) => POP3Result::POP3Err - } - } - - /// Quits the current session. - pub fn quit(&mut self) -> POP3Result { - let quit_command = "QUIT\r\n"; - - match self.write_str(&quit_command) { - Ok(_) => {}, - Err(_) => panic!("Error writing"), - } - - match self.read_response(Quit) { - Ok(res) => { - match res.result { - Some(s) => s, - None => POP3Result::POP3Err - } - }, - Err(_) => POP3Result::POP3Err - } - } - - /// Doesn't do anything. This is usually just used to keep the connection open. - pub fn noop(&mut self) -> POP3Result { - if !self.is_authenticated { - panic!("Not Logged In"); - } - - let noop_command = "noop\r\n"; - - match self.write_str(noop_command) { - Ok(_) => {}, - Err(_) => panic!("Error writing"), - } - - match self.read_response(Noop) { - Ok(res) => { - match res.result { - Some(s) => s, - None => POP3Result::POP3Err - } - }, - Err(_) => panic!("Error noop") - } - } - - fn read_response(&mut self, command: POP3Command) -> Result> { - let mut response = Box::new(POP3Response::new()); - //Carriage return - let cr = 0x0d; - //Line Feed - let lf = 0x0a; - let mut line_buffer: Vec = Vec::new(); - - while !response.complete { - while line_buffer.len() < 2 || (line_buffer[line_buffer.len()-1] != lf && line_buffer[line_buffer.len()-2] != cr) { - let byte_buffer: &mut [u8] = &mut [0]; - match self.read(byte_buffer) { - Ok(_) => {}, - Err(_) => println!("Error Reading!"), - } - line_buffer.push(byte_buffer[0]); - } - - match String::from_utf8(line_buffer.clone()) { - Ok(res) => { - response.add_line(res, command.clone()); - line_buffer = Vec::new(); - }, - Err(_) => return Err(Error::new(ErrorKind::Other, "Failed to read the response")) - } - } - Ok(response) - } + fn read_response(&mut self, command: POP3Command) -> Result> { + let mut response = Box::new(POP3Response::new()); + //Carriage return + let cr = 0x0d; + //Line Feed + let lf = 0x0a; + let mut line_buffer: Vec = Vec::new(); + + while !response.complete { + while line_buffer.len() < 2 + || (line_buffer[line_buffer.len() - 1] != lf + && line_buffer[line_buffer.len() - 2] != cr) + { + let byte_buffer: &mut [u8] = &mut [0]; + match self.read(byte_buffer) { + Ok(_) => {} + Err(_) => println!("Error Reading!"), + } + line_buffer.push(byte_buffer[0]); + } + + match String::from_utf8(line_buffer.clone()) { + Ok(res) => { + response.add_line(res, command.clone()); + line_buffer = Vec::new(); + } + Err(_) => return Err(Error::new(ErrorKind::Other, "Failed to read the response")), + } + } + Ok(response) + } } -#[derive(Clone,Copy,Debug)] +#[derive(Clone, Copy, Debug)] pub struct POP3EmailMetadata { - pub message_id: i32, - pub message_size: i32 + pub message_id: i32, + pub message_size: i32, } -#[derive(Clone,Debug)] +#[derive(Clone, Debug)] pub struct POP3EmailUidldata { pub message_id: i32, - pub message_uid: String + pub message_uid: String, } #[derive(Debug)] pub enum POP3Result { - POP3Ok, - POP3Err, - POP3Stat { - num_email: i32, - mailbox_size: i32 - }, + POP3Ok, + POP3Err, + POP3Stat { + num_email: i32, + mailbox_size: i32, + }, POP3Uidl { emails_metadata: Vec, }, - POP3List { - emails_metadata: Vec, - }, - POP3Message { - raw: Vec, - }, + POP3List { + emails_metadata: Vec, + }, + POP3Message { + raw: Vec, + }, } #[derive(Default)] struct POP3Response { - complete: bool, - lines: Vec, - result: Option + complete: bool, + lines: Vec, + result: Option, } impl POP3Response { - fn new() -> POP3Response { - POP3Response { - complete: false, - lines: Vec::new(), - result: None - } - } - - fn add_line(&mut self, line: String, command: POP3Command) { - //We are retreiving status line - if self.lines.len() == 0 { - if OK_REGEX.is_match(&line) { - self.lines.push(line); - match command { - Greet|User|Pass|Quit|Dele|Rset => { - self.result = Some(POP3Result::POP3Ok); - self.complete = true; - }, - Stat => { - self.complete = true; - self.parse_stat() - }, - UidlAll => { - - }, - UidlOne => { - self.complete = true; - self.parse_uidl_one(); - }, - ListAll => { - - }, - ListOne => { - self.complete = true; - self.parse_list_one(); - }, - Retr => { - - }, - _ => self.complete = true, - } - } else if ERR_REGEX.is_match(&line) { - self.lines.push(line); - self.result = Some(POP3Result::POP3Err); - self.complete = true; - } - } else { - if ENDING_REGEX.is_match(&line) { - self.lines.push(line); - match command { - UidlAll => { - self.complete = true; - self.parse_uidl_all(); - }, - ListAll => { - self.complete = true; - self.parse_list_all(); - }, - Retr => { - self.complete = true; - self.parse_message(); - }, - _ => self.complete = true, - } - } else { - self.lines.push(line); - } - } - } - - fn parse_stat(&mut self) { - let caps = STAT_REGEX.captures(&self.lines[0]).unwrap(); - let num_emails = FromStr::from_str(caps.get(1).unwrap().as_str()); - let total_email_size = FromStr::from_str(caps.get(2).unwrap().as_str()); - self.result = Some(POP3Result::POP3Stat { - num_email: num_emails.unwrap(), - mailbox_size: total_email_size.unwrap() - }) - } + fn new() -> POP3Response { + POP3Response { + complete: false, + lines: Vec::new(), + result: None, + } + } + fn add_line(&mut self, line: String, command: POP3Command) { + //We are retreiving status line + if self.lines.len() == 0 { + if OK_REGEX.is_match(&line) { + self.lines.push(line); + match command { + Greet | User | Pass | Quit | Dele | Rset => { + self.result = Some(POP3Result::POP3Ok); + self.complete = true; + } + Stat => { + self.complete = true; + self.parse_stat() + } + UidlAll => {} + UidlOne => { + self.complete = true; + self.parse_uidl_one(); + } + ListAll => {} + ListOne => { + self.complete = true; + self.parse_list_one(); + } + Retr => {} + _ => self.complete = true, + } + } else if ERR_REGEX.is_match(&line) { + self.lines.push(line); + self.result = Some(POP3Result::POP3Err); + self.complete = true; + } + } else { + if ENDING_REGEX.is_match(&line) { + self.lines.push(line); + match command { + UidlAll => { + self.complete = true; + self.parse_uidl_all(); + } + ListAll => { + self.complete = true; + self.parse_list_all(); + } + Retr => { + self.complete = true; + self.parse_message(); + } + _ => self.complete = true, + } + } else { + self.lines.push(line); + } + } + } + + fn parse_stat(&mut self) { + let caps = STAT_REGEX.captures(&self.lines[0]).unwrap(); + let num_emails = FromStr::from_str(caps.get(1).unwrap().as_str()); + let total_email_size = FromStr::from_str(caps.get(2).unwrap().as_str()); + self.result = Some(POP3Result::POP3Stat { + num_email: num_emails.unwrap(), + mailbox_size: total_email_size.unwrap(), + }) + } fn parse_uidl_all(&mut self) { let mut metadata = Vec::new(); for i in 1..self.lines.len() - 1 { - let caps = MESSAGE_DATA_UIDL_ALL_REGEX.captures(&self.lines[i]).unwrap(); + let caps = MESSAGE_DATA_UIDL_ALL_REGEX + .captures(&self.lines[i]) + .unwrap(); let message_id = FromStr::from_str(caps.get(1).unwrap().as_str()); let message_uid = caps.get(2).unwrap().as_str(); metadata.push(POP3EmailUidldata { message_id: message_id.unwrap(), - message_uid: message_uid.to_owned() + message_uid: message_uid.to_owned(), }); } self.result = Some(POP3Result::POP3Uidl { - emails_metadata: metadata + emails_metadata: metadata, }); } fn parse_uidl_one(&mut self) { - let caps = MESSAGE_DATA_UIDL_ONE_REGEX.captures(&self.lines[0]).unwrap(); + let caps = MESSAGE_DATA_UIDL_ONE_REGEX + .captures(&self.lines[0]) + .unwrap(); let message_id = FromStr::from_str(caps.get(1).unwrap().as_str()); let message_uid = caps.get(2).unwrap().as_str(); self.result = Some(POP3Result::POP3Uidl { - emails_metadata: vec![POP3EmailUidldata{ - message_id: message_id.unwrap(), - message_uid: message_uid.to_owned() - }] + emails_metadata: vec![POP3EmailUidldata { + message_id: message_id.unwrap(), + message_uid: message_uid.to_owned(), + }], }); } - fn parse_list_all(&mut self) { - let mut metadata = Vec::new(); - - for i in 1 .. self.lines.len()-1 { - let caps = MESSAGE_DATA_LIST_ALL_REGEX.captures(&self.lines[i]).unwrap(); - let message_id = FromStr::from_str(caps.get(1).unwrap().as_str()); - let message_size = FromStr::from_str(caps.get(2).unwrap().as_str()); - metadata.push(POP3EmailMetadata{ message_id: message_id.unwrap(), message_size: message_size.unwrap()}); - } - self.result = Some(POP3Result::POP3List { - emails_metadata: metadata - }); - } - - fn parse_list_one(&mut self) { - let caps = STAT_REGEX.captures(&self.lines[0]).unwrap(); - let message_id = FromStr::from_str(caps.get(1).unwrap().as_str()); - let message_size = FromStr::from_str(caps.get(2).unwrap().as_str()); - self.result = Some(POP3Result::POP3List { - emails_metadata: vec![POP3EmailMetadata{ message_id: message_id.unwrap(), message_size: message_size.unwrap()}] - }); - } - - fn parse_message(&mut self) { - let mut raw = Vec::new(); - for i in 1 .. self.lines.len()-1 { - raw.push(self.lines[i].clone()); - } - self.result = Some(POP3Result::POP3Message{ - raw: raw - }); - } + fn parse_list_all(&mut self) { + let mut metadata = Vec::new(); + + for i in 1..self.lines.len() - 1 { + let caps = MESSAGE_DATA_LIST_ALL_REGEX + .captures(&self.lines[i]) + .unwrap(); + let message_id = FromStr::from_str(caps.get(1).unwrap().as_str()); + let message_size = FromStr::from_str(caps.get(2).unwrap().as_str()); + metadata.push(POP3EmailMetadata { + message_id: message_id.unwrap(), + message_size: message_size.unwrap(), + }); + } + self.result = Some(POP3Result::POP3List { + emails_metadata: metadata, + }); + } + + fn parse_list_one(&mut self) { + let caps = STAT_REGEX.captures(&self.lines[0]).unwrap(); + let message_id = FromStr::from_str(caps.get(1).unwrap().as_str()); + let message_size = FromStr::from_str(caps.get(2).unwrap().as_str()); + self.result = Some(POP3Result::POP3List { + emails_metadata: vec![POP3EmailMetadata { + message_id: message_id.unwrap(), + message_size: message_size.unwrap(), + }], + }); + } + + fn parse_message(&mut self) { + let mut raw = Vec::new(); + for i in 1..self.lines.len() - 1 { + raw.push(self.lines[i].clone()); + } + self.result = Some(POP3Result::POP3Message { raw: raw }); + } } From 2f1eded509541607ad54f1b8265b3b09e4740b85 Mon Sep 17 00:00:00 2001 From: K8sCat Date: Mon, 15 Nov 2021 02:05:40 +0800 Subject: [PATCH 2/9] fix: ParseIntError --- .travis.yml | 27 --------------------------- Cargo.toml | 2 +- LICENSE | 2 +- README.md | 37 +++++++++++++++++++++---------------- src/pop3.rs | 4 ++-- 5 files changed, 25 insertions(+), 47 deletions(-) delete mode 100644 .travis.yml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 0c1a3822..00000000 --- a/.travis.yml +++ /dev/null @@ -1,27 +0,0 @@ -sudo: false -language: rust - -addons: - apt: - packages: - - libssl-dev - -rust: -- stable -- beta -- nightly - -matrix: - allow_failures: - - rust: nightly - -script: -- | - cargo build && - cargo test - -after_success: -- if [[ "$TRAVIS_OS_NAME" == "linux" && "$TRAVIS_RUST_VERSION" == "stable" ]]; then - bash <(curl https://raw.githubusercontent.com/xd009642/tarpaulin/master/travis-install.sh); - cargo tarpaulin --ciserver travis-ci --coveralls $TRAVIS_JOB_ID; - fi diff --git a/Cargo.toml b/Cargo.toml index e2b08130..cca9c589 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rs-pop3" version = "1.0.7" -authors = ["Matt McCoy "] +authors = ["Matt McCoy ", "K8sCat "] homepage = "https://github.com/k8scat/rust-pop3" repository = "https://github.com/k8scat/rust-pop3" description = "POP3 client for Rust" diff --git a/LICENSE b/LICENSE index 1904755e..dcb7902c 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2014 Matt McCoy +Copyright (c) 2014 Matt McCoy, K8sCat Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/README.md b/README.md index 961eacc7..76c957c5 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,4 @@ -rust-pop3 -================ +# rust-pop3 **Forked https://github.com/mattnenterprise/rust-pop3** @@ -8,17 +7,23 @@ POP3 Client for Rust This client has SSL support. SSL is configured using an SSLContext that is passed into the connect method of a POP3Stream. If no SSL support is wanted just pass in None. The library rust-openssl is used to support SSL for this project. -[![Number of Crate Downloads](https://img.shields.io/crates/d/pop3.svg)](https://crates.io/crates/pop3) -[![Crate Version](https://img.shields.io/crates/v/pop3.svg)](https://crates.io/crates/pop3) -[![Crate License](https://img.shields.io/crates/l/pop3.svg)](https://crates.io/crates/pop3) -[![Travis CI Build Status](https://travis-ci.org/mattnenterprise/rust-pop3.svg)](https://travis-ci.org/mattnenterprise/rust-pop3) -[![Coverage Status](https://coveralls.io/repos/github/mattnenterprise/rust-pop3/badge.svg?branch=master)](https://coveralls.io/github/mattnenterprise/rust-pop3?branch=master) +[![Number of Crate Downloads](https://img.shields.io/crates/d/rs-pop3.svg)](https://crates.io/crates/rs-pop3) +[![Crate Version](https://img.shields.io/crates/v/rs-pop3.svg)](https://crates.io/crates/rs-pop3) +[![Crate License](https://img.shields.io/crates/l/rs-pop3.svg)](https://crates.io/crates/rs-pop3) +[![Coverage Status](https://coveralls.io/repos/github/k8scat/rust-pop3/badge.svg?branch=master)](https://coveralls.io/github/k8scat/rust-pop3?branch=master) -[Documentation](https://docs.rs/pop3/) +[Documentation](https://docs.rs/rs_pop3/) + +## Usage + +```toml +[dependencies] +rs-pop3 = "1.0.7" +openssl = "0.10" +``` -### Usage ```rust -extern crate pop3; +extern crate rs_pop3; extern crate openssl; use openssl::ssl::{SslConnector, SslMethod}; @@ -26,7 +31,7 @@ use pop3::POP3Stream; use pop3::POP3Result::{POP3Stat, POP3List, POP3Message, POP3Err}; fn main() { - let mut gmail_socket = match POP3Stream::connect(("pop.gmail.com", 995), Some(SslConnector::builder(SslMethod::tls()).unwrap().build()),"pop.gmail.com") { + let mut gmail_socket = match POP3Stream::connect(("pop.gmail.com", 995), Some(SslConnector::builder(SslMethod::tls()).unwrap().build()),"pop.gmail.com") { Ok(s) => s, Err(e) => panic!("{}", e) }; @@ -39,9 +44,9 @@ fn main() { let stat = gmail_socket.stat(); match stat { - POP3Stat {num_email, - mailbox_size} => println!("num_email: {}, mailbox_size:{}", num_email, mailbox_size), - _ => println!("Err for stat"), + POP3Stat {num_email, + mailbox_size} => println!("num_email: {}, mailbox_size:{}", num_email, mailbox_size), + _ => println!("Err for stat"), } let list_all = gmail_socket.list(None); @@ -68,6 +73,6 @@ fn main() { } ``` -### License +## License -MIT +[MIT](https://github.com/k8scat/rust-pop3/blob/master/LICENSE) diff --git a/src/pop3.rs b/src/pop3.rs index 1070d075..0dfa080f 100644 --- a/src/pop3.rs +++ b/src/pop3.rs @@ -369,7 +369,7 @@ pub enum POP3Result { POP3Err, POP3Stat { num_email: i32, - mailbox_size: i32, + mailbox_size: i64, }, POP3Uidl { emails_metadata: Vec, @@ -457,7 +457,7 @@ impl POP3Response { fn parse_stat(&mut self) { let caps = STAT_REGEX.captures(&self.lines[0]).unwrap(); let num_emails = FromStr::from_str(caps.get(1).unwrap().as_str()); - let total_email_size = FromStr::from_str(caps.get(2).unwrap().as_str()); + let total_email_size = caps.get(2).unwrap().as_str().parse::(); self.result = Some(POP3Result::POP3Stat { num_email: num_emails.unwrap(), mailbox_size: total_email_size.unwrap(), From 82c2853294a2ea6ffffb9547f42ca43131058c25 Mon Sep 17 00:00:00 2001 From: K8sCat Date: Mon, 15 Nov 2021 02:14:34 +0800 Subject: [PATCH 3/9] update: release 1.0.8 --- Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.toml b/Cargo.toml index cca9c589..372399b5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rs-pop3" -version = "1.0.7" +version = "1.0.8" authors = ["Matt McCoy ", "K8sCat "] homepage = "https://github.com/k8scat/rust-pop3" repository = "https://github.com/k8scat/rust-pop3" From a800db5b15a6e7aed96601f428e51d3a47575ecc Mon Sep 17 00:00:00 2001 From: caret Date: Sun, 18 Dec 2022 16:00:47 -0600 Subject: [PATCH 4/9] addressed #13 --- Cargo.toml | 13 ++++++++----- examples/README.md | 7 +++++++ example.rs => examples/gmail.rs | 3 --- 3 files changed, 15 insertions(+), 8 deletions(-) create mode 100644 examples/README.md rename example.rs => examples/gmail.rs (96%) diff --git a/Cargo.toml b/Cargo.toml index 372399b5..4f54b0a8 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [package] name = "rs-pop3" -version = "1.0.8" -authors = ["Matt McCoy ", "K8sCat "] +version = "2.0.8" +authors = ["Matt McCoy ", "K8sCat ", "caret "] homepage = "https://github.com/k8scat/rust-pop3" repository = "https://github.com/k8scat/rust-pop3" description = "POP3 client for Rust" @@ -13,6 +13,9 @@ name = "rs_pop3" path = "src/pop3.rs" [dependencies] -openssl = "0.10" -regex = "1" -lazy_static = "1" +lazy_static = "1.4.0" +openssl = "0.10.44" +regex = "1.7.0" +#openssl = "0.10" +#regex = "1" +#lazy_static = "1" diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..544e556b --- /dev/null +++ b/examples/README.md @@ -0,0 +1,7 @@ +Examples +======== + +This directory contains examples of working with the POP3 client. + +Examples: + * gmail - This is a very basic example of using the client. diff --git a/example.rs b/examples/gmail.rs similarity index 96% rename from example.rs rename to examples/gmail.rs index 9d551498..968ca964 100644 --- a/example.rs +++ b/examples/gmail.rs @@ -1,6 +1,3 @@ -extern crate pop3; -extern crate openssl; - use openssl::ssl::{SslConnector, SslMethod}; use pop3::POP3Stream; use pop3::POP3Result::{POP3Stat, POP3List, POP3Message, POP3Err}; From fae299e02ca1ff4c8716794374ae89c9bb074163 Mon Sep 17 00:00:00 2001 From: caret Date: Sun, 18 Dec 2022 16:08:42 -0600 Subject: [PATCH 5/9] updated for edition 2021 --- Cargo.toml | 1 + examples/README.md | 3 +++ examples/gmail.rs | 4 ++-- src/pop3.rs | 3 --- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 4f54b0a8..ea91d7ef 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "rs-pop3" version = "2.0.8" +edition = "2021" authors = ["Matt McCoy ", "K8sCat ", "caret "] homepage = "https://github.com/k8scat/rust-pop3" repository = "https://github.com/k8scat/rust-pop3" diff --git a/examples/README.md b/examples/README.md index 544e556b..97a15bed 100644 --- a/examples/README.md +++ b/examples/README.md @@ -5,3 +5,6 @@ This directory contains examples of working with the POP3 client. Examples: * gmail - This is a very basic example of using the client. + +How to run: +`cargo run --example gmail` diff --git a/examples/gmail.rs b/examples/gmail.rs index 968ca964..25a5c301 100644 --- a/examples/gmail.rs +++ b/examples/gmail.rs @@ -1,6 +1,6 @@ use openssl::ssl::{SslConnector, SslMethod}; -use pop3::POP3Stream; -use pop3::POP3Result::{POP3Stat, POP3List, POP3Message, POP3Err}; +use rs_pop3::POP3Stream; +use rs_pop3::POP3Result::{POP3Stat, POP3List, POP3Message, POP3Err}; fn main() { let mut gmail_socket = match POP3Stream::connect(("pop.gmail.com", 995), Some(SslConnector::builder(SslMethod::tls()).unwrap().build()),"pop.gmail.com") { diff --git a/src/pop3.rs b/src/pop3.rs index 0dfa080f..700431d8 100644 --- a/src/pop3.rs +++ b/src/pop3.rs @@ -1,9 +1,6 @@ #![crate_name = "rs_pop3"] #![crate_type = "lib"] -extern crate openssl; -extern crate regex; - #[macro_use] extern crate lazy_static; From e9735b64ce2ac2712ed3255ac461ff7747ffe2e1 Mon Sep 17 00:00:00 2001 From: caret Date: Sun, 18 Dec 2022 18:28:25 -0600 Subject: [PATCH 6/9] addressed #16 --- Cargo.toml | 6 +++--- examples/gmail.rs | 3 ++- src/pop3.rs | 12 +++++++----- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index ea91d7ef..1c52d9d5 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,8 +1,8 @@ [package] name = "rs-pop3" -version = "2.0.8" +version = "1.0.9" edition = "2021" -authors = ["Matt McCoy ", "K8sCat ", "caret "] +authors = ["Matt McCoy ", "K8sCat ", "caret"] homepage = "https://github.com/k8scat/rust-pop3" repository = "https://github.com/k8scat/rust-pop3" description = "POP3 client for Rust" @@ -15,7 +15,7 @@ path = "src/pop3.rs" [dependencies] lazy_static = "1.4.0" -openssl = "0.10.44" +native-tls = "0.2.11" regex = "1.7.0" #openssl = "0.10" #regex = "1" diff --git a/examples/gmail.rs b/examples/gmail.rs index 25a5c301..07dab630 100644 --- a/examples/gmail.rs +++ b/examples/gmail.rs @@ -1,4 +1,5 @@ -use openssl::ssl::{SslConnector, SslMethod}; +//use openssl::ssl::{SslConnector, SslMethod}; +use native_tls::{TlsConnector,TlsStream}; use rs_pop3::POP3Stream; use rs_pop3::POP3Result::{POP3Stat, POP3List, POP3Message, POP3Err}; diff --git a/src/pop3.rs b/src/pop3.rs index 700431d8..75faa649 100644 --- a/src/pop3.rs +++ b/src/pop3.rs @@ -4,7 +4,8 @@ #[macro_use] extern crate lazy_static; -use openssl::ssl::{SslConnector, SslStream}; +// use openssl::ssl::{SslConnector, SslStream}; +use native_tls::{TlsConnector,TlsStream}; use regex::Regex; use std::io::prelude::*; use std::io::{Error, ErrorKind, Result}; @@ -33,7 +34,7 @@ lazy_static! { #[derive(Debug)] enum POP3StreamTypes { Basic(TcpStream), - Ssl(SslStream), + Ssl(TlsStream), } /// The stream to use for interfacing with the POP3 Server. @@ -65,13 +66,14 @@ impl POP3Stream { /// Creates a new POP3Stream. pub fn connect( addr: A, - ssl_context: Option, + ssl_context: Option, domain: &str, ) -> Result { let tcp_stream = TcpStream::connect(addr)?; let mut socket = match ssl_context { - Some(context) => POP3Stream { - stream: Ssl(SslConnector::connect(&context, domain, tcp_stream).unwrap()), + Some(_context) => POP3Stream { + // stream: Ssl(SslConnector::connect(&context, domain, tcp_stream).unwrap()), + stream: Ssl(TlsConnector::new().unwrap().connect(domain, tcp_stream).unwrap()), is_authenticated: false, }, None => POP3Stream { From 07b881da5a2ec6d58ac39f4ed8133cfcdd47030d Mon Sep 17 00:00:00 2001 From: caret Date: Sun, 18 Dec 2022 21:15:26 -0600 Subject: [PATCH 7/9] updated example --- README.md | 4 ++-- examples/gmail.rs | 5 +++-- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 76c957c5..d4e06d61 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ POP3 Client for Rust This client has SSL support. SSL is configured using an SSLContext that is passed into the connect method of a POP3Stream. If no SSL -support is wanted just pass in None. The library rust-openssl is used to support SSL for this project. +support is wanted just pass in None. The library was updated to use native-tls to support SSL connectivity for this project. [![Number of Crate Downloads](https://img.shields.io/crates/d/rs-pop3.svg)](https://crates.io/crates/rs-pop3) [![Crate Version](https://img.shields.io/crates/v/rs-pop3.svg)](https://crates.io/crates/rs-pop3) @@ -18,8 +18,8 @@ support is wanted just pass in None. The library rust-openssl is used to support ```toml [dependencies] +native-tls = "0.2.11" rs-pop3 = "1.0.7" -openssl = "0.10" ``` ```rust diff --git a/examples/gmail.rs b/examples/gmail.rs index 07dab630..2efa76a5 100644 --- a/examples/gmail.rs +++ b/examples/gmail.rs @@ -1,10 +1,11 @@ //use openssl::ssl::{SslConnector, SslMethod}; -use native_tls::{TlsConnector,TlsStream}; +use native_tls::{TlsConnector,TlsStream,TlsConnectorBuilder}; use rs_pop3::POP3Stream; use rs_pop3::POP3Result::{POP3Stat, POP3List, POP3Message, POP3Err}; fn main() { - let mut gmail_socket = match POP3Stream::connect(("pop.gmail.com", 995), Some(SslConnector::builder(SslMethod::tls()).unwrap().build()),"pop.gmail.com") { + // let mut gmail_socket = match POP3Stream::connect(("pop.gmail.com", 995), Some(SslConnector::builder(SslMethod::tls()).unwrap().build()),"pop.gmail.com") { + let mut gmail_socket = match POP3Stream::connect(("pop.gmail.com", 995), Some(TlsConnector::new().unwrap()),"pop.gmail.com") { Ok(s) => s, Err(e) => panic!("{}", e) }; From f4c3fe61b3b6e56161aa2c456be4231811a8128f Mon Sep 17 00:00:00 2001 From: caret Date: Sun, 18 Dec 2022 21:20:04 -0600 Subject: [PATCH 8/9] Updated --- README.md | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index d4e06d61..71f2cbdb 100644 --- a/README.md +++ b/README.md @@ -16,22 +16,23 @@ support is wanted just pass in None. The library was updated to use native-tls t ## Usage +`Cargo.toml` + ```toml [dependencies] native-tls = "0.2.11" -rs-pop3 = "1.0.7" +rs-pop3 = "1.0.8" ``` -```rust -extern crate rs_pop3; -extern crate openssl; +`main.rs` -use openssl::ssl::{SslConnector, SslMethod}; -use pop3::POP3Stream; -use pop3::POP3Result::{POP3Stat, POP3List, POP3Message, POP3Err}; +```rust +use native_tls::{TlsConnector,TlsStream,TlsConnectorBuilder}; +use rs_pop3::POP3Stream; +use rs_pop3::POP3Result::{POP3Stat, POP3List, POP3Message, POP3Err}; fn main() { - let mut gmail_socket = match POP3Stream::connect(("pop.gmail.com", 995), Some(SslConnector::builder(SslMethod::tls()).unwrap().build()),"pop.gmail.com") { + let mut gmail_socket = match POP3Stream::connect(("pop.gmail.com", 995), Some(TlsConnector::new().unwrap()),"pop.gmail.com") { Ok(s) => s, Err(e) => panic!("{}", e) }; From d31f9523337463da8769f0cc1184a76afbaf81b9 Mon Sep 17 00:00:00 2001 From: caret Date: Sun, 18 Dec 2022 21:25:27 -0600 Subject: [PATCH 9/9] Removed un-used import --- README.md | 2 +- examples/gmail.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 71f2cbdb..337e8bbe 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ rs-pop3 = "1.0.8" `main.rs` ```rust -use native_tls::{TlsConnector,TlsStream,TlsConnectorBuilder}; +use native_tls::TlsConnector; use rs_pop3::POP3Stream; use rs_pop3::POP3Result::{POP3Stat, POP3List, POP3Message, POP3Err}; diff --git a/examples/gmail.rs b/examples/gmail.rs index 2efa76a5..025827ec 100644 --- a/examples/gmail.rs +++ b/examples/gmail.rs @@ -1,5 +1,4 @@ -//use openssl::ssl::{SslConnector, SslMethod}; -use native_tls::{TlsConnector,TlsStream,TlsConnectorBuilder}; +use native_tls::TlsConnector; use rs_pop3::POP3Stream; use rs_pop3::POP3Result::{POP3Stat, POP3List, POP3Message, POP3Err};