{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE StandaloneDeriving #-}
module MusicBrainz.Email
( Email(..)
, Template(..)
-- * Messaging Setup
, establishRabbitMqConfiguration
-- * Exchanges
, outboxExchange
, failureExchange
-- * Routing keys
, invalidKey
, unroutableKey
-- * Queues
, outboxQueue
, invalidQueue
, unroutableQueue
-- * Queueing emails
, enqueueEmail
) where
--------------------------------------------------------------------------------
import GHC.Generics (Generic)
--------------------------------------------------------------------------------
import qualified Data.Aeson as Aeson
import qualified Data.Text as Text
import qualified Network.AMQP as AMQP
import qualified Network.Mail.Mime as Mail
--------------------------------------------------------------------------------
deriving instance Eq Mail.Address
deriving instance Generic Mail.Address
deriving instance Show Mail.Address
data Email = Email
{ emailTemplate :: Template
, emailTo :: Mail.Address
, emailFrom :: Mail.Address
}
deriving (Eq, Generic, Show)
instance Aeson.FromJSON Mail.Address
instance Aeson.FromJSON Email
instance Aeson.ToJSON Mail.Address
instance Aeson.ToJSON Email
--------------------------------------------------------------------------------
data Template = PasswordReset { passwordResetEditor :: Text.Text }
deriving (Eq, Generic, Show)
instance Aeson.FromJSON Template
instance Aeson.ToJSON Template
--------------------------------------------------------------------------------
outboxExchange, failureExchange :: String
invalidKey, unroutableKey :: String
outboxQueue, unroutableQueue, invalidQueue :: String
outboxExchange = "outbox"
failureExchange = "failure"
invalidKey = "invalid"
unroutableKey = "unroutable"
outboxQueue = "outbox"
invalidQueue = "outbox.invalid"
unroutableQueue = "outbox.unroutable"
--------------------------------------------------------------------------------
establishRabbitMqConfiguration :: AMQP.Channel -> IO ()
establishRabbitMqConfiguration rabbitMq = do
AMQP.declareExchange rabbitMq
AMQP.newExchange { AMQP.exchangeName = outboxExchange
, AMQP.exchangeType = "fanout"
}
AMQP.declareExchange rabbitMq
AMQP.newExchange { AMQP.exchangeName = failureExchange
, AMQP.exchangeType = "direct"
}
AMQP.declareQueue rabbitMq
AMQP.newQueue { AMQP.queueName = outboxQueue }
AMQP.declareQueue rabbitMq
AMQP.newQueue { AMQP.queueName = invalidQueue }
AMQP.declareQueue rabbitMq
AMQP.newQueue { AMQP.queueName = unroutableQueue }
AMQP.bindQueue rabbitMq outboxQueue outboxExchange ""
AMQP.bindQueue rabbitMq invalidQueue failureExchange invalidKey
AMQP.bindQueue rabbitMq unroutableQueue failureExchange unroutableKey
--------------------------------------------------------------------------------
enqueueEmail :: AMQP.Channel -> Email -> IO ()
enqueueEmail rabbitMq email =
AMQP.publishMsg rabbitMq outboxExchange ""
AMQP.newMsg
{ AMQP.msgBody = Aeson.encode email
, AMQP.msgDeliveryMode = Just AMQP.Persistent
}