1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
use std::ops::{Deref, DerefMut};
use std::result;
use crate::connection::{
AsRawFdOrSocket, Async, AsyncConnection, AsyncRead, AsyncWrite, TlsClientUpgrader,
UpgraderExtRefer,
};
use crate::imap::{validate_str, Error};
use crate::session::AsyncSession;
pub struct AsyncClient<AS, ASTU>
where
AS: AsRawFdOrSocket,
Async<AS>: AsyncRead + AsyncWrite,
ASTU: TlsClientUpgrader<Async<AS>> + Unpin,
ASTU::Output: AsyncRead + AsyncWrite + Unpin,
{
conn: AsyncConnection<AS, ASTU>,
}
impl<AS, ASTU> Deref for AsyncClient<AS, ASTU>
where
AS: AsRawFdOrSocket,
Async<AS>: AsyncRead + AsyncWrite,
ASTU: TlsClientUpgrader<Async<AS>> + Unpin,
ASTU::Output: AsyncRead + AsyncWrite + Unpin,
{
type Target = AsyncConnection<AS, ASTU>;
fn deref(&self) -> &AsyncConnection<AS, ASTU> {
&self.conn
}
}
impl<AS, ASTU> DerefMut for AsyncClient<AS, ASTU>
where
AS: AsRawFdOrSocket,
Async<AS>: AsyncRead + AsyncWrite,
ASTU: TlsClientUpgrader<Async<AS>> + Unpin,
ASTU::Output: AsyncRead + AsyncWrite + Unpin,
{
fn deref_mut(&mut self) -> &mut AsyncConnection<AS, ASTU> {
&mut self.conn
}
}
macro_rules! ok_or_unauth_client_err {
($r:expr, $self:expr) => {
match $r {
Ok(o) => o,
Err(e) => return Err((e, $self)),
}
};
}
impl<AS, ASTU> AsyncClient<AS, ASTU>
where
AS: AsRawFdOrSocket,
Async<AS>: AsyncRead + AsyncWrite,
ASTU: TlsClientUpgrader<Async<AS>> + UpgraderExtRefer<Async<AS>> + Unpin,
ASTU::Output: AsyncRead + AsyncWrite + Unpin,
{
pub(crate) fn new(conn: AsyncConnection<AS, ASTU>) -> Self {
Self { conn }
}
pub async fn login<U: AsRef<str>, P: AsRef<str>>(
mut self,
username: U,
password: P,
) -> result::Result<AsyncSession<AS, ASTU>, (Error, Self)> {
let u = ok_or_unauth_client_err!(validate_str(username.as_ref()), self);
let p = ok_or_unauth_client_err!(validate_str(password.as_ref()), self);
ok_or_unauth_client_err!(
self.run_command_and_check_ok(&format!("LOGIN {} {}", u, p))
.await,
self
);
Ok(AsyncSession::new(self.conn))
}
}