imap_client/tasks/tasks/
login.rs

1use imap_next::imap_types::{
2    command::CommandBody,
3    core::{AString, Vec1},
4    response::{Capability, Code, Data, StatusBody, StatusKind},
5    secret::Secret,
6};
7
8use super::TaskError;
9use crate::tasks::Task;
10
11#[derive(Clone, Debug)]
12pub struct LoginTask {
13    username: AString<'static>,
14    password: Secret<AString<'static>>,
15    output: Option<Vec1<Capability<'static>>>,
16}
17
18impl LoginTask {
19    pub fn new(username: AString<'static>, password: Secret<AString<'static>>) -> Self {
20        Self {
21            username,
22            password,
23            output: None,
24        }
25    }
26}
27
28impl Task for LoginTask {
29    type Output = Result<Option<Vec1<Capability<'static>>>, TaskError>;
30
31    fn command_body(&self) -> CommandBody<'static> {
32        CommandBody::Login {
33            username: self.username.clone(),
34            password: self.password.clone(),
35        }
36    }
37
38    // Capabilities may (unfortunately) be found in a data response.
39    // See https://github.com/modern-email/defects/issues/18
40    fn process_data(&mut self, data: Data<'static>) -> Option<Data<'static>> {
41        if let Data::Capability(capabilities) = data {
42            self.output = Some(capabilities);
43            None
44        } else {
45            Some(data)
46        }
47    }
48
49    fn process_tagged(self, status_body: StatusBody<'static>) -> Self::Output {
50        match status_body.kind {
51            StatusKind::Ok => Ok(
52                if let Some(Code::Capability(capabilities)) = status_body.code {
53                    Some(capabilities)
54                } else {
55                    self.output
56                },
57            ),
58            StatusKind::No => Err(TaskError::UnexpectedNoResponse(status_body)),
59            StatusKind::Bad => Err(TaskError::UnexpectedBadResponse(status_body)),
60        }
61    }
62}