X-Git-Url: http://gitweb.michael.orlitzky.com/?p=dead%2Fhalcyon.git;a=blobdiff_plain;f=src%2FMail.hs;h=3f519ccd8f0d0e22714a248a6595af378ca947eb;hp=ba605f977673ae3a76694888131767bfd383e255;hb=0ed071e75268da9ba8273d5c13817fa1297c94e2;hpb=69b8af30f49aaad0f5c051998d2556b9ec291df7 diff --git a/src/Mail.hs b/src/Mail.hs index ba605f9..3f519cc 100644 --- a/src/Mail.hs +++ b/src/Mail.hs @@ -1,19 +1,27 @@ -- |Email functions and data types. -module Mail +module Mail ( + Message(..), + default_headers, + print_sendmail_result, + rfc822_now, + sendmail ) where -import Control.Concurrent -import Control.Concurrent.MVar -import Control.Exception (evaluate) -import Data.List (intercalate) -import System.Exit -import System.Process -import System.IO +import Control.Concurrent ( forkIO, newEmptyMVar, putMVar, readMVar ) +import Control.Exception ( evaluate ) +import Control.Monad ( liftM ) +import Data.List ( intercalate ) +import Data.Time ( formatTime, getZonedTime ) +import System.Exit ( ExitCode(..) ) +import System.Locale ( defaultTimeLocale, rfc822DateFormat ) +import System.Process ( runInteractiveProcess, waitForProcess ) +import System.IO ( hClose, hGetContents, hPutStr ) + type Header = String --- |A crude model of an RFC821 email message. +-- | A crude model of an RFC821 email message. data Message = Message { headers :: [Header], subject :: String, body :: String, @@ -21,28 +29,52 @@ data Message = Message { headers :: [Header], to :: String } deriving (Eq) --- |Showing a message will print it in roughly RFC-compliant --- form. This form is sufficient for handing the message off to --- sendmail. -instance Show Message where - show m = - concat [ if (length (headers m) == 0) then "" else (intercalate "\n" (headers m)) ++ "\n", - "Subject: " ++ (subject m) ++ "\n", - "From: " ++ (from m) ++ "\n", - "To: " ++ (to m) ++ "\n", - "\n", - (body m) ] +-- | The default headers attached to each message. The MIME junk is +-- needed for UTF-8 to work properly. Note that your mail server +-- should support the 8BITMIME extension. +default_headers :: [Header] +default_headers = ["MIME-Version: 1.0", + "Content-Type: text/plain; charset=UTF-8", + "Content-Transfer-Encoding: 8bit"] + +-- | Showing a message will print it in roughly RFC-compliant +-- form. This form is sufficient for handing the message off to +-- sendmail (or compatible). +instance Show Message where + show m = + concat [ formatted_headers, + "Subject: " ++ (subject m) ++ "\n", + "From: " ++ (from m) ++ "\n", + "To: " ++ (to m) ++ "\n", + "\n", + (body m) ] + where + formatted_headers = + if null (headers m) + then "" + else (intercalate "\n" (headers m)) ++ "\n" + + + +-- | Constructs a 'String' in RFC822 date format for the current +-- date/time. +rfc822_now :: IO String +rfc822_now = + liftM (formatTime defaultTimeLocale rfc822DateFormat) getZonedTime + + -- |Takes a message as an argument, and passes it to the system's --- sendmail binary. -sendmail :: Message -> IO (String, String, ExitCode) -sendmail message = do +-- sendmail (or compatible) binary. +sendmail :: FilePath -> Message -> IO (String, String, ExitCode) +sendmail sendmail_path message = do let sendmail_args = ["-f", - (from message)] + (from message), + (to message)] (inh, outh, errh, ph) <- - runInteractiveProcess "/usr/bin/sendmail" sendmail_args Nothing Nothing + runInteractiveProcess sendmail_path sendmail_args Nothing Nothing outm <- newEmptyMVar outs <- hGetContents outh @@ -50,9 +82,9 @@ sendmail message = do errm <- newEmptyMVar errs <- hGetContents errh - forkIO $ hPutStr inh (show message) >> hClose inh - forkIO $ evaluate (length outs) >> putMVar outm () - forkIO $ evaluate (length errs) >> putMVar errm () + _ <- forkIO $ hPutStr inh (show message) >> hClose inh + _ <- forkIO $ evaluate (length outs) >> putMVar outm () + _ <- forkIO $ evaluate (length errs) >> putMVar errm () readMVar outm readMVar errm @@ -65,9 +97,9 @@ sendmail message = do -- errors, and exit codes. This function pretty-prints one of those -- three-tuples. print_sendmail_result :: (String, String, ExitCode) -> IO () -print_sendmail_result (outs, errs, ec) = do - case ec of - ExitSuccess -> return () - _ -> putStrLn $ concat ["Output: " ++ outs, - "\nErrors: " ++ errs, - "\nExit Code: " ++ (show ec)] +print_sendmail_result (outs, errs, ec) = + case ec of + ExitSuccess -> return () + _ -> putStrLn $ concat ["Output: " ++ outs, + "\nErrors: " ++ errs, + "\nExit Code: " ++ (show ec)]