From 7eae0f0d834ffe6517031b4570e9aa86ea7c26bf Mon Sep 17 00:00:00 2001 From: Mildred Ki'Lya Date: Fri, 11 Aug 2023 20:35:24 +0200 Subject: [PATCH] Implement dual-stack IPv4/IPv6 Use dial to create the socket, which will automatically create either an IPv4 or IPv6 socket based on the address resolution. --- src/smtp.nim | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/src/smtp.nim b/src/smtp.nim index 721ea89..067b76e 100644 --- a/src/smtp.nim +++ b/src/smtp.nim @@ -67,6 +67,7 @@ type sock: SocketType address: string debug: bool + sslContext: SslContext Smtp* = SmtpBase[Socket] AsyncSmtp* = SmtpBase[AsyncSocket] @@ -179,13 +180,14 @@ proc newSmtp*(useSsl = false, debug = false, sslContext: SslContext = nil): Smtp ## Creates a new `Smtp` instance. new result result.debug = debug - result.sock = newSocket() + result.sock = nil + result.sslContext = nil if useSsl: when compiledWithSsl: if sslContext == nil: - getSSLContext().wrapSocket(result.sock) + result.sslContext = getSSLContext() else: - sslContext.wrapSocket(result.sock) + result.sslContext = sslContext else: {.error: "SMTP module compiled without SSL support".} @@ -193,13 +195,14 @@ proc newAsyncSmtp*(useSsl = false, debug = false, sslContext: SslContext = nil): ## Creates a new `AsyncSmtp` instance. new result result.debug = debug - result.sock = newAsyncSocket() + result.sock = nil + result.sslContext = nil if useSsl: when compiledWithSsl: if sslContext == nil: - getSSLContext().wrapSocket(result.sock) + result.sslContext = getSSLContext() else: - sslContext.wrapSocket(result.sock) + result.sslContext = sslContext else: {.error: "SMTP module compiled without SSL support".} @@ -251,12 +254,25 @@ proc connect*(smtp: Smtp | AsyncSmtp, ## Establishes a connection with a SMTP server. ## May fail with ReplyError or with a socket error. smtp.address = address - await smtp.sock.connect(address, port) + when smtp is Smtp: + smtp.sock = net.dial(address, port) + else: + smtp.sock = await asyncnet.dial(address, port) + if smtp.sslContext != nil: + smtp.sslContext.wrapSocket(smtp.sock) await smtp.checkReply("220") let speaksEsmtp = await smtp.ehlo() if not speaksEsmtp: await smtp.helo() +proc dial*(address: string, port: Port, useSsl = false, debug = false, sslContext: SslContext = nil): Smtp = + result = newSmtp(useSsl, debug, sslContext) + result.connect(address, port) + +proc dialAsync*(address: string, port: Port, useSsl = false, debug = false, sslContext: SslContext = nil): Future[AsyncSmtp] {.async.} = + result = newAsyncSmtp(useSsl, debug, sslContext) + await result.connect(address, port) + proc startTls*(smtp: Smtp | AsyncSmtp, sslContext: SslContext = nil) {.multisync.} = ## Put the SMTP connection in TLS (Transport Layer Security) mode. ## May fail with ReplyError @@ -314,4 +330,4 @@ proc sendMail*(smtp: Smtp | AsyncSmtp, fromAddr: string, proc close*(smtp: Smtp | AsyncSmtp) {.multisync.} = ## Disconnects from the SMTP server and closes the socket. await smtp.debugSend("QUIT\c\L") - smtp.sock.close() + if smtp.sock != nil: smtp.sock.close()