ismtp 2.0.3 → 3.0.1
raw patch · 11 files changed
+116/−126 lines, 11 filesdep −unixdep ~netlinessetup-changedPVP ok
version bump matches the API change (PVP)
Dependencies removed: unix
Dependency ranges changed: netlines
API changes (from Hackage documentation)
- Network.Smtp.Connect: ignoreSigPipe :: IO ()
- Network.Smtp.Connect: withIgnoredSigPipe :: IO a -> IO a
- Network.Smtp.Monad: runMailT_ :: (Applicative m, MonadIO m) => Handle -> StringMailT (Either SomeException a) m a -> m a
- Network.Smtp.Tools: netLine :: Monad m => Int -> Iteratee ByteString m (Maybe ByteString)
- Network.Smtp.Tools: netLines :: Monad m => Int -> Enumeratee ByteString ByteString m b
- Network.Smtp.Tools: responseLines :: Monad m => Int -> Int -> Iteratee SmtpResponse m b -> Iteratee ByteString m b
- Network.Smtp.Types: type StringMailT r m = Iteratee ByteString (StateT r MailConfig m)
+ Network.Smtp.Monad: mailSetWriteTimeout :: Int -> MailT r m ()
+ Network.Smtp.Session: verify :: MonadIO m => ByteString -> MailT r m Bool
+ Network.Smtp.Simple: mailTimeoutIO :: SendMail -> Int
+ Network.Smtp.Types: SmtpVerifyCmd :: ByteString -> SmtpCommand
+ Network.Smtp.Types: mailWriteTimeout :: MailConfig -> Int
- Network.Smtp.Connect: withMxConn :: (Applicative m, DnsMonad m, MonadPeelIO m) => Domain -> Bool -> MailT (Either SomeException a) m a -> m a
+ Network.Smtp.Connect: withMxConn :: (Applicative m, DnsMonad m, MonadPeelIO m) => Domain -> Bool -> MailT a m a -> m a
- Network.Smtp.Connect: withSmtpConn :: (Applicative m, MonadPeelIO m) => HostName -> PortID -> MailT (Either SomeException a) m a -> m a
+ Network.Smtp.Connect: withSmtpConn :: (Applicative m, MonadPeelIO m) => HostName -> PortID -> MailT a m a -> m a
- Network.Smtp.Monad: runMailT :: (Applicative m, Monad m) => Handle -> StringMailT (Either SomeException a) m a -> m (Either SomeException a)
+ Network.Smtp.Monad: runMailT :: (Applicative m, Monad m) => Int -> Int -> Handle -> MailT a m a -> Iteratee ByteString m a
- Network.Smtp.Simple: SendMail :: Int -> Handle -> Int -> Int -> Handle -> Int -> SendMail
+ Network.Smtp.Simple: SendMail :: Int -> Handle -> Int -> Int -> Handle -> Int -> Int -> SendMail
- Network.Smtp.Simple: sendMail :: (Applicative m, MonadIO m) => SendMail -> MailT (Either SomeException a) m a -> m (Either SomeException a)
+ Network.Smtp.Simple: sendMail :: (Applicative m, MonadIO m) => SendMail -> MailT a m a -> m (Either SomeException a)
- Network.Smtp.Simple: sendMail_ :: (Applicative m, MonadIO m) => SendMail -> MailT (Either SomeException a) m a -> m a
+ Network.Smtp.Simple: sendMail_ :: (Applicative m, MonadIO m) => SendMail -> MailT a m a -> m a
- Network.Smtp.Types: MailConfig :: Set Extension -> Handle -> MailConfig
+ Network.Smtp.Types: MailConfig :: Set Extension -> Handle -> Int -> MailConfig
- Network.Smtp.Types: type Mail r a = MailT r IO a
+ Network.Smtp.Types: type Mail r = MailT r IO
- Network.Smtp.Types: type MailT r m = Iteratee SmtpResponse (StateT r MailConfig m)
+ Network.Smtp.Types: type MailT r m = StateT r MailConfig (Iteratee SmtpResponse m)
Files
- LICENSE +1/−1
- Network/Smtp.hs +12/−7
- Network/Smtp/Connect.hs +7/−29
- Network/Smtp/Ext/Auth.hs +1/−2
- Network/Smtp/Monad.hs +38/−26
- Network/Smtp/Session.hs +24/−4
- Network/Smtp/Simple.hs +14/−15
- Network/Smtp/Tools.hs +1/−18
- Network/Smtp/Types.hs +10/−16
- Setup.lhs +1/−1
- ismtp.cabal +7/−7
LICENSE view
@@ -1,5 +1,5 @@ ismtp license-Copyright (c) 2010, Ertugrul Soeylemez+Copyright (c) 2011, Ertugrul Soeylemez All rights reserved.
Network/Smtp.hs view
@@ -1,9 +1,8 @@ -- | -- Module: Network.SMTP--- Copyright: (c) 2010 Ertugrul Soeylemez+-- Copyright: (c) 2011 Ertugrul Soeylemez -- License: BSD3 -- Maintainer: Ertugrul Soeylemez <es@ertes.de>--- Stability: experimental -- -- This package provides a monad transformer for fast, incremental ESMTP -- sessions, with which you can, among other things, send emails. Here@@ -22,6 +21,12 @@ -- > mailDataStr content -- > quit --+-- The @r@ type parameter is related to contstuff's 'StateT' monad+-- transformer, which is used internally. If you don't know what to do,+-- just leave it fully polymorphic like in the example above. You only+-- need to care about @r@, if you want to make use of the CPS features+-- of 'StateT'.+-- -- The simplest interfaces to running SMTP sessions are 'withSmtpConn' -- and 'withMxConn'. The latter does a DNS lookup for the given domain -- to discover the MX server and connect to it. The former simply@@ -34,11 +39,11 @@ -- and other purposes. -- -- Finally you can use the low level interface for running sessions.--- See the 'runMailT' function along with 'enumHandleTimeout' and--- 'responseLines'. This way you get the full power of iteratees. For--- example you can run the session through a custom enumeratee, which--- enables you to wrap the session in another protocol (e.g. proxy--- servers or SSL).+-- See the 'runMailT' function along with 'enumHandleTimeout'. This way+-- you get the full power of iteratees. For example you can run the+-- session through a custom enumeratee, which enables you to wrap the+-- session in another protocol (e.g. proxy servers or SSL). This is not+-- possible with the higher level functions. module Network.Smtp ( -- * Reexports
Network/Smtp/Connect.hs view
@@ -1,9 +1,8 @@ -- | -- Module: Network.Smtp.Connect--- Copyright: (c) 2010 Ertugrul Soeylemez+-- Copyright: (c) 2011 Ertugrul Soeylemez -- License: BSD3 -- Maintainer: Ertugrul Soeylemez <es@ertes.de>--- Stability: experimental -- -- High level interfaces for networking. @@ -15,11 +14,7 @@ withSmtpConn, -- * Initialization- withIsmtp,-- -- * Utility functions- ignoreSigPipe,- withIgnoredSigPipe+ withIsmtp ) where @@ -31,32 +26,14 @@ import Network.Smtp.Simple import Network.Smtp.Types import System.IO-import System.Posix.Signals --- | Disable the /SIGPIPE/ signal, so our program doesn't die on broken--- pipes.--ignoreSigPipe :: IO ()-ignoreSigPipe = () <$ installHandler sigPIPE Ignore Nothing----- | Run the given computation with the /SIGPIPE/ signal disabled, so--- our program doesn't die on broken pipes.--withIgnoredSigPipe :: IO a -> IO a-withIgnoredSigPipe =- Ex.bracket (installHandler sigPIPE Ignore Nothing)- (\old -> installHandler sigPIPE old Nothing)- . const-- -- | Perform some useful (but not necessarily needed) initialization -- like disabling SIGPIPE and initializing sockets, run the given -- computation and then clean up. withIsmtp :: IO a -> IO a-withIsmtp = withSocketsDo . withIgnoredSigPipe+withIsmtp = withSocketsDo -- | Interface to 'withSmtpConn', which connects to the first mail@@ -66,7 +43,7 @@ withMxConn :: (Applicative m, DnsMonad m, MonadPeelIO m) =>- Domain -> Bool -> MailT (Either SomeException a) m a -> m a+ Domain -> Bool -> MailT a m a -> m a withMxConn domain fallback c = do mMx <- resolveMX domain hostname <-@@ -81,8 +58,9 @@ -- Note that there is also 'withMxConn', which resolves the MX server of -- the given domain. -withSmtpConn :: forall a m. (Applicative m, MonadPeelIO m) =>- HostName -> PortID -> MailT (Either SomeException a) m a -> m a+withSmtpConn ::+ forall a m. (Applicative m, MonadPeelIO m) =>+ HostName -> PortID -> MailT a m a -> m a withSmtpConn host port c = Ex.bracket connect (liftIO . hClose) $ \h -> do sendMail_ (defSendMail h h) c
Network/Smtp/Ext/Auth.hs view
@@ -1,9 +1,8 @@ -- | -- Module: Network.Smtp.Ext.Auth--- Copyright: (c) 2010 Ertugrul Soeylemez+-- Copyright: (c) 2011 Ertugrul Soeylemez -- License: BSD3 -- Maintainer: Ertugrul Soeylemez <es@ertes.de>--- Stability: experimental -- -- This module implements the authentication extension to SMTP as -- defined in RFC 2554.
Network/Smtp/Monad.hs view
@@ -1,9 +1,8 @@ -- | -- Module: Network.Smtp.Monad--- Copyright: (c) 2010 Ertugrul Soeylemez+-- Copyright: (c) 2011 Ertugrul Soeylemez -- License: BSD3 -- Maintainer: Ertugrul Soeylemez <es@ertes.de>--- Stability: experimental -- -- This module implements a monad for SMTP sessions. @@ -12,8 +11,10 @@ module Network.Smtp.Monad ( -- * Running sessions runMailT,- runMailT_, + -- * Manipulating sessions+ mailSetWriteTimeout,+ -- * Utility functions mailError, mailPut,@@ -24,12 +25,13 @@ import qualified Data.Set as S import Control.ContStuff-import Control.Exception.Peel as Ex+--import Control.Exception.Peel as Ex import Data.ByteString (ByteString) import Data.ByteString.Char8 () import Data.Enumerator as E-import Data.Enumerator.Binary as EB+--import Data.Enumerator.Binary as EB import Data.Enumerator.List as EL+import Data.Enumerator.NetLines import Data.Vector (Vector) import Network.Smtp.Tools import Network.Smtp.Types@@ -43,15 +45,17 @@ Monad m => SmtpCommand -> String -> Integer -> Vector ByteString -> MailT r m a mailError cmd errMsg code msgs =- throwError $ SmtpException errMsg cmd code (formatMsgs msgs)+ lift . throwError $ SmtpException errMsg cmd code (formatMsgs msgs) -- | Send a stream of 'ByteString's to the SMTP server. mailPut :: MonadIO m => Enumerator ByteString (MailT r m) () -> MailT r m () mailPut enum = do- h <- lift $ getField mailHandle- run (enum $$ EB.iterHandle h) >>= either throwError return+ h <- getField mailHandle+ timeout <- getField mailWriteTimeout+ run (enum $$ iterHandleTimeout timeout h) >>=+ either (lift . throwError) return -- | Send a list of 'ByteString's followed an SMTP line terminator to@@ -61,30 +65,38 @@ mailPutLn strs = mailPut $ concatEnums [enumList 16 strs, enumList 1 ["\r\n"]] +-- | Set the write timeout for the current mail session in milliseconds.++mailSetWriteTimeout :: Int -> MailT r m ()+mailSetWriteTimeout timeout =+ modify (\cfg -> cfg { mailWriteTimeout = timeout })++ -- | Retrieve the next SMTP response. Throw an 'Error', if there is no -- next response. nextResponse :: Monad m => MailT r m SmtpResponse-nextResponse = do- let smtpError = throwError $ userError "Connection closed prematurely"- EL.head >>= maybe smtpError return+nextResponse =+ lift $ do+ let smtpError = throwError $ userError "Connection closed prematurely"+ EL.head >>= maybe smtpError return --- | Run a mail session computation with the given output handle. The--- input is supplied by an 'Enumerator' such as 'enumHandleTimeout'.+-- | Run a mail session computation with the given protocol line length+-- limit (first argument), response lines limit (second argument) and+-- output handle. The input is supplied by an 'Enumerator' such as+-- 'enumHandleTimeout'.+--+-- The inner iteratee uses 'SmtpResponse' as its input type and hence+-- expects the 'netLines' and 'smtpResponses' enumeratees to be applied.+-- This is done by 'runMailT' for you, so the resulting iteratee takes a+-- raw 'ByteString' stream as input. runMailT :: (Applicative m, Monad m) =>- Handle -> StringMailT (Either SomeException a) m a ->- m (Either SomeException a)-runMailT h c =+ Int -> Int -> Handle -> MailT a m a ->+ Iteratee ByteString m a+runMailT maxLine maxMsgs h c = let cfg = MailConfig { mailExtensions = S.empty,- mailHandle = h }- in evalStateT cfg . run $ c----- | Run a mail session computation using 'runMailT' and throw an--- exception on error.--runMailT_ :: (Applicative m, MonadIO m) =>- Handle -> StringMailT (Either SomeException a) m a -> m a-runMailT_ h = runMailT h >=> either Ex.throwIO return+ mailHandle = h,+ mailWriteTimeout = 15000 }+ in netLines maxLine =$ smtpResponses maxMsgs =$ evalStateT cfg c
Network/Smtp/Session.hs view
@@ -1,9 +1,8 @@ -- | -- Module: Network.Smtp.Session--- Copyright: (c) 2010 Ertugrul Soeylemez+-- Copyright: (c) 2011 Ertugrul Soeylemez -- License: BSD3 -- Maintainer: Ertugrul Soeylemez <es@ertes.de>--- Stability: experimental -- -- SMTP session computations. @@ -18,6 +17,7 @@ quit, rcptTo, reset,+ verify, waitForWelcome ) where@@ -44,7 +44,7 @@ L.drop 1 . V.toList $ msgs case code of- 250 -> lift $ modify (\cfg -> cfg { mailExtensions = exts })+ 250 -> modify (\cfg -> cfg { mailExtensions = exts }) 500 -> tryHelo 502 -> tryHelo 554 -> tryHelo@@ -94,7 +94,8 @@ _ -> mailError (SmtpMailFromCmd from) "MAIL FROM rejected" code msgs --- | Send /QUIT/ command.+-- | Send /QUIT/ command. Please note: This iteratee violates the+-- standard by recognizing a 250 result code as success. quit :: MonadIO m => MailT r m () quit = do@@ -102,6 +103,7 @@ SmtpResponse code msgs <- nextResponse case code of 221 -> return ()+ 250 -> return () _ -> mailError SmtpQuitCmd "Quit rejected" code msgs @@ -125,6 +127,24 @@ case code of 250 -> return () _ -> mailError SmtpResetCmd "RSET rejected" code msgs+++-- | Send the /VRFY/ command to find out, whether the mail exchangers+-- knows the given user. Nowadays most mail exchangers disable this+-- command for security reasons.+--+-- Please note that many SMTP servers will give you false positives or+-- false negatives to prevent spamming attempts. It is not recommended+-- to use this command.++verify :: MonadIO m => ByteString -> MailT r m Bool+verify checkUser = do+ mailPutLn ["VRFY ", checkUser]+ SmtpResponse code msgs <- nextResponse+ case code of+ 250 -> return True+ 550 -> return False+ _ -> mailError (SmtpVerifyCmd checkUser) "VRFY rejected" code msgs -- | Wait for the welcome greeting from the SMTP server.
Network/Smtp/Simple.hs view
@@ -1,9 +1,8 @@ -- | -- Module: Network.Smtp.Simple--- Copyright: (c) 2010 Ertugrul Soeylemez+-- Copyright: (c) 2011 Ertugrul Soeylemez -- License: BSD3 -- Maintainer: Ertugrul Soeylemez <es@ertes.de>--- Stability: experimental -- -- Higher level interface to ismtp. @@ -34,7 +33,8 @@ mailMaxLine :: Int, -- ^ Maximum line length (flood protection). mailMaxMessages :: Int, -- ^ Maximum number of messages (flood protection). mailOutputHandle :: Handle, -- ^ Output handle (e.g. sending socket).- mailTimeout :: Int -- ^ Receive timeout in milliseconds.+ mailTimeout :: Int, -- ^ Session timeout in milliseconds.+ mailTimeoutIO :: Int -- ^ Read/write timeout in milliseconds. } @@ -48,30 +48,29 @@ mailMaxLine = 512, mailMaxMessages = 128, mailOutputHandle = outH,- mailTimeout = 60000 }+ mailTimeout = 60000,+ mailTimeoutIO = 15000 } -- | Execute the given mail session using the supplied configuration.--- Please note that both handles must be set to binary mode and the--- input handle should be unbuffered ('NoBuffering').+-- Please note that both handles must be set to binary mode and be+-- unbuffered. See 'hSetBuffering' and 'hSetBinaryMode'. sendMail :: (Applicative m, MonadIO m) =>- SendMail -> MailT (Either SomeException a) m a ->- m (Either SomeException a)-sendMail cfg c =+ SendMail -> MailT a m a -> m (Either SomeException a)+sendMail cfg c = do let SendMail { mailBufferSize = bufSize, mailInputHandle = inH, mailMaxLine = maxLine, mailMaxMessages = maxMsgs, mailOutputHandle = outH,- mailTimeout = timeout } = cfg- in runMailT outH (enumHandleTimeout bufSize timeout inH $$- responseLines maxLine maxMsgs c)+ mailTimeout = timeout,+ mailTimeoutIO = ioTimeout } = cfg+ run $ enumHandleTimeout bufSize timeout inH $$+ runMailT maxLine maxMsgs outH (mailSetWriteTimeout ioTimeout >> c) -- | Like 'sendMail', but throws an exception on error. -sendMail_ :: (Applicative m, MonadIO m) =>- SendMail -> MailT (Either SomeException a) m a ->- m a+sendMail_ :: (Applicative m, MonadIO m) => SendMail -> MailT a m a -> m a sendMail_ cfg = sendMail cfg >=> either throwIO return
Network/Smtp/Tools.hs view
@@ -1,9 +1,8 @@ -- | -- Module: Network.Smtp.Tools--- Copyright: (c) 2010 Ertugrul Soeylemez+-- Copyright: (c) 2011 Ertugrul Soeylemez -- License: BSD3 -- Maintainer: Ertugrul Soeylemez <es@ertes.de>--- Stability: experimental -- -- Helper functions and types. @@ -12,9 +11,6 @@ module Network.Smtp.Tools ( enumHandleTimeout, formatMsgs,- netLine,- netLines,- responseLines, smtpResponseLine, smtpResponse, smtpResponses,@@ -63,19 +59,6 @@ 45 -> return True 32 -> return False _ -> empty----- | Composition of all 'Enumeratee's, which are needed to convert a raw--- 'ByteString' stream to an 'SmtpResponse' stream. This function takes--- the maximum line length and the response line limit as its first two--- parameters.--responseLines :: Monad m =>- Int -> Int -> Iteratee SmtpResponse m b -> Iteratee ByteString m b-responseLines maxLine maxMsgs c =- joinI $ netLines maxLine $$- joinI $ smtpResponses maxMsgs $$- c -- | Read the next SMTP response line from the given 'ByteString' lines
Network/Smtp/Types.hs view
@@ -1,9 +1,8 @@ -- | -- Module: Network.Smtp.Types--- Copyright: (c) 2010 Ertugrul Soeylemez+-- Copyright: (c) 2011 Ertugrul Soeylemez -- License: BSD3 -- Maintainer: Ertugrul Soeylemez <es@ertes.de>--- Stability: experimental -- -- Types used by ismtp. @@ -13,7 +12,6 @@ ( -- * Mail monad Mail, MailT,- StringMailT, -- * SMTP service extensions Extension(..),@@ -54,39 +52,35 @@ -- | The 'MailT' monad transformer encapsulates an SMTP session. -type MailT r m = Iteratee SmtpResponse (StateT r MailConfig m)----- | Convenient type alias for raw streams. Needed by--- 'Network.Smtp.Monad.runMailT'.--type StringMailT r m = Iteratee ByteString (StateT r MailConfig m)+type MailT r m = StateT r MailConfig (Iteratee SmtpResponse m) -- | The 'Mail' monad is 'MailT' over 'IO'. -type Mail r a = MailT r IO a+type Mail r = MailT r IO -- | Mail session configuration. data MailConfig = MailConfig {- mailExtensions :: Set Extension, -- ^ Supported extensions.- mailHandle :: Handle -- ^ Connection handle.+ mailExtensions :: Set Extension, -- ^ Supported extensions.+ mailHandle :: Handle, -- ^ Connection handle.+ mailWriteTimeout :: Int -- ^ Write timeout in milliseconds. } -- | Failed SMTP command (used by 'SmtpException'). data SmtpCommand- = SmtpWelcomeCmd -- ^ Waiting for welcome message.+ = SmtpDataCmd -- ^ DATA. | SmtpHelloCmd ByteString -- ^ EHLO or HELO with domain. | SmtpMailFromCmd ByteString -- ^ MAIL FROM with address.+ | SmtpQuitCmd -- ^ QUIT. | SmtpRcptToCmd ByteString -- ^ RCPT TO with address.- | SmtpDataCmd -- ^ DATA. | SmtpResetCmd -- ^ RSET.- | SmtpQuitCmd -- ^ QUIT.+ | SmtpVerifyCmd ByteString -- ^ VRFY with the given user name.+ | SmtpWelcomeCmd -- ^ Waiting for welcome message. -- | SMTP exception.
Setup.lhs view
@@ -1,5 +1,5 @@ ismtp setup script-Copyright (C) 2010, Ertugrul Soeylemez+Copyright (C) 2011, Ertugrul Soeylemez Please see the LICENSE file for terms and conditions of use, modification and distribution of this package, including this file.
ismtp.cabal view
@@ -1,14 +1,14 @@ Name: ismtp-Version: 2.0.3+Version: 3.0.1 Category: Network Synopsis: Advanced ESMTP library Maintainer: Ertugrul Söylemez <es@ertes.de> Author: Ertugrul Söylemez <es@ertes.de>-Copyright: (c) 2010 Ertugrul Söylemez+Copyright: (c) 2011 Ertugrul Söylemez License: BSD3 License-file: LICENSE Build-type: Simple-Stability: experimental+Stability: beta Cabal-version: >= 1.6 Description: @@ -24,9 +24,8 @@ dnscache >= 1.0.1, enumerator >= 0.4.7, monad-peel >= 0.1,- netlines >= 0.3.0,+ netlines >= 0.4.3, network >= 2.2.1.7,- unix >= 2.4.0.2, vector >= 0.7.0.1 GHC-Options: -W Exposed-modules:@@ -39,8 +38,9 @@ Network.Smtp.Tools Network.Smtp.Types --- Executable test+-- Executable ismtp-test -- Build-depends:--- base >= 4 && <= 5+-- base >= 4 && <= 5,+-- unix -- GHC-Options: -W -threaded -- Main-is: Test.hs