forked from meli/meli
1
Fork 0

melib/smtp: fix test smtp server logic

duesee/experiment/use_imap_codec
Manos Pitsidianakis 2023-04-26 12:08:15 +03:00
parent d679a74450
commit 39d9c2af3b
Signed by: Manos Pitsidianakis
GPG Key ID: 7729C7707F7E09D0
1 changed files with 114 additions and 115 deletions

View File

@ -22,57 +22,55 @@
#![allow(clippy::just_underscores_and_digits)]
#![allow(clippy::needless_lifetimes)]
/*!
* SMTP client support
*
* This module implements a client for the SMTP protocol as specified by [RFC 5321 Simple Mail
* Transfer Protocol](https://www.rfc-editor.org/rfc/rfc5321).
*
* The connection and methods are `async` and uses the `smol` runtime.
*# Example
*
*```not_run
*extern crate melib;
*
*use melib::futures;
*use melib::smol;
*use melib::smtp::*;
*use melib::Result;
*let conf = SmtpServerConf {
* hostname: "smtp.mail.gr".into(),
* port: 587,
* security: SmtpSecurity::StartTLS {
* danger_accept_invalid_certs: false,
* },
* extensions: SmtpExtensionSupport::default(),
* auth: SmtpAuth::Auto {
* username: "l15".into(),
* password: Password::CommandEval(
* "gpg2 --no-tty -q -d ~/.passwords/mail.gpg".into(),
* ),
* require_auth: true,
* },
*};
*
*std::thread::Builder::new().spawn(move || {
* let ex = smol::Executor::new();
* futures::executor::block_on(ex.run(futures::future::pending::<()>()));
*}).unwrap();
*
*let mut conn = futures::executor::block_on(SmtpConnection::new_connection(conf)).unwrap();
*futures::executor::block_on(conn.mail_transaction(r#"To: l10@mail.gr
*Subject: Fwd: SMTP TEST
*From: Me <l15@mail.gr>
*Message-Id: <E1hSjnr-0003fN-RL@pppppp>
*Date: Mon, 13 Jul 2020 09:02:15 +0300
*
*Prescriptions-R-X"#,
* b"l15@mail.gr",
* b"l10@mail.gr",
*)).unwrap();
*Ok(())
*```
*/
//! SMTP client support
//!
//! This module implements a client for the SMTP protocol as specified by [RFC 5321 Simple Mail
//! Transfer Protocol](https://www.rfc-editor.org/rfc/rfc5321).
//!
//! The connection and methods are `async` and uses the `smol` runtime.
//!# Example
//!
//! ```not_run
//! extern crate melib;
//!
//! use melib::futures;
//! use melib::smol;
//! use melib::smtp::*;
//! use melib::Result;
//! let conf = SmtpServerConf {
//! hostname: "smtp.example.com".into(),
//! port: 587,
//! security: SmtpSecurity::StartTLS {
//! danger_accept_invalid_certs: false,
//! },
//! extensions: SmtpExtensionSupport::default(),
//! auth: SmtpAuth::Auto {
//! username: "l15".into(),
//! password: Password::CommandEval(
//! "gpg2 --no-tty -q -d ~/.passwords/mail.gpg".into(),
//! ),
//! require_auth: true,
//! },
//! };
//!
//! std::thread::Builder::new().spawn(move || {
//! let ex = smol::Executor::new();
//! futures::executor::block_on(ex.run(futures::future::pending::<()>()));
//! }).unwrap();
//!
//! let mut conn = futures::executor::block_on(SmtpConnection::new_connection(conf)).unwrap();
//! futures::executor::block_on(conn.mail_transaction(r#"To: l10@example.com
//! Subject: Fwd: SMTP TEST
//! From: Me <l15@example.com>
//! Message-Id: <E1hSjnr-0003fN-RL@example.com>
//! Date: Mon, 13 Jul 2020 09:02:15 +0300
//!
//! Prescriptions-R-X"#,
//! b"l15@example.com",
//! b"l10@example.com",
//! )).unwrap();
//! Ok(())
//! ```
use crate::connections::{lookup_ipv4, Connection};
use crate::email::{parser::BytesExt, Address, Envelope};
@ -93,17 +91,17 @@ use std::process::Command;
pub enum SmtpSecurity {
#[serde(alias = "starttls", alias = "STARTTLS")]
StartTLS {
#[serde(default = "false_val")]
#[serde(default = "crate::conf::false_val")]
danger_accept_invalid_certs: bool,
},
#[serde(alias = "auto")]
Auto {
#[serde(default = "false_val")]
#[serde(default = "crate::conf::false_val")]
danger_accept_invalid_certs: bool,
},
#[serde(alias = "tls", alias = "TLS")]
Tls {
#[serde(default = "false_val")]
#[serde(default = "crate::conf::false_val")]
danger_accept_invalid_certs: bool,
},
#[serde(alias = "none")]
@ -138,7 +136,7 @@ pub enum SmtpAuth {
Auto {
username: String,
password: Password,
#[serde(default = "true_val")]
#[serde(default = "crate::conf::true_val")]
require_auth: bool,
#[serde(skip_serializing, skip_deserializing, default)]
auth_type: SmtpAuthType,
@ -146,7 +144,7 @@ pub enum SmtpAuth {
#[serde(alias = "xoauth2")]
XOAuth2 {
token_command: String,
#[serde(default = "true_val")]
#[serde(default = "crate::conf::true_val")]
require_auth: bool,
},
// md5, sasl, etc
@ -158,14 +156,6 @@ pub struct SmtpAuthType {
login: bool,
}
const fn true_val() -> bool {
true
}
const fn false_val() -> bool {
false
}
impl SmtpAuth {
fn require_auth(&self) -> bool {
use SmtpAuth::*;
@ -201,17 +191,17 @@ pub struct SmtpExtensionSupport {
/// [RFC 6152: SMTP Service Extension for 8-bit MIME Transport](https://www.rfc-editor.org/rfc/rfc6152)
#[serde(default = "crate::conf::true_val")]
_8bitmime: bool,
//Essentially, the PRDR extension to SMTP allows (but does not require) an SMTP server to
//issue multiple responses after a message has been transferred, by mutual consent of the
//client and server. SMTP clients that support the PRDR extension then use the expanded
//responses as supplemental data to the responses that were received during the earlier
//envelope exchange.
/// Essentially, the PRDR extension to SMTP allows (but does not require) an SMTP server to
/// issue multiple responses after a message has been transferred, by mutual consent of the
/// client and server. SMTP clients that support the PRDR extension then use the expanded
/// responses as supplemental data to the responses that were received during the earlier
/// envelope exchange.
#[serde(default = "crate::conf::true_val")]
prdr: bool,
#[serde(default = "crate::conf::true_val")]
binarymime: bool,
//Resources:
//- http://www.postfix.org/SMTPUTF8_README.html
/// Resources:
/// - http://www.postfix.org/SMTPUTF8_README.html
#[serde(default = "crate::conf::true_val")]
smtputf8: bool,
#[serde(default = "crate::conf::true_val")]
@ -239,10 +229,10 @@ impl Default for SmtpExtensionSupport {
}
}
#[derive(Debug)]
/// SMTP client session object.
///
/// See module-wide documentation.
#[derive(Debug)]
pub struct SmtpConnection {
stream: AsyncWrapper<Connection>,
read_buffer: String,
@ -543,6 +533,11 @@ impl SmtpConnection {
Ok(ret)
}
/// Set a new value for `envelope_from`.
pub fn set_envelope_from(&mut self, envelope_from: String) {
self.server_conf.envelope_from = envelope_from;
}
fn set_extension_support(&mut self, reply: Reply<'_>) {
debug_assert_eq!(reply.code, ReplyCode::_250);
self.server_conf.extensions.pipelining &= reply.lines.contains(&"PIPELINING");
@ -1081,6 +1076,7 @@ mod test {
.lock()
.unwrap()
.iter_mut()
.rev()
.find(|((i, d), _)| (i, d.as_str()) == (&ip, domain))
{
std::dbg!(&message);
@ -1157,9 +1153,8 @@ mod test {
}
fn data_end(&mut self) -> Response {
eprintln!("datae_nd() ");
if let Some(((_, _), message)) = self.mails.lock().unwrap().pop() {
if let Message::Data { from: _, to, buf } = message {
let last = self.mails.lock().unwrap().pop();
if let Some(((ip, domain), Message::Data { from: _, to, buf })) = last {
for to in to {
match crate::Envelope::from_bytes(&buf, None) {
Ok(env) => {
@ -1172,9 +1167,13 @@ mod test {
}
}
}
self.mails
.lock()
.unwrap()
.push(((ip, domain), Message::Helo));
return OK;
}
}
eprintln!("last self.mails item was not Message::Data: {last:?}");
INTERNAL_ERROR
}
}