imap: use anyhow for error handling

This commit is contained in:
link2xt
2021-08-29 14:10:04 +00:00
parent 71e0493c4a
commit 9dedcad220
2 changed files with 29 additions and 60 deletions

View File

@@ -6,9 +6,8 @@
use std::{cmp, cmp::max, collections::BTreeMap}; use std::{cmp, cmp::max, collections::BTreeMap};
use anyhow::{anyhow, bail, format_err, Context as _, Result}; use anyhow::{anyhow, bail, format_err, Context as _, Result};
use async_imap::{ use async_imap::types::{
error::Result as ImapResult, Fetch, Flag, Mailbox, Name, NameAttribute, Quota, QuotaRoot, UnsolicitedResponse,
types::{Fetch, Flag, Mailbox, Name, NameAttribute, Quota, QuotaRoot, UnsolicitedResponse},
}; };
use async_std::channel::Receiver; use async_std::channel::Receiver;
use async_std::prelude::*; use async_std::prelude::*;
@@ -259,7 +258,7 @@ impl Imap {
let oauth2 = self.config.oauth2; let oauth2 = self.config.oauth2;
let connection_res: ImapResult<Client> = if self.config.lp.security == Socket::Starttls let connection_res: Result<Client> = if self.config.lp.security == Socket::Starttls
|| self.config.lp.security == Socket::Plain || self.config.lp.security == Socket::Plain
{ {
let config = &mut self.config; let config = &mut self.config;
@@ -354,7 +353,7 @@ impl Imap {
Ok(()) Ok(())
} }
Err((err, _)) => { Err(err) => {
let imap_user = self.config.lp.user.to_owned(); let imap_user = self.config.lp.user.to_owned();
let message = stock_str::cannot_login(context, &imap_user).await; let message = stock_str::cannot_login(context, &imap_user).await;

View File

@@ -3,10 +3,9 @@ use std::{
time::Duration, time::Duration,
}; };
use async_imap::{ use anyhow::{Context as _, Result};
error::{Error as ImapError, Result as ImapResult},
Client as ImapClient, use async_imap::Client as ImapClient;
};
use async_smtp::ServerAddress; use async_smtp::ServerAddress;
use async_std::net::{self, TcpStream}; use async_std::net::{self, TcpStream};
@@ -40,24 +39,12 @@ impl DerefMut for Client {
} }
impl Client { impl Client {
pub async fn login( pub async fn login(self, username: &str, password: &str) -> Result<Session> {
self, let Client { inner, .. } = self;
username: &str,
password: &str,
) -> std::result::Result<Session, (ImapError, Self)> {
let Client { inner, is_secure } = self;
let session = inner let session = inner
.login(username, password) .login(username, password)
.await .await
.map_err(|(err, client)| { .map_err(|(err, _client)| err)?;
(
err,
Client {
is_secure,
inner: client,
},
)
})?;
Ok(Session { inner: session }) Ok(Session { inner: session })
} }
@@ -65,21 +52,12 @@ impl Client {
self, self,
auth_type: &str, auth_type: &str,
authenticator: impl async_imap::Authenticator, authenticator: impl async_imap::Authenticator,
) -> std::result::Result<Session, (ImapError, Self)> { ) -> Result<Session> {
let Client { inner, is_secure } = self; let Client { inner, .. } = self;
let session = let session = inner
inner
.authenticate(auth_type, authenticator) .authenticate(auth_type, authenticator)
.await .await
.map_err(|(err, client)| { .map_err(|(err, _client)| err)?;
(
err,
Client {
is_secure,
inner: client,
},
)
})?;
Ok(Session { inner: session }) Ok(Session { inner: session })
} }
@@ -87,7 +65,7 @@ impl Client {
addr: impl net::ToSocketAddrs, addr: impl net::ToSocketAddrs,
domain: &str, domain: &str,
strict_tls: bool, strict_tls: bool,
) -> ImapResult<Self> { ) -> Result<Self> {
let stream = TcpStream::connect(addr).await?; let stream = TcpStream::connect(addr).await?;
let tls = dc_build_tls(strict_tls); let tls = dc_build_tls(strict_tls);
let tls_stream: Box<dyn SessionStream> = Box::new(tls.connect(domain, stream).await?); let tls_stream: Box<dyn SessionStream> = Box::new(tls.connect(domain, stream).await?);
@@ -96,7 +74,7 @@ impl Client {
let _greeting = client let _greeting = client
.read_response() .read_response()
.await .await
.ok_or_else(|| ImapError::Bad("failed to read greeting".to_string()))?; .context("failed to read greeting")?;
Ok(Client { Ok(Client {
is_secure: true, is_secure: true,
@@ -104,14 +82,14 @@ impl Client {
}) })
} }
pub async fn connect_insecure(addr: impl net::ToSocketAddrs) -> ImapResult<Self> { pub async fn connect_insecure(addr: impl net::ToSocketAddrs) -> Result<Self> {
let stream: Box<dyn SessionStream> = Box::new(TcpStream::connect(addr).await?); let stream: Box<dyn SessionStream> = Box::new(TcpStream::connect(addr).await?);
let mut client = ImapClient::new(stream); let mut client = ImapClient::new(stream);
let _greeting = client let _greeting = client
.read_response() .read_response()
.await .await
.ok_or_else(|| ImapError::Bad("failed to read greeting".to_string()))?; .context("failed to read greeting")?;
Ok(Client { Ok(Client {
is_secure: false, is_secure: false,
@@ -123,15 +101,11 @@ impl Client {
target_addr: &ServerAddress, target_addr: &ServerAddress,
strict_tls: bool, strict_tls: bool,
socks5_config: Socks5Config, socks5_config: Socks5Config,
) -> ImapResult<Self> { ) -> Result<Self> {
let socks5_stream: Box<dyn SessionStream> = Box::new( let socks5_stream: Box<dyn SessionStream> = Box::new(
match socks5_config socks5_config
.connect(target_addr, Some(Duration::from_secs(IMAP_TIMEOUT))) .connect(target_addr, Some(Duration::from_secs(IMAP_TIMEOUT)))
.await .await?,
{
Ok(s) => s,
Err(e) => return ImapResult::Err(async_imap::error::Error::Bad(e.to_string())),
},
); );
let tls = dc_build_tls(strict_tls); let tls = dc_build_tls(strict_tls);
@@ -142,7 +116,7 @@ impl Client {
let _greeting = client let _greeting = client
.read_response() .read_response()
.await .await
.ok_or_else(|| ImapError::Bad("failed to read greeting".to_string()))?; .context("failed to read greeting")?;
Ok(Client { Ok(Client {
is_secure: true, is_secure: true,
@@ -153,22 +127,18 @@ impl Client {
pub async fn connect_insecure_socks5( pub async fn connect_insecure_socks5(
target_addr: &ServerAddress, target_addr: &ServerAddress,
socks5_config: Socks5Config, socks5_config: Socks5Config,
) -> ImapResult<Self> { ) -> Result<Self> {
let socks5_stream: Box<dyn SessionStream> = Box::new( let socks5_stream: Box<dyn SessionStream> = Box::new(
match socks5_config socks5_config
.connect(target_addr, Some(Duration::from_secs(IMAP_TIMEOUT))) .connect(target_addr, Some(Duration::from_secs(IMAP_TIMEOUT)))
.await .await?,
{
Ok(s) => s,
Err(e) => return ImapResult::Err(async_imap::error::Error::Bad(e.to_string())),
},
); );
let mut client = ImapClient::new(socks5_stream); let mut client = ImapClient::new(socks5_stream);
let _greeting = client let _greeting = client
.read_response() .read_response()
.await .await
.ok_or_else(|| ImapError::Bad("failed to read greeting".to_string()))?; .context("failed to read greeting")?;
Ok(Client { Ok(Client {
is_secure: false, is_secure: false,
@@ -176,7 +146,7 @@ impl Client {
}) })
} }
pub async fn secure(self, domain: &str, strict_tls: bool) -> ImapResult<Client> { pub async fn secure(self, domain: &str, strict_tls: bool) -> Result<Client> {
if self.is_secure { if self.is_secure {
Ok(self) Ok(self)
} else { } else {