Skip to main content

rust_pop3_client/
pop3_connection_factory.rs

1use std::sync::Arc;
2use std::net::TcpStream;
3use std::error::Error;
4
5use rustls::pki_types::ServerName;
6use rustls::{RootCertStore, ClientConnection, StreamOwned};
7
8use crate::LineReader;
9use crate::Pop3ConnectionImpl;
10
11pub struct Pop3ConnectionFactory {
12
13}
14
15impl Pop3ConnectionFactory {
16    /// Returns a new POP3 connection.
17    ///
18    /// # Arguments
19    ///
20    /// * `host` - IP-Address or host name of the POP3 server to connect
21    /// * `port` - Port of the POP3 server to connect
22    pub fn new(host: &str, port: u16) -> Result<Pop3ConnectionImpl<StreamOwned<ClientConnection, TcpStream>>, Box<dyn Error>> {
23        let mut root_store = RootCertStore::empty();
24        for cert in rustls_native_certs::load_native_certs().certs {
25            root_store.add(cert)?;
26        }
27
28        Pop3ConnectionFactory::with_custom_certs(host, port, root_store)
29    }
30
31    /// Returns a new POP3 connection with custom certificates.
32    ///
33    /// # Arguments
34    ///
35    /// * `host` - IP-Address or host name of the POP3 server to connect
36    /// * `port` - Port of the POP3 server to connect
37    /// * `root_store` - Store of trusted (root) certificates.
38    ///
39    /// # Examples
40    ///
41    /// ```
42    /// use rust_pop3_client::Pop3ConnectionFactory;
43    /// use rustls::RootCertStore;
44    ///
45    /// let mut root_store = RootCertStore::empty();
46    /// for cert in rustls_native_certs::load_native_certs().certs {
47    ///     root_store.add(cert).unwrap();
48    /// }
49    /// 
50    /// let connection = Pop3ConnectionFactory::with_custom_certs("", 995, root_store);
51    /// ```
52    pub fn with_custom_certs(host: &str, port: u16, root_store: RootCertStore) -> Result<Pop3ConnectionImpl<StreamOwned<ClientConnection, TcpStream>>, Box<dyn Error>> {
53        let config = rustls::ClientConfig::builder()
54            .with_root_certificates(root_store)
55            .with_no_client_auth();
56
57        let server_name = ServerName::try_from(host)?;
58
59        let connection = rustls::ClientConnection::new(Arc::new(config), server_name.to_owned())?;
60        let stream =  TcpStream::connect(format!("{}:{}", host, port))?;
61        let stream = rustls::StreamOwned::new(connection, stream);
62
63        let mut client = Pop3ConnectionImpl { 
64            stream,
65            reader: LineReader::new()
66        };
67
68        client.read_status_line()?;
69        Ok(client)
70    }
71
72    /// Returns a new POP3 conneciton without TLS.
73    /// 
74    /// # Argumetns
75    /// 
76    /// * `host` - IP-Address or host name of the POP3 server to connect
77    /// * `port` - Port of the POP3 server to connect
78    pub fn without_tls(host: &str, port: u16) -> Result<Pop3ConnectionImpl<TcpStream>, Box<dyn Error>> {
79        let stream =  TcpStream::connect(format!("{}:{}", host, port))?;
80        let mut client = Pop3ConnectionImpl { 
81            stream,
82            reader: LineReader::new()
83        };
84        client.read_status_line()?;
85        Ok(client)
86    }
87
88}