imap: add support for imaps connections
Take port value and a `use_starttls` flag from the configuration file.embed
parent
9563007069
commit
ee82ae175a
|
@ -55,15 +55,22 @@ pub struct EnvelopeCache {
|
|||
flags: Option<Flag>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ImapServerConf {
|
||||
pub server_hostname: String,
|
||||
pub server_username: String,
|
||||
pub server_password: String,
|
||||
pub server_port: u16,
|
||||
pub use_starttls: bool,
|
||||
pub danger_accept_invalid_certs: bool,
|
||||
}
|
||||
|
||||
type Capabilities = FnvHashSet<Vec<u8>>;
|
||||
#[derive(Debug)]
|
||||
pub struct ImapType {
|
||||
account_name: String,
|
||||
server_hostname: String,
|
||||
server_username: String,
|
||||
server_password: String,
|
||||
danger_accept_invalid_certs: bool,
|
||||
connection: Arc<Mutex<ImapConnection>>,
|
||||
server_conf: ImapServerConf,
|
||||
|
||||
folders: FnvHashMap<FolderHash, ImapFolder>,
|
||||
hash_index: Arc<Mutex<FnvHashMap<EnvelopeHash, (UID, FolderHash)>>>,
|
||||
|
@ -180,12 +187,7 @@ impl MailBackend for ImapType {
|
|||
.capabilities
|
||||
.contains(&b"IDLE"[0..]);
|
||||
let folders = self.folders.clone();
|
||||
let conn = ImapConnection::new_connection(
|
||||
self.server_hostname.clone(),
|
||||
self.server_username.clone(),
|
||||
self.server_password.clone(),
|
||||
self.danger_accept_invalid_certs,
|
||||
);
|
||||
let conn = ImapConnection::new_connection(&self.server_conf);
|
||||
let main_conn = self.connection.clone();
|
||||
let hash_index = self.hash_index.clone();
|
||||
let uid_index = self.uid_index.clone();
|
||||
|
@ -394,23 +396,32 @@ impl ImapType {
|
|||
let server_hostname = get_conf_val!(s["server_hostname"]);
|
||||
let server_username = get_conf_val!(s["server_username"]);
|
||||
let server_password = get_conf_val!(s["server_password"]);
|
||||
let server_port = get_conf_val!(s["server_port"], 143);
|
||||
let use_starttls = get_conf_val!(s["use_starttls"], {
|
||||
if server_port == 993 {
|
||||
false
|
||||
} else {
|
||||
true
|
||||
}
|
||||
});
|
||||
let danger_accept_invalid_certs: bool =
|
||||
get_conf_val!(s["danger_accept_invalid_certs"], false);
|
||||
let connection = ImapConnection::new_connection(
|
||||
server_hostname.to_string(),
|
||||
server_username.to_string(),
|
||||
server_password.to_string(),
|
||||
let server_conf = ImapServerConf {
|
||||
server_hostname: server_hostname.to_string(),
|
||||
server_username: server_username.to_string(),
|
||||
server_password: server_password.to_string(),
|
||||
server_port,
|
||||
use_starttls,
|
||||
danger_accept_invalid_certs,
|
||||
);
|
||||
};
|
||||
let connection = ImapConnection::new_connection(&server_conf);
|
||||
|
||||
let mut m = ImapType {
|
||||
account_name: s.name().to_string(),
|
||||
server_hostname: get_conf_val!(s["server_hostname"]).to_string(),
|
||||
server_username: get_conf_val!(s["server_username"]).to_string(),
|
||||
server_password: get_conf_val!(s["server_password"]).to_string(),
|
||||
server_conf,
|
||||
|
||||
folders: Default::default(),
|
||||
connection: Arc::new(Mutex::new(connection)),
|
||||
danger_accept_invalid_certs,
|
||||
hash_index: Default::default(),
|
||||
uid_index: Default::default(),
|
||||
byte_cache: Default::default(),
|
||||
|
@ -430,12 +441,7 @@ impl ImapType {
|
|||
}
|
||||
|
||||
pub fn shell(&mut self) {
|
||||
let mut conn = ImapConnection::new_connection(
|
||||
self.server_hostname.clone(),
|
||||
self.server_username.clone(),
|
||||
self.server_password.clone(),
|
||||
self.danger_accept_invalid_certs,
|
||||
);
|
||||
let mut conn = ImapConnection::new_connection(&self.server_conf);
|
||||
let mut res = String::with_capacity(8 * 1024);
|
||||
conn.read_response(&mut res).unwrap();
|
||||
debug!("out: {}", &res);
|
||||
|
|
|
@ -30,7 +30,7 @@ use std::iter::FromIterator;
|
|||
use std::net::SocketAddr;
|
||||
|
||||
use super::protocol_parser;
|
||||
use super::Capabilities;
|
||||
use super::{Capabilities, ImapServerConf};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ImapStream {
|
||||
|
@ -41,10 +41,7 @@ pub struct ImapStream {
|
|||
#[derive(Debug)]
|
||||
pub struct ImapConnection {
|
||||
pub stream: Result<ImapStream>,
|
||||
server_hostname: String,
|
||||
server_username: String,
|
||||
server_password: String,
|
||||
danger_accept_invalid_certs: bool,
|
||||
pub server_conf: ImapServerConf,
|
||||
pub capabilities: Capabilities,
|
||||
}
|
||||
|
||||
|
@ -145,23 +142,18 @@ impl ImapStream {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn new_connection(
|
||||
server_hostname: &str,
|
||||
server_username: &str,
|
||||
server_password: &str,
|
||||
danger_accept_invalid_certs: bool,
|
||||
) -> Result<(Capabilities, ImapStream)> {
|
||||
pub fn new_connection(server_conf: &ImapServerConf) -> Result<(Capabilities, ImapStream)> {
|
||||
use std::io::prelude::*;
|
||||
use std::net::TcpStream;
|
||||
let path = &server_hostname;
|
||||
let path = &server_conf.server_hostname;
|
||||
|
||||
let mut connector = TlsConnector::builder();
|
||||
if danger_accept_invalid_certs {
|
||||
if server_conf.danger_accept_invalid_certs {
|
||||
connector.danger_accept_invalid_certs(true);
|
||||
}
|
||||
let connector = connector.build()?;
|
||||
|
||||
let addr = if let Ok(a) = lookup_ipv4(path, 143) {
|
||||
let addr = if let Ok(a) = lookup_ipv4(path, server_conf.server_port) {
|
||||
a
|
||||
} else {
|
||||
return Err(MeliError::new(format!(
|
||||
|
@ -172,6 +164,7 @@ impl ImapStream {
|
|||
|
||||
let mut socket = TcpStream::connect(&addr)?;
|
||||
let cmd_id = 0;
|
||||
if server_conf.use_starttls {
|
||||
socket.write_all(format!("M{} STARTTLS\r\n", cmd_id).as_bytes())?;
|
||||
|
||||
let mut buf = vec![0; 1024];
|
||||
|
@ -200,6 +193,7 @@ impl ImapStream {
|
|||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
socket
|
||||
.set_nonblocking(true)
|
||||
|
@ -228,7 +222,11 @@ impl ImapStream {
|
|||
};
|
||||
let mut ret = ImapStream { cmd_id, stream };
|
||||
ret.send_command(
|
||||
format!("LOGIN \"{}\" \"{}\"", &server_username, &server_password).as_bytes(),
|
||||
format!(
|
||||
"LOGIN \"{}\" \"{}\"",
|
||||
&server_conf.server_username, &server_conf.server_password
|
||||
)
|
||||
.as_bytes(),
|
||||
)?;
|
||||
let mut res = String::with_capacity(8 * 1024);
|
||||
ret.read_lines(&mut res, String::new())?;
|
||||
|
@ -240,18 +238,10 @@ impl ImapStream {
|
|||
}
|
||||
|
||||
impl ImapConnection {
|
||||
pub fn new_connection(
|
||||
server_hostname: String,
|
||||
server_username: String,
|
||||
server_password: String,
|
||||
danger_accept_invalid_certs: bool,
|
||||
) -> ImapConnection {
|
||||
pub fn new_connection(server_conf: &ImapServerConf) -> ImapConnection {
|
||||
ImapConnection {
|
||||
stream: Err(MeliError::new("Offline".to_string())),
|
||||
server_hostname,
|
||||
server_username,
|
||||
server_password,
|
||||
danger_accept_invalid_certs,
|
||||
server_conf: server_conf.clone(),
|
||||
capabilities: Capabilities::default(),
|
||||
}
|
||||
}
|
||||
|
@ -260,12 +250,7 @@ impl ImapConnection {
|
|||
if let Ok(ref mut stream) = self.stream {
|
||||
return stream.read_response(ret);
|
||||
}
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(
|
||||
&self.server_hostname,
|
||||
&self.server_username,
|
||||
&self.server_password,
|
||||
self.danger_accept_invalid_certs,
|
||||
)?;
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?;
|
||||
let ret = stream.read_response(ret);
|
||||
if ret.is_ok() {
|
||||
self.stream = Ok(stream);
|
||||
|
@ -278,12 +263,7 @@ impl ImapConnection {
|
|||
if let Ok(ref mut stream) = self.stream {
|
||||
return stream.read_lines(ret, termination_string);
|
||||
}
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(
|
||||
&self.server_hostname,
|
||||
&self.server_username,
|
||||
&self.server_password,
|
||||
self.danger_accept_invalid_certs,
|
||||
)?;
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?;
|
||||
let ret = stream.read_lines(ret, termination_string);
|
||||
if ret.is_ok() {
|
||||
self.stream = Ok(stream);
|
||||
|
@ -296,12 +276,7 @@ impl ImapConnection {
|
|||
if let Ok(ref mut stream) = self.stream {
|
||||
return stream.wait_for_continuation_request();
|
||||
}
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(
|
||||
&self.server_hostname,
|
||||
&self.server_username,
|
||||
&self.server_password,
|
||||
self.danger_accept_invalid_certs,
|
||||
)?;
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?;
|
||||
let ret = stream.wait_for_continuation_request();
|
||||
if ret.is_ok() {
|
||||
self.stream = Ok(stream);
|
||||
|
@ -314,12 +289,7 @@ impl ImapConnection {
|
|||
if let Ok(ref mut stream) = self.stream {
|
||||
return stream.send_command(command);
|
||||
}
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(
|
||||
&self.server_hostname,
|
||||
&self.server_username,
|
||||
&self.server_password,
|
||||
self.danger_accept_invalid_certs,
|
||||
)?;
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?;
|
||||
let ret = stream.send_command(command);
|
||||
if ret.is_ok() {
|
||||
self.stream = Ok(stream);
|
||||
|
@ -332,12 +302,7 @@ impl ImapConnection {
|
|||
if let Ok(ref mut stream) = self.stream {
|
||||
return stream.send_literal(data);
|
||||
}
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(
|
||||
&self.server_hostname,
|
||||
&self.server_username,
|
||||
&self.server_password,
|
||||
self.danger_accept_invalid_certs,
|
||||
)?;
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?;
|
||||
let ret = stream.send_literal(data);
|
||||
if ret.is_ok() {
|
||||
self.stream = Ok(stream);
|
||||
|
@ -350,12 +315,7 @@ impl ImapConnection {
|
|||
if let Ok(ref mut stream) = self.stream {
|
||||
return stream.send_raw(raw);
|
||||
}
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(
|
||||
&self.server_hostname,
|
||||
&self.server_username,
|
||||
&self.server_password,
|
||||
self.danger_accept_invalid_certs,
|
||||
)?;
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?;
|
||||
|
||||
let ret = stream.send_raw(raw);
|
||||
if ret.is_ok() {
|
||||
|
@ -369,12 +329,7 @@ impl ImapConnection {
|
|||
if let Ok(ref mut stream) = self.stream {
|
||||
return stream.set_nonblocking(val);
|
||||
}
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(
|
||||
&self.server_hostname,
|
||||
&self.server_username,
|
||||
&self.server_password,
|
||||
self.danger_accept_invalid_certs,
|
||||
)?;
|
||||
let (capabilities, mut stream) = ImapStream::new_connection(&self.server_conf)?;
|
||||
let ret = stream.set_nonblocking(val);
|
||||
if ret.is_ok() {
|
||||
self.stream = Ok(stream);
|
||||
|
@ -423,12 +378,7 @@ impl Iterator for ImapBlockingConnection {
|
|||
} = self;
|
||||
loop {
|
||||
if conn.stream.is_err() {
|
||||
if let Ok((_, stream)) = ImapStream::new_connection(
|
||||
&conn.server_hostname,
|
||||
&conn.server_username,
|
||||
&conn.server_password,
|
||||
conn.danger_accept_invalid_certs,
|
||||
) {
|
||||
if let Ok((_, stream)) = ImapStream::new_connection(&conn.server_conf) {
|
||||
conn.stream = Ok(stream);
|
||||
} else {
|
||||
debug!(&conn.stream);
|
||||
|
|
Loading…
Reference in New Issue