Skip to content

feat(NODE-1955): Add SMTP library & server#87

Merged
blind-oracle merged 8 commits into
mainfrom
igor/smtp-gateway-v1
May 19, 2026
Merged

feat(NODE-1955): Add SMTP library & server#87
blind-oracle merged 8 commits into
mainfrom
igor/smtp-gateway-v1

Conversation

@blind-oracle
Copy link
Copy Markdown
Contributor

  1. Refactor HTTP module and move some stuff that's common to both SMTP/HTTP into a new network module
  2. Adds SMTP library (IC-agnostic) and IC Candid primitives to talk to canisters
  3. Small test SMTP server

More work will follow to glue SMTP to the IC

@blind-oracle blind-oracle requested a review from a team as a code owner May 18, 2026 10:01
Comment thread ic-bn-lib/src/smtp/server.rs Outdated
Comment thread ic-bn-lib/src/smtp/server.rs
Comment thread ic-bn-lib/tools/smtp_server.rs
Comment thread ic-bn-lib/src/smtp/inbound/manager.rs Outdated
Comment thread ic-bn-lib/src/smtp/ic/candid.rs
Comment thread ic-bn-lib/src/smtp/inbound/session.rs
Comment thread ic-bn-lib/src/smtp/inbound/session.rs
Comment thread ic-bn-lib/src/smtp/inbound/session.rs
Comment thread ic-bn-lib/src/smtp/inbound/session.rs
Comment thread ic-bn-lib/src/smtp/inbound/session.rs
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Introduces an SMTP library and a small testing SMTP server binary, refactors common networking code (listeners, TLS handshake, async byte-counter) out of the http module into a new network module, and adds Candid types for talking to canisters over an IC SMTP protocol.

Changes:

  • Extract shared network primitives (Listener, listen_tcp, listen_unix, tls_handshake, AsyncCounter, AsyncReadWrite) into src/network/.
  • Add src/smtp/ with an inbound SMTP session state machine (EHLO/HELO, MAIL FROM with SPF/iprev, RCPT TO with resolver policies, DATA/BDAT, STARTTLS), session manager, and Server.
  • Add IC SMTP Candid types under src/smtp/ic/candid.rs and a tools/smtp-server test binary; pull in mail-auth, mail-parser, smtp-proto workspace deps.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
Cargo.toml Adds mail-auth, mail-parser, smtp-proto to the workspace.
ic-bn-lib/Cargo.toml Adds SMTP-related deps, tokio-test, tracing-subscriber, and the smtp-server binary target.
ic-bn-lib/src/lib.rs Exposes network and smtp modules; allows collapsible_if.
ic-bn-lib/src/http/mod.rs Moves AsyncReadWrite/AsyncCounter to network.
ic-bn-lib/src/http/server/mod.rs Switches to shared Listener/tls_handshake from network.
ic-bn-lib/src/network/mod.rs New module with tls_handshake, AsyncCounter, AsyncReadWrite.
ic-bn-lib/src/network/listener.rs Generic TCP/Unix listener moved here.
ic-bn-lib/src/smtp/mod.rs Core SMTP types (Message, traits, dummies, errors).
ic-bn-lib/src/smtp/address.rs EmailAddress parsing/formatting.
ic-bn-lib/src/smtp/server.rs TCP listener loop spawning sessions.
ic-bn-lib/src/smtp/inbound/mod.rs Session config/state/data + tests.
ic-bn-lib/src/smtp/inbound/session.rs Session state machine and IO loop.
ic-bn-lib/src/smtp/inbound/ehlo.rs EHLO/HELO handling.
ic-bn-lib/src/smtp/inbound/mail_from.rs MAIL FROM handling with optional iprev/SPF.
ic-bn-lib/src/smtp/inbound/rcpt_to.rs RCPT TO handling with resolver policies.
ic-bn-lib/src/smtp/inbound/manager.rs Session lifetime + STARTTLS upgrade.
ic-bn-lib/src/smtp/ic/mod.rs, candid.rs IC SMTP Candid types.
ic-bn-lib/tools/smtp_server.rs Test binary running the SMTP server.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.


pub(crate) async fn message_too_big(&mut self) -> SessionResult<()> {
let msg = format!(
"Message too big for, we accept up to {} bytes.",
"Message too big for, we accept up to {} bytes.",
self.cfg.max_message_size
);
return self.reply("552", "5.3.4", &msg).await;
if let Some(v) = output.explanation() {
write!(msg, ": {v}.").ok();
}
write!(msg, "\r\n").ok();
let rustls_server_cfg = ServerConfig::builder()
.with_no_client_auth()
.with_cert_resolver(Arc::new(
StubResolver::new(TEST_CERT_1.as_bytes(), TEST_KEY_2.as_bytes()).unwrap(),

use crate::{
network::listener::listen_tcp,
smtp::inbound::{SessionConfig, SessionError, SessionResult, manager::SessionManager},
@@ -0,0 +1,34 @@
use std::{net::SocketAddr, str::FromStr, sync::Arc, time::Duration};
@blind-oracle blind-oracle merged commit a29d2a8 into main May 19, 2026
10 of 11 checks passed
@blind-oracle blind-oracle deleted the igor/smtp-gateway-v1 branch May 19, 2026 15:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants