assumpta-core-0.1.0.0: Core functionality for an SMTP client

Safe HaskellSafe
LanguageHaskell2010

Network.Mail.Assumpta.ParseResponse

Contents

Description

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

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

type Parser = Parser Source #

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.

parseFrom :: Monad m => Parser r -> m ByteString -> m (Either String r) Source #

parseFrom x pull

Given some action 'pull' which can be called to supply the parser with more input, parse thing x and return a result.