email-0.1: Data/EmailRepr.hs
-- vim: set encoding=utf-8 :
module Data.EmailRepr(Email(..), Message, _EMPTY_EMAIL_, encodeHeaders
,Headers, Content(..), MimePart(..), email2message) where
----------------------------------------
---- STDLIB
----------------------------------------
import Data.Time.Calendar (toGregorian)
import Data.Time.Format (formatTime)
import Data.Time.LocalTime (LocalTime(..), TimeOfDay(..), TimeZone(..), ZonedTime(..))
import System.Time (CalendarTime(..), Day(..), Month(..))
import System.Locale (defaultTimeLocale)
----------------------------------------
---- SITE-PACKAGES
----------------------------------------
import Text.ParserCombinators.Parsec.Rfc2822
(Field(..), NameAddr(..), GenericMessage(..))
import qualified Data.ByteString as BS (ByteString, empty, concat)
import Data.EmailSerializer (Message, encodeHeader, _CRLF_)
----------------------------------------
---- LOCAL
----------------------------------------
data Email = Email { em_from :: [NameAddr]
, em_to :: [NameAddr]
, em_cc :: [NameAddr]
, em_bcc :: [NameAddr]
, em_subject :: String
, em_date :: Maybe ZonedTime
, em_optionals :: Headers
, em_body :: Content
} deriving Show
_EMPTY_EMAIL_ = Email [] [] [] [] "" Nothing [] (ContentByte BS.empty)
type Headers = [(String, String)]
data Content = ContentByte BS.ByteString | ContentMime MimePart deriving Show
data MimePart = MimePart
{ mp_mime_type :: Maybe String -- text/plain \
, mp_filename :: Maybe String -- test.txt +--> Content-Type
, mp_charset :: Maybe String -- UTF-8 /
, mp_inline :: Bool -- True ----> Content-Disposition
, mp_optionals :: Headers -- [("MIME-Version", "1.0)]
, mp_content :: Content -- "foo bar"
} deriving Show
append2 :: BS.ByteString -> BS.ByteString -> BS.ByteString
append2 a b = BS.concat [a, _CRLF_, b]
encodeHeaders :: Headers -> BS.ByteString
encodeHeaders hs = foldr append2 BS.empty $ map (uncurry encodeHeader) hs
dow2ltDow :: Int -> Day
dow2ltDow day =
case day of
0 -> Sunday
1 -> Monday
2 -> Tuesday
3 -> Wednesday
4 -> Thursday
5 -> Friday
6 -> Saturday
dtMonth2ltMonth :: Int -> Month
dtMonth2ltMonth dtMonth =
case dtMonth of
1 -> January
2 -> February
3 -> March
4 -> April
5 -> May
6 -> June
7 -> July
8 -> August
9 -> September
10 -> October
11 -> November
12 -> December
zonedTimeToCalendarTime :: ZonedTime -> CalendarTime
zonedTimeToCalendarTime (ZonedTime (LocalTime day (TimeOfDay h min s)) (TimeZone tzMin tzDst tzName)) =
-- =
CalendarTime y' m' d h min s' ps wd yd tzName tzSec tzDst
where (y, m, d) = toGregorian day
y' = fromInteger y
m' = dtMonth2ltMonth m
s' = fromInteger (round s)
tzSec = tzMin * 60
wd = dow2ltDow (read $ formatTime defaultTimeLocale "%w" day)
ps = 0
yd = read $ formatTime defaultTimeLocale "%j" day
email2message :: Email -> Message
email2message (Email ef et ecc ebcc es ed eo (ContentByte eb)) =
Message fields' eb
where fromField = From ef
toField = To et
ccField = Cc ecc
bccField = Bcc ebcc
subjectField = Subject es
optionalFields = map (uncurry OptionalField) eo
fields = [fromField] ++ [toField] ++ [ccField] ++ [bccField] ++
[subjectField] ++ optionalFields
fields' = case ed of
Just date ->
fields ++ [dateField]
where format = "%a, %d %b %Y %H:%M:%S %z"
dateField = Date (zonedTimeToCalendarTime date)
Nothing -> fields