mirror of
https://github.com/rustmailer/bichon.git
synced 2026-08-03 07:48:34 +02:00
110 lines
3.2 KiB
Rust
110 lines
3.2 KiB
Rust
//
|
|
// Copyright (c) 2025-2026 rustmailer.com (https://rustmailer.com)
|
|
//
|
|
// This file is part of the Bichon Email Archiving Project
|
|
//
|
|
// This program is free software: you can redistribute it and/or modify
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
// (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU Affero General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
use std::net::SocketAddr;
|
|
|
|
use tokio::net::TcpListener;
|
|
use tokio_rustls::TlsAcceptor;
|
|
|
|
use crate::modules::{
|
|
common::signal::SIGNAL_MANAGER,
|
|
settings::cli::{SmtpEncryptionMode, SETTINGS},
|
|
smtp::{
|
|
server::{run_smtp_server, run_smtps_server},
|
|
tls::create_acceptor,
|
|
},
|
|
};
|
|
|
|
pub mod server;
|
|
pub mod stream;
|
|
pub mod tls;
|
|
#[cfg(test)]
|
|
mod tests;
|
|
|
|
#[derive(Clone, Default)]
|
|
pub struct SmtpConfig {
|
|
pub whitelist: Option<Vec<String>>,
|
|
pub tls_acceptor: Option<TlsAcceptor>,
|
|
pub auth_required: bool,
|
|
}
|
|
|
|
pub struct SmtpServer {
|
|
pub smtp_addr: SocketAddr,
|
|
smtp_handle: tokio::task::JoinHandle<()>,
|
|
}
|
|
|
|
impl SmtpServer {
|
|
pub async fn stop(self) {
|
|
let _ = self.smtp_handle.await;
|
|
}
|
|
}
|
|
|
|
pub async fn start_smtp_server() -> std::io::Result<SmtpServer> {
|
|
let smtp_port = SETTINGS.bichon_smtp_port;
|
|
|
|
let tls_acceptor: Option<TlsAcceptor> = match SETTINGS.bichon_smtp_encryption {
|
|
SmtpEncryptionMode::None => None,
|
|
SmtpEncryptionMode::Starttls | SmtpEncryptionMode::Tls => Some(create_acceptor().await?),
|
|
};
|
|
|
|
let smtp_listener = TcpListener::bind((
|
|
SETTINGS.bichon_bind_ip.clone().unwrap_or("0.0.0.0".into()),
|
|
smtp_port,
|
|
))
|
|
.await
|
|
.map_err(|e| {
|
|
if e.kind() == std::io::ErrorKind::AddrInUse {
|
|
std::io::Error::other(format!(
|
|
"SMTP port {smtp_port} is already in use. Is another instance running?"
|
|
))
|
|
} else {
|
|
e
|
|
}
|
|
})?;
|
|
let smtp_addr = smtp_listener.local_addr()?;
|
|
|
|
let smtp_config = SmtpConfig {
|
|
whitelist: None,
|
|
tls_acceptor: match SETTINGS.bichon_smtp_encryption {
|
|
SmtpEncryptionMode::None | SmtpEncryptionMode::Tls => None,
|
|
SmtpEncryptionMode::Starttls => tls_acceptor.clone(),
|
|
},
|
|
auth_required: SETTINGS.bichon_smtp_auth_required,
|
|
};
|
|
|
|
let smtp_shutdown = SIGNAL_MANAGER.subscribe();
|
|
|
|
let smtp_handle = if matches!(SETTINGS.bichon_smtp_encryption, SmtpEncryptionMode::Tls) {
|
|
let acceptor = tls_acceptor
|
|
.clone()
|
|
.expect("TLS acceptor required when tls=true");
|
|
tokio::spawn(async move {
|
|
run_smtps_server(smtp_listener, smtp_config, acceptor, smtp_shutdown).await;
|
|
})
|
|
} else {
|
|
tokio::spawn(async move {
|
|
run_smtp_server(smtp_listener, smtp_config, smtp_shutdown).await;
|
|
})
|
|
};
|
|
|
|
Ok(SmtpServer {
|
|
smtp_addr,
|
|
smtp_handle,
|
|
})
|
|
}
|