mail_send/smtp/
envelope.rs

1/*
2 * Copyright Stalwart Labs Ltd.
3 *
4 * Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5 * https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6 * <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
7 * option. This file may not be copied, modified, or distributed
8 * except according to those terms.
9 */
10
11use tokio::io::{AsyncRead, AsyncWrite, AsyncWriteExt};
12
13use crate::SmtpClient;
14
15use super::{message::Parameters, AssertReply};
16
17impl<T: AsyncRead + AsyncWrite + Unpin> SmtpClient<T> {
18    /// Sends a MAIL FROM command to the server.
19    pub async fn mail_from(&mut self, addr: &str, params: &Parameters<'_>) -> crate::Result<()> {
20        self.cmd(format!("MAIL FROM:<{addr}>{params}\r\n").as_bytes())
21            .await?
22            .assert_positive_completion()
23    }
24
25    /// Sends a RCPT TO command to the server.
26    pub async fn rcpt_to(&mut self, addr: &str, params: &Parameters<'_>) -> crate::Result<()> {
27        self.cmd(format!("RCPT TO:<{addr}>{params}\r\n").as_bytes())
28            .await?
29            .assert_positive_completion()
30    }
31
32    /// Sends a DATA command to the server.
33    pub async fn data(&mut self, message: impl AsRef<[u8]>) -> crate::Result<()> {
34        self.cmd(b"DATA\r\n").await?.assert_code(354)?;
35        tokio::time::timeout(self.timeout, async {
36            // Write message
37            self.write_message(message.as_ref()).await?;
38            self.read().await
39        })
40        .await
41        .map_err(|_| crate::Error::Timeout)??
42        .assert_positive_completion()
43    }
44
45    /// Sends a BDAT command to the server.
46    pub async fn bdat(&mut self, message: impl AsRef<[u8]>) -> crate::Result<()> {
47        let message = message.as_ref();
48        tokio::time::timeout(self.timeout, async {
49            self.stream
50                .write_all(format!("BDAT {} LAST\r\n", message.len()).as_bytes())
51                .await?;
52            self.stream.write_all(message).await?;
53            self.stream.flush().await?;
54            self.read().await
55        })
56        .await
57        .map_err(|_| crate::Error::Timeout)??
58        .assert_positive_completion()
59    }
60
61    /// Sends a RSET command to the server.
62    pub async fn rset(&mut self) -> crate::Result<()> {
63        self.cmd(b"RSET\r\n").await?.assert_positive_completion()
64    }
65
66    /// Sends a NOOP command to the server.
67    pub async fn noop(&mut self) -> crate::Result<()> {
68        self.cmd(b"NOOP\r\n").await?.assert_positive_completion()
69    }
70
71    /// Sends a QUIT command to the server.
72    pub async fn quit(mut self) -> crate::Result<()> {
73        self.cmd(b"QUIT\r\n").await?.assert_positive_completion()
74    }
75}