Safe Haskell | Safe |
---|---|
Language | Haskell2010 |
Parse server replies.
The general format of replies is described in RFC 5321, at p. 49:
The format for multiline replies requires that every line, except the last, begin with the reply code, followed immediately by a hyphen, "-" (also known as minus), followed by text. The last line will begin with the reply code, followed immediately by <SP>, optionally some text, and <CRLF>. For example: 123-First line 123-Second line 123-234 text beginning with numbers 123 The last line
On p. 49, sec 4.2.2, "Reply Codes by Function Groups", the RFC lists the various server responses that can be made. (Also Wikipedia has a more pleasantly formatted version of the list at https://en.wikipedia.org/wiki/List_of_SMTP_server_return_codes.)
Synopsis
- getReply :: MonadError SmtpError m => m ByteString -> m Reply
- type Parser = Parser
- textstring :: Parser ByteString
- code :: Parser ReplyCode
- reply :: Parser Reply
- getReply_ :: Monad m => m ByteString -> m (Either String Reply)
- parseFrom :: Monad m => Parser r -> m ByteString -> m (Either String r)
Fetching replies
getReply
is intended to be the main function
used by other modules - it allows fetching and parsing replies
from a server. The other functions are lower-level utility functions, and
might be useful if you want to customize parsing.
getReply :: MonadError SmtpError m => m ByteString -> m Reply Source #
getReply pull
Given some action 'pull' which can be called to
supply the parser with more input, attempt to fetch
content from the server and parse it as a Reply
.
On failure, ParseError
will be thrown, with
a message explaining the failure.
A ParseError
will also be thrown if the response
looks superficially like a reply, but has multiple
reply codes for different lines. (In other words,
a successful return value means the reply has at
least one line, and all lines have the same reply
code.)
The result returned is in the MonadError
monad,
so can be specialised by the caller to a Maybe
,
Either
, or some other MonadError
instance as desired.
Low-level functions and types
Attoparsec parser type.
textstring :: Parser ByteString Source #
A string of length at least 1, which may contain printable US ASCII, characters, space characters, and horizontal tabs.
See RFC 5321, p. 47, "textstring".
The spec in the RFC is
textstring = 1*(%d09 / %d32-126) ; HT, SP, Printable US-ASCII
>>>
:set -XOverloadedStrings
>>>
Att.parseOnly (textstring <* Att.endOfInput) "~" -- ASCII 126
Right "~">>>
Att.parseOnly (textstring <* Att.endOfInput) "\x7f" -- ASCII 127
Left "printable ASCII text: Failed reading: takeWhile1"
code :: Parser ReplyCode Source #
Parser for a reply code.
The RFC states that an SMTP server SHOULD only send the codes listed in the spec, but we don't validate that here; we accept any sequence of decimal digits, higher-level functions can further validate it if desired.
>>>
:set -XOverloadedStrings
>>>
Att.parseOnly (code <* Att.endOfInput) "42"
Right 42>>>
Att.parseOnly (code <* Att.endOfInput) "042"
Right 42
reply :: Parser Reply Source #
One or more server reply lines, terminating with a last line. The parser does not check that they all have the same reply code.
getReply_ :: Monad m => m ByteString -> m (Either String Reply) Source #
getReply_ pull
Given some action 'pull' which can be called to
supply the parser with more input, attempt to
fetch input and parse it as a superficially
well-formed Reply
(multiple lines ending in a terminating
line).
We don't check that all reply lines have the
same reply code.