///|
/// A real SMTP transport over `moonbitlang/async/socket` (native only).
/// This file is compiled only for the native target; the js and wasm targets
/// use stubs that raise `Unsupported`.
pub struct SocketTransport {
mut conn : @socket.Tcp?
}
///|
pub fn SocketTransport::new() -> SocketTransport {
{ conn: None }
}
///|
pub impl SmtpTransport for SocketTransport with fn connect(self, config) {
let tcp = @socket.Tcp::connect_to_host(config.host, port=config.port) catch {
e =>
raise MailFailure::io(
"socket connect to \{config.host}:\{config.port} failed: \{e}",
)
}
self.conn = Some(tcp)
}
///|
pub impl SmtpTransport for SocketTransport with fn write_line(self, line) {
match self.conn {
Some(conn) =>
conn.write(line + "\r\n") catch {
e => raise MailFailure::io("socket write failed: \{e}")
}
None => raise MailFailure::transport("socket transport is not connected")
}
}
///|
pub impl SmtpTransport for SocketTransport with fn read_line(self) {
match self.conn {
Some(conn) => {
let line = conn.read_until("\n") catch {
e => raise MailFailure::io("socket read failed: \{e}")
}
match line {
Some(text) =>
match text.strip_suffix("\r") {
Some(view) => view.to_owned()
None => text
}
None => raise MailFailure::io("connection closed by server")
}
}
None => raise MailFailure::transport("socket transport is not connected")
}
}
///|
pub impl SmtpTransport for SocketTransport with fn close(self) {
match self.conn {
Some(conn) => conn.close()
None => ()
}
self.conn = None
}