X-Git-Url: http://gitweb.michael.orlitzky.com/?a=blobdiff_plain;f=src%2FMail.hs;h=2e86a204e003ceda90bfb32994fe4e83f386ad48;hb=fdc80f514bfe9005f55768f63b619ad170ad1b56;hp=c280f1e82d2f6324385d484b6c8570af7989e041;hpb=94484087fbfe98d6735aa82798a9bf506f97fd19;p=dead%2Fhalcyon.git diff --git a/src/Mail.hs b/src/Mail.hs index c280f1e..2e86a20 100644 --- a/src/Mail.hs +++ b/src/Mail.hs @@ -1,16 +1,21 @@ +-- |Email functions and data types. + module Mail where import Control.Concurrent -import Control.Concurrent.MVar import Control.Exception (evaluate) import Data.List (intercalate) +import Data.Time (formatTime, getZonedTime) import System.Exit +import System.Locale (defaultTimeLocale, rfc822DateFormat) import System.Process -import System.IO +import System.IO (hClose, hGetContents, hPutStr) + type Header = String +-- |A crude model of an RFC821 email message. data Message = Message { headers :: [Header], subject :: String, body :: String, @@ -18,6 +23,17 @@ data Message = Message { headers :: [Header], to :: String } deriving (Eq) +-- |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 [ if (length (headers m) == 0) then "" else (intercalate "\n" (headers m)) ++ "\n", @@ -28,13 +44,35 @@ instance Show Message where (body m) ] -sendmail :: Message -> IO (String, String, ExitCode) -sendmail message = do + +-- |Pad a string on the left with zeros until the entire string has +-- length n. +pad_left :: String -> Int -> String +pad_left str n + | n < (length str) = str + | otherwise = (replicate num_zeros '0') ++ str + where num_zeros = n - (length str) + + + +-- | Constructs a 'String' in RFC822 date format for the current +-- date/time. +rfc822_now :: IO String +rfc822_now = do + date <- getZonedTime + return $ formatTime defaultTimeLocale rfc822DateFormat date + + + +-- |Takes a message as an argument, and passes it to the system's +-- sendmail (or compatible) binary. +sendmail :: FilePath -> Message -> IO (String, String, ExitCode) +sendmail sendmail_path message = do let sendmail_args = ["-f", (from 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 @@ -42,9 +80,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 @@ -53,6 +91,9 @@ sendmail message = do return (outs, errs, ec) +-- |The 'sendmail' function returns a three-tuple of its outputs, +-- 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