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 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
//! A SMTP server that can be embedded into another program
//!
//! This library provides a simple embeddable SMTP server. The
//! server uses blocking IO and a threadpool.
//! # Examples
//! ```no_run
//! use mailin_embedded::{Server, SslConfig, Handler};
//! # use mailin_embedded::err::Error;
//!
//! #[derive(Clone)]
//! struct MyHandler {}
//! impl Handler for MyHandler{}
//!
//! let handler = MyHandler {};
//! let mut server = Server::new(handler);
//!
//! server.with_name("example.com")
//! .with_ssl(SslConfig::None)?
//! .with_addr("127.0.0.1:25")?;
//! server.serve();
//! # Ok::<(), Error>(())
//! ```
#![forbid(unsafe_code)]
#![forbid(missing_docs)]
/// Custom error type for mailin_embedded
pub mod err;
cfg_if::cfg_if! {
if #[cfg(feature = "ossl")] {
mod ossl;
use crate::ossl::SslImpl;
} else {
mod rtls;
use crate::rtls::SslImpl;
}
}
mod running;
mod ssl;
use crate::err::Error;
pub use crate::ssl::SslConfig;
pub use mailin::response;
pub use mailin::{Action, AuthMechanism, Handler, Response};
use std::net::{SocketAddr, TcpListener, ToSocketAddrs};
/// `Server` is used to configure and start the SMTP server
pub struct Server<H>
where
H: Handler + Clone + Send,
{
handler: H,
name: String,
ssl: Option<SslImpl>,
num_threads: u32,
auth: Vec<AuthMechanism>,
tcp_listener: Option<TcpListener>,
socket_address: Vec<SocketAddr>,
}
impl<H> Server<H>
where
H: Handler + Clone + Send,
{
/// Create a new server with the given Handler
pub fn new(handler: H) -> Self {
Self {
handler,
name: "localhost".to_owned(),
ssl: None,
num_threads: 4,
auth: Vec::with_capacity(4),
tcp_listener: None,
socket_address: Vec::with_capacity(4),
}
}
/// Give the server a name
pub fn with_name<T>(&mut self, name: T) -> &mut Self
where
T: Into<String>,
{
self.name = name.into();
self
}
/// Set the SSL configuration of the server
pub fn with_ssl(&mut self, ssl_config: SslConfig) -> Result<&mut Self, Error> {
self.ssl = SslImpl::setup(ssl_config)?;
Ok(self)
}
/// Set the size of the threadpool which is equal to the maximum number of
/// concurrent SMTP sessions.
pub fn with_num_threads(&mut self, num_threads: u32) -> &mut Self {
self.num_threads = num_threads;
self
}
/// Add an authentication mechanism that will supported by the server
pub fn with_auth(&mut self, auth: AuthMechanism) -> &mut Self {
self.auth.push(auth);
self
}
/// Set a tcp listener from an already open socket
pub fn with_tcp_listener(&mut self, listener: TcpListener) -> &mut Self {
self.tcp_listener = Some(listener);
self
}
/// Add ip addresses and ports to listen on.
/// Returns an error if the given socket addresses are not valid.
/// ```
/// # use mailin_embedded::{Server, Handler};
/// # use mailin_embedded::err::Error;
/// # #[derive(Clone)]
/// # struct EmptyHandler {}
/// # impl Handler for EmptyHandler {}
/// # let mut server = Server::new(EmptyHandler {});
/// server.with_addr("127.0.0.1:25")?;
/// # Ok::<(), Error>(())
/// ```
pub fn with_addr<A: ToSocketAddrs>(&mut self, addr: A) -> Result<&mut Self, Error> {
for addr in addr
.to_socket_addrs()
.map_err(|e| Error::with_source("Invalid socket address", e))?
{
self.socket_address.push(addr);
}
Ok(self)
}
/// Start the SMTP server and run forever
pub fn serve(self) -> Result<(), Error> {
running::serve(self)
}
}