1 -- |Email functions and data types.
6 import Control.Concurrent
7 import Control.Exception (evaluate)
8 import Data.List (intercalate)
9 import Data.Time (formatTime, getZonedTime)
11 import System.Locale (defaultTimeLocale, rfc822DateFormat)
13 import System.IO (hClose, hGetContents, hPutStr)
18 -- |A crude model of an RFC821 email message.
19 data Message = Message { headers :: [Header],
26 -- |The default headers attached to each message.
27 -- The MIME junk is needed for UTF-8 to work properly.
28 -- Note that your mail server should support the 8BITMIME extension.
29 default_headers :: [Header]
30 default_headers = ["MIME-Version: 1.0",
31 "Content-Type: text/plain; charset=UTF-8",
32 "Content-Transfer-Encoding: 8bit"]
34 -- |Showing a message will print it in roughly RFC-compliant
35 -- form. This form is sufficient for handing the message off to
37 instance Show Message where
39 concat [ if (length (headers m) == 0) then "" else (intercalate "\n" (headers m)) ++ "\n",
40 "Subject: " ++ (subject m) ++ "\n",
41 "From: " ++ (from m) ++ "\n",
42 "To: " ++ (to m) ++ "\n",
48 -- |Pad a string on the left with zeros until the entire string has
50 pad_left :: String -> Int -> String
52 | n < (length str) = str
53 | otherwise = (replicate num_zeros '0') ++ str
54 where num_zeros = n - (length str)
58 -- | Constructs a 'String' in RFC822 date format for the current
60 rfc822_now :: IO String
63 return $ formatTime defaultTimeLocale rfc822DateFormat date
67 -- |Takes a message as an argument, and passes it to the system's
69 sendmail :: Message -> IO (String, String, ExitCode)
71 let sendmail_args = ["-f",
74 (inh, outh, errh, ph) <-
75 runInteractiveProcess "/usr/bin/sendmail" sendmail_args Nothing Nothing
78 outs <- hGetContents outh
81 errs <- hGetContents errh
83 _ <- forkIO $ hPutStr inh (show message) >> hClose inh
84 _ <- forkIO $ evaluate (length outs) >> putMVar outm ()
85 _ <- forkIO $ evaluate (length errs) >> putMVar errm ()
90 ec <- waitForProcess ph
91 return (outs, errs, ec)
94 -- |The 'sendmail' function returns a three-tuple of its outputs,
95 -- errors, and exit codes. This function pretty-prints one of those
97 print_sendmail_result :: (String, String, ExitCode) -> IO ()
98 print_sendmail_result (outs, errs, ec) = do
100 ExitSuccess -> return ()
101 _ -> putStrLn $ concat ["Output: " ++ outs,
102 "\nErrors: " ++ errs,
103 "\nExit Code: " ++ (show ec)]