postmaster-0.1: Postmaster ESMTP ServerContentsIndex
Network.Postmaster.Base
PortabilityHaskell 2-pre
Stabilityprovisional
Maintainersimons@cryp.to
Contents
The Smtpd Monad
Environment
Generating Unique Identifiers.
Event Handler
Data Handler
Logging
Exception Handling
Resource Management
Description
Synopsis
type GlobalEnv = MVar Env
type SmtpdState = Env
type Smtpd a = RWST GlobalEnv [LogMsg] SmtpdState IO a
say :: Int -> Int -> Int -> String -> Smtpd SmtpReply
global :: EnvT a -> Smtpd a
local :: EnvT a -> Smtpd a
type SmtpdVariable = forall a. Typeable a => (Variable -> EnvT a) -> Smtpd a
defineLocal :: String -> SmtpdVariable
defineGlobal :: String -> SmtpdVariable
type ID = Int
getUniqueID :: Smtpd ID
mySessionID :: Smtpd ID
type EventHandler = Event -> Smtpd SmtpReply
type EventT = EventHandler -> EventHandler
type DataHandler = Buffer -> Smtpd (Maybe SmtpReply, Buffer)
data LogMsg = LogMsg ID SmtpdState LogEvent
yell :: LogEvent -> Smtpd ()
data LogEvent
= Msg String
| StartSession
| EndSession
| Input String
| Output String
| AcceptConn SockAddr
| DropConn SockAddr
| UserShutdown
| CaughtException Exception
| CaughtIOError IOException
| StartEventHandler String Event
| EventHandlerResult String Event SmtpCode
| CurrentState
| AssignMailID ID
fallback :: Smtpd a -> Smtpd a -> Smtpd a
bracketOnError :: IO a -> a -> IO b -> a -> IO c -> IO c
acquire :: ((a -> IO b) -> IO b) -> IO (MVar a)
release :: MVar a -> IO ()
The Smtpd Monad
type GlobalEnv = MVar Env
type SmtpdState = Env
type Smtpd a = RWST GlobalEnv [LogMsg] SmtpdState IO a
say :: Int -> Int -> Int -> String -> Smtpd SmtpReply
say a b c msg = return (reply a b c [msg])

The SmtpReply codes returned the event handler returns determine what Postmaster will do:

1xx, 2xx, 3xx
make the SessionState transition determined determined by smtpdFSM.
4xx, 5xx
Do not make the transition.
221, 421
Drop the connection after this reply.

The reply for the Greeting event (the first event triggered when a session starts up) is interpreted as follows: 2xx accepts the connection, everything else refuses the connection.

Environment
global :: EnvT a -> Smtpd a
local :: EnvT a -> Smtpd a
type SmtpdVariable = forall a. Typeable a => (Variable -> EnvT a) -> Smtpd a
defineLocal :: String -> SmtpdVariable
defineGlobal :: String -> SmtpdVariable
Generating Unique Identifiers.
type ID = Int
getUniqueID :: Smtpd ID
Produce an unique ID using a global counter.
mySessionID :: Smtpd ID
Provides an unique ID for every (TCP) session.
Event Handler
type EventHandler = Event -> Smtpd SmtpReply
type EventT = EventHandler -> EventHandler
Data Handler
type DataHandler = Buffer -> Smtpd (Maybe SmtpReply, Buffer)
Logging
data LogMsg
Constructors
LogMsg ID SmtpdState LogEvent
show/hide Instances
yell :: LogEvent -> Smtpd ()
Given a log event, construct a LogMsg and write it to the monad's log stream with tell. Every log event contains the current SmtpdState and the "SessionID".
data LogEvent
Constructors
Msg String
StartSession
EndSession
Input String
Output String
AcceptConn SockAddr
DropConn SockAddr
UserShutdown
CaughtException Exception
CaughtIOError IOException
StartEventHandler String Event
EventHandlerResult String Event SmtpCode
CurrentState
AssignMailID ID
show/hide Instances
Exception Handling
fallback
::
=> Smtpd acomputation to run
-> Smtpd afallback function
-> Smtpd a
Run a computation and fall back to the second if the first throws an exception. The error is logged. An exception in the second computation will propagate.
bracketOnError
::
=> IO acomputation to run first ("acquire resource")
-> a -> IO bcomputation to run last ("release resource")
-> a -> IO ccomputation to run in-between
-> IO c
Like bracket, but only performs the final action if there was an exception raised by the in-between computation. GHC 6.5 provides this function in Control.Exception.
Resource Management
acquire :: ((a -> IO b) -> IO b) -> IO (MVar a)
Convert bracket-style resource management to allocate/free style. We need this, because we have to acquire resources that leave the scope in which they were allocated. Yeah, callback-driven I/O does that to functional programs. Anyway, the resource will be gone once you empty the MVar (or when it falls out of scope). So use only withMVar and friends to access the value.
release :: MVar a -> IO ()
Let go of a resource allocated with acquire.
Produced by Haddock version 2.1.0