mailin_embedded/lib.rs
1//! A SMTP server that can be embedded into another program
2//!
3//! This library provides a simple embeddable SMTP server. The
4//! server uses blocking IO and a threadpool.
5//! # Examples
6//! ```no_run
7//! use mailin_embedded::{Server, SslConfig, Handler};
8//! # use mailin_embedded::err::Error;
9//!
10//! #[derive(Clone)]
11//! struct MyHandler {}
12//! impl Handler for MyHandler{}
13//!
14//! let handler = MyHandler {};
15//! let mut server = Server::new(handler);
16//!
17//! server.with_name("example.com")
18//! .with_ssl(SslConfig::None)?
19//! .with_addr("127.0.0.1:25")?;
20//! server.serve();
21//! # Ok::<(), Error>(())
22//! ```
23
24#![forbid(unsafe_code)]
25#![forbid(missing_docs)]
26
27/// Custom error type for mailin_embedded
28pub mod err;
29
30cfg_if::cfg_if! {
31 if #[cfg(feature = "ossl")] {
32 mod ossl;
33 use crate::ossl::SslImpl;
34 } else {
35 mod rtls;
36 use crate::rtls::SslImpl;
37 }
38}
39
40mod running;
41mod ssl;
42
43use crate::err::Error;
44pub use crate::ssl::SslConfig;
45pub use mailin::response;
46pub use mailin::{Action, AuthMechanism, Handler, Response};
47use std::net::{SocketAddr, TcpListener, ToSocketAddrs};
48
49/// `Server` is used to configure and start the SMTP server
50pub struct Server<H>
51where
52 H: Handler + Clone + Send,
53{
54 handler: H,
55 name: String,
56 ssl: Option<SslImpl>,
57 num_threads: u32,
58 auth: Vec<AuthMechanism>,
59 tcp_listener: Option<TcpListener>,
60 socket_address: Vec<SocketAddr>,
61}
62
63impl<H> Server<H>
64where
65 H: Handler + Clone + Send,
66{
67 /// Create a new server with the given Handler
68 pub fn new(handler: H) -> Self {
69 Self {
70 handler,
71 name: "localhost".to_owned(),
72 ssl: None,
73 num_threads: 4,
74 auth: Vec::with_capacity(4),
75 tcp_listener: None,
76 socket_address: Vec::with_capacity(4),
77 }
78 }
79
80 /// Give the server a name
81 pub fn with_name<T>(&mut self, name: T) -> &mut Self
82 where
83 T: Into<String>,
84 {
85 self.name = name.into();
86 self
87 }
88
89 /// Set the SSL configuration of the server
90 pub fn with_ssl(&mut self, ssl_config: SslConfig) -> Result<&mut Self, Error> {
91 self.ssl = SslImpl::setup(ssl_config)?;
92 Ok(self)
93 }
94
95 /// Set the size of the threadpool which is equal to the maximum number of
96 /// concurrent SMTP sessions.
97 pub fn with_num_threads(&mut self, num_threads: u32) -> &mut Self {
98 self.num_threads = num_threads;
99 self
100 }
101
102 /// Add an authentication mechanism that will supported by the server
103 pub fn with_auth(&mut self, auth: AuthMechanism) -> &mut Self {
104 self.auth.push(auth);
105 self
106 }
107
108 /// Set a tcp listener from an already open socket
109 pub fn with_tcp_listener(&mut self, listener: TcpListener) -> &mut Self {
110 self.tcp_listener = Some(listener);
111 self
112 }
113
114 /// Add ip addresses and ports to listen on.
115 /// Returns an error if the given socket addresses are not valid.
116 /// ```
117 /// # use mailin_embedded::{Server, Handler};
118 /// # use mailin_embedded::err::Error;
119 /// # #[derive(Clone)]
120 /// # struct EmptyHandler {}
121 /// # impl Handler for EmptyHandler {}
122 /// # let mut server = Server::new(EmptyHandler {});
123 /// server.with_addr("127.0.0.1:25")?;
124 /// # Ok::<(), Error>(())
125 /// ```
126 pub fn with_addr<A: ToSocketAddrs>(&mut self, addr: A) -> Result<&mut Self, Error> {
127 for addr in addr
128 .to_socket_addrs()
129 .map_err(|e| Error::with_source("Invalid socket address", e))?
130 {
131 self.socket_address.push(addr);
132 }
133 Ok(self)
134 }
135
136 /// Start the SMTP server and run forever
137 pub fn serve(self) -> Result<(), Error> {
138 running::serve(self)
139 }
140}