Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for sending "ehlo" and receiving multiline "ehlo" response. #19077

Merged
merged 6 commits into from
Nov 3, 2021
Merged
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 30 additions & 7 deletions lib/pure/smtp.nim
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ type
sock: SocketType
address: string
debug: bool
useEhlo: bool

Smtp* = SmtpBase[Socket]
AsyncSmtp* = SmtpBase[AsyncSocket]
Expand Down Expand Up @@ -100,7 +101,6 @@ proc debugRecv*(smtp: Smtp | AsyncSmtp): Future[string] {.multisync.} =
## `SMTP extensions<https://en.wikipedia.org/wiki/Extended_SMTP>`_.
##
## See `checkReply(reply)<#checkReply,AsyncSmtp,string>`_.

result = await smtp.sock.recvLine()
if smtp.debug:
echo("S:" & result)
Expand Down Expand Up @@ -172,11 +172,13 @@ proc `$`*(msg: Message): string =
result.add(msg.msgBody)

proc newSmtp*(useSsl = false, debug = false,
sslContext: SslContext = nil): Smtp =
sslContext: SslContext = nil, useEhlo = false): Smtp =
## Creates a new `Smtp` instance.
## If `useEhlo` is true, `ehlo` is sent instead of `helo`
new result
result.debug = debug
result.sock = newSocket()
result.useEhlo = useEhlo
if useSsl:
when compiledWithSsl:
if sslContext == nil:
Expand All @@ -187,11 +189,11 @@ proc newSmtp*(useSsl = false, debug = false,
{.error: "SMTP module compiled without SSL support".}

proc newAsyncSmtp*(useSsl = false, debug = false,
sslContext: SslContext = nil): AsyncSmtp =
sslContext: SslContext = nil, useEhlo = false): AsyncSmtp =
## Creates a new `AsyncSmtp` instance.
new result
result.debug = debug

result.useEhlo = useEhlo
result.sock = newAsyncSocket()
if useSsl:
when compiledWithSsl:
Expand Down Expand Up @@ -220,7 +222,6 @@ proc checkReply*(smtp: Smtp | AsyncSmtp, reply: string) {.multisync.} =
## would need to call when using this module. One exception to
## this is if you are implementing any
## `SMTP extensions<https://en.wikipedia.org/wiki/Extended_SMTP>`_.

var line = await smtp.debugRecv()
if not line.startsWith(reply):
await quitExcpt(smtp, "Expected " & reply & " reply, got: " & line)
Expand All @@ -230,14 +231,33 @@ proc helo*(smtp: Smtp | AsyncSmtp) {.multisync.} =
await smtp.debugSend("HELO " & smtp.address & "\c\L")
await smtp.checkReply("250")

proc recvEhlo*(smtp: Smtp | AsyncSmtp) {.multisync.} =
## skips "250-" lines, read until "250 " found
while true:
var line = await smtp.sock.recvLine()
if smtp.debug:
echo("S:" & line)
if line.startsWith("250-"): continue
elif line.startsWith("250 "): break # last line
else:
await quitExcpt(smtp, "Expected 250 reply from EHLO response, got: " & line)

proc ehlo*(smtp: Smtp | AsyncSmtp) {.multisync.} =
## Sends EHLO request
enthus1ast marked this conversation as resolved.
Show resolved Hide resolved
await smtp.debugSend("EHLO " & smtp.address & "\c\L")
await smtp.recvEhlo()

proc connect*(smtp: Smtp | AsyncSmtp,
address: string, port: Port) {.multisync.} =
## 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)
await smtp.checkReply("220")
await smtp.helo()
if smtp.useEhlo:
await smtp.ehlo()
else:
await smtp.helo()

proc startTls*(smtp: Smtp | AsyncSmtp, sslContext: SslContext = nil) {.multisync.} =
## Put the SMTP connection in TLS (Transport Layer Security) mode.
Expand All @@ -249,7 +269,10 @@ proc startTls*(smtp: Smtp | AsyncSmtp, sslContext: SslContext = nil) {.multisync
getSSLContext().wrapConnectedSocket(smtp.sock, handshakeAsClient)
else:
sslContext.wrapConnectedSocket(smtp.sock, handshakeAsClient)
await smtp.helo()
if smtp.useEhlo:
await smtp.ehlo()
else:
await smtp.helo()
else:
{.error: "SMTP module compiled without SSL support".}

Expand Down