Skip to main content

new_tokio_smtp/command/auth/
login.rs

1use base64::encode;
2use futures::future::{self, Either, Future};
3
4use super::validate_auth_capability;
5use crate::{
6    error::{LogicError, MissingCapabilities},
7    future_ext::ResultWithContextExt,
8    Cmd, EhloData, ExecFuture, Io,
9};
10
11/// Simple implementation of AUTH LOGIN for smtp.
12#[derive(Debug, Clone)]
13pub struct Login {
14    username: String,
15    password: String,
16}
17
18impl Login {
19    /// Create a new auth login command based on username and password.
20    pub fn new(username: &str, password: &str) -> Self {
21        Login {
22            username: encode(username),
23            password: encode(password),
24        }
25    }
26
27    /// Create a new auth login command based on base64 encoded username and password.
28    pub fn from_base64(username: String, password: String) -> Self {
29        Login { username, password }
30    }
31
32    /// Returns the username contained in the `Login` command.
33    pub fn base64_username(&self) -> &str {
34        &self.username
35    }
36
37    //intentionally no base64_password!
38}
39
40impl Cmd for Login {
41    fn check_cmd_availability(&self, caps: Option<&EhloData>) -> Result<(), MissingCapabilities> {
42        validate_auth_capability(caps, "LOGIN")
43    }
44
45    fn exec(self, mut io: Io) -> ExecFuture {
46        let Login { username, password } = self;
47
48        io.write_line_from_parts(&["AUTH LOGIN", username.as_str()]);
49
50        let fut = io
51            .flush()
52            .and_then(Io::parse_response)
53            .ctx_and_then(move |io: Io, response| {
54                if !response.code().is_intermediate() {
55                    Either::A(future::ok((io, Err(LogicError::UnexpectedCode(response)))))
56                } else {
57                    let fut = io
58                        .flush_line_from_parts(&[password.as_str()])
59                        .and_then(Io::parse_response);
60
61                    Either::B(fut)
62                }
63            });
64
65        Box::new(fut)
66    }
67}