chore(email): option to keep sender fixed and use replyto instead
This commit is contained in:
parent
2fb4dce95f
commit
272eb73203
@ -19,6 +19,7 @@ mail-from:
|
|||||||
name: "_env:MAILFROM_NAME:Uni2work"
|
name: "_env:MAILFROM_NAME:Uni2work"
|
||||||
email: "_env:MAILFROM_EMAIL:uniworx@localhost"
|
email: "_env:MAILFROM_EMAIL:uniworx@localhost"
|
||||||
mail-object-domain: "_env:MAILOBJECT_DOMAIN:localhost"
|
mail-object-domain: "_env:MAILOBJECT_DOMAIN:localhost"
|
||||||
|
mail-sender-fixed: "_env:MAILSENDER_FIXED:True"
|
||||||
#mail-verp:
|
#mail-verp:
|
||||||
# separator: "_env:VERP_SEPARATOR:+"
|
# separator: "_env:VERP_SEPARATOR:+"
|
||||||
# prefix: "_env:VERP_PREFIX:bounce"
|
# prefix: "_env:VERP_PREFIX:bounce"
|
||||||
|
|||||||
@ -174,9 +174,10 @@ instance YesodAuthPersist UniWorX where
|
|||||||
|
|
||||||
|
|
||||||
instance YesodMail UniWorX where
|
instance YesodMail UniWorX where
|
||||||
defaultFromAddress = getsYesod $ view _appMailFrom
|
defaultFromAddress = getsYesod $ view _appMailFrom
|
||||||
envelopeFromAddress = getsYesod $ view _appMailEnvelopeFrom
|
envelopeFromAddress = getsYesod $ view _appMailEnvelopeFrom
|
||||||
mailObjectIdDomain = getsYesod $ view _appMailObjectDomain
|
mailObjectIdDomain = getsYesod $ view _appMailObjectDomain
|
||||||
|
fixedSenderInDomain = getsYesod $ view _appMailFixedDomainSender
|
||||||
mailDateTZ = return appTZ
|
mailDateTZ = return appTZ
|
||||||
mailSmtp act = do
|
mailSmtp act = do
|
||||||
pool <- maybe (throwM MailNotAvailable) return =<< getsYesod appSmtpPool
|
pool <- maybe (throwM MailNotAvailable) return =<< getsYesod appSmtpPool
|
||||||
|
|||||||
@ -31,7 +31,7 @@ dispatchJobSendCourseCommunication jRecipientEmail jAllRecipientAddresses jCours
|
|||||||
MsgRenderer mr <- getMailMsgRenderer
|
MsgRenderer mr <- getMailMsgRenderer
|
||||||
|
|
||||||
void $ setMailObjectUUID jMailObjectUUID
|
void $ setMailObjectUUID jMailObjectUUID
|
||||||
_mailReplyTo .= userAddressFrom sender
|
_mailFrom .= userAddressFrom sender
|
||||||
addMailHeader "Cc" [st|#{mr MsgCommUndisclosedRecipients}:;|]
|
addMailHeader "Cc" [st|#{mr MsgCommUndisclosedRecipients}:;|]
|
||||||
addMailHeader "Auto-Submitted" "no"
|
addMailHeader "Auto-Submitted" "no"
|
||||||
setSubjectI . prependCourseTitle courseTerm courseSchool courseShorthand $ maybe (SomeMessage MsgCommCourseSubject) SomeMessage jSubject
|
setSubjectI . prependCourseTitle courseTerm courseSchool courseShorthand $ maybe (SomeMessage MsgCommCourseSubject) SomeMessage jSubject
|
||||||
|
|||||||
35
src/Mail.hs
35
src/Mail.hs
@ -49,6 +49,7 @@ import qualified Network.Mail.Mime as Mime (addPart)
|
|||||||
import Settings.Mime
|
import Settings.Mime
|
||||||
|
|
||||||
import Data.Monoid (Last(..))
|
import Data.Monoid (Last(..))
|
||||||
|
-- import Control.Monad.Trans.Maybe (MaybeT(..))
|
||||||
import Control.Monad.Trans.RWS (RWST(..))
|
import Control.Monad.Trans.RWS (RWST(..))
|
||||||
import Control.Monad.Trans.State (StateT(..), execStateT, mapStateT)
|
import Control.Monad.Trans.State (StateT(..), execStateT, mapStateT)
|
||||||
import Control.Monad.Trans.Writer (execWriter, execWriterT, Writer)
|
import Control.Monad.Trans.Writer (execWriter, execWriterT, Writer)
|
||||||
@ -71,7 +72,7 @@ import qualified Data.Text.Lazy.Builder as LTB
|
|||||||
import qualified Data.ByteString.Lazy as LBS
|
import qualified Data.ByteString.Lazy as LBS
|
||||||
import qualified Data.ByteString as BS
|
import qualified Data.ByteString as BS
|
||||||
|
|
||||||
import Utils (MsgRendererS(..), MonadSecretBox(..), YamlValue, maybeMonoid, insertAssoc)
|
import Utils (MsgRendererS(..), MonadSecretBox(..), YamlValue, maybeMonoid, insertAssoc, maybeT, guardM)
|
||||||
import Utils.Lens.TH
|
import Utils.Lens.TH
|
||||||
|
|
||||||
import Control.Lens hiding (from)
|
import Control.Lens hiding (from)
|
||||||
@ -144,7 +145,7 @@ _mailReplyTo' = _mailHeaders . _headerReplyTo'
|
|||||||
|
|
||||||
_headerReplyTo' :: Lens' Headers Text
|
_headerReplyTo' :: Lens' Headers Text
|
||||||
-- Functor f => (Text -> f Text) -> [(ByteString, Text)] -> f [(ByteString, Text)]
|
-- Functor f => (Text -> f Text) -> [(ByteString, Text)] -> f [(ByteString, Text)]
|
||||||
_headerReplyTo' f hdrs = (\x -> insertAssoc (replyto,x) hdrs) <$> f (maybeMonoid $ lookup replyto hdrs)
|
_headerReplyTo' f hdrs = (\x -> insertAssoc (replyto, x) hdrs) <$> f (maybeMonoid $ lookup replyto hdrs)
|
||||||
where
|
where
|
||||||
replyto = "Reply-To"
|
replyto = "Reply-To"
|
||||||
|
|
||||||
@ -153,7 +154,7 @@ _mailReplyTo = _mailHeaders . _headerReplyTo
|
|||||||
|
|
||||||
_headerReplyTo :: Lens' Headers Address
|
_headerReplyTo :: Lens' Headers Address
|
||||||
-- Functor f => (Address -> f Address) -> [(ByteString, Text)] -> f [(ByteString, Text)]
|
-- Functor f => (Address -> f Address) -> [(ByteString, Text)] -> f [(ByteString, Text)]
|
||||||
_headerReplyTo f hdrs = (\x -> insertAssoc (replyto,renderAddress x) hdrs) <$> f (fromString $ unpack $ maybeMonoid $ lookup replyto hdrs)
|
_headerReplyTo f hdrs = (\x -> insertAssoc (replyto, renderAddress x) hdrs) <$> f (fromString $ unpack $ maybeMonoid $ lookup replyto hdrs)
|
||||||
where
|
where
|
||||||
replyto = "Reply-To"
|
replyto = "Reply-To"
|
||||||
-- _addressEmail :: Lens' Address Text might help to simplify this code?
|
-- _addressEmail :: Lens' Address Text might help to simplify this code?
|
||||||
@ -248,12 +249,17 @@ instance Exception MailException
|
|||||||
class Yesod site => YesodMail site where
|
class Yesod site => YesodMail site where
|
||||||
defaultFromAddress :: (MonadHandler m, HandlerSite m ~ site) => m Address
|
defaultFromAddress :: (MonadHandler m, HandlerSite m ~ site) => m Address
|
||||||
defaultFromAddress = Address Nothing . ("yesod@" <>) . pack <$> liftIO getHostName
|
defaultFromAddress = Address Nothing . ("yesod@" <>) . pack <$> liftIO getHostName
|
||||||
|
|
||||||
envelopeFromAddress :: (MonadHandler m, HandlerSite m ~ site) => m Text
|
envelopeFromAddress :: (MonadHandler m, HandlerSite m ~ site) => m Text
|
||||||
envelopeFromAddress = addressEmail <$> defaultFromAddress
|
envelopeFromAddress = addressEmail <$> defaultFromAddress
|
||||||
|
|
||||||
mailObjectIdDomain :: (MonadHandler m, HandlerSite m ~ site) => m Text
|
mailObjectIdDomain :: (MonadHandler m, HandlerSite m ~ site) => m Text
|
||||||
mailObjectIdDomain = pack <$> liftIO getHostName
|
mailObjectIdDomain = pack <$> liftIO getHostName
|
||||||
|
|
||||||
|
-- | Use replyTo instead for all senders within mailObjectIdDomain
|
||||||
|
fixedSenderInDomain :: (MonadHandler m, HandlerSite m ~ site) => m Bool
|
||||||
|
fixedSenderInDomain = return False
|
||||||
|
|
||||||
mailDateTZ :: (MonadHandler m, HandlerSite m ~ site) => m TZ
|
mailDateTZ :: (MonadHandler m, HandlerSite m ~ site) => m TZ
|
||||||
mailDateTZ = return utcTZ
|
mailDateTZ = return utcTZ
|
||||||
|
|
||||||
@ -306,10 +312,20 @@ defMailT :: ( MonadHandler m
|
|||||||
-> MailT m a
|
-> MailT m a
|
||||||
-> m a
|
-> m a
|
||||||
defMailT ls (MailT mailC) = do
|
defMailT ls (MailT mailC) = do
|
||||||
fromAddress <- defaultFromAddress
|
fromAddress <- defaultFromAddress
|
||||||
(ret, mail, smtpData) <- runRWST mailC ls (emptyMail fromAddress)
|
(ret, mail, smtpData) <- runRWST mailC ls (emptyMail fromAddress)
|
||||||
mail' <- liftIO $ LBS.toStrict <$> renderMail' mail
|
|
||||||
-- logDebugS "Mail" $ "Rendered mail:\n" <> decodeUtf8 mail'
|
mail' <- maybeT (return mail) $ do
|
||||||
|
guardM fixedSenderInDomain -- if sender must be fixed within ObjectIdDomain, use replyTo instead
|
||||||
|
let sender = mail ^. _mailFrom
|
||||||
|
domain <- lift mailObjectIdDomain
|
||||||
|
guard $ domain `Text.isSuffixOf` (sender ^. _addressEmail) -- allowing foreign senders might be Fraport specific; maybe remove this guard
|
||||||
|
return $ mail
|
||||||
|
& _mailFrom .~ fromAddress
|
||||||
|
& _mailReplyTo .~ sender
|
||||||
|
|
||||||
|
mail'' <- liftIO $ LBS.toStrict <$> renderMail' mail'
|
||||||
|
-- logDebugS "Mail" $ "Rendered mail:\n" <> decodeUtf8 mail''
|
||||||
ret <$ case smtpData of
|
ret <$ case smtpData of
|
||||||
MailSmtpData{ smtpEnvelopeFrom = Last Nothing } -> throwM MailNoSenderSpecified
|
MailSmtpData{ smtpEnvelopeFrom = Last Nothing } -> throwM MailNoSenderSpecified
|
||||||
MailSmtpData{ smtpRecipients }
|
MailSmtpData{ smtpRecipients }
|
||||||
@ -321,7 +337,7 @@ defMailT ls (MailT mailC) = do
|
|||||||
liftIO $ SMTP.sendMail
|
liftIO $ SMTP.sendMail
|
||||||
returnPath
|
returnPath
|
||||||
recipients
|
recipients
|
||||||
mail'
|
mail''
|
||||||
conn
|
conn
|
||||||
|
|
||||||
|
|
||||||
@ -334,8 +350,7 @@ instance Semigroup (PrioritisedAlternatives m) where
|
|||||||
(<>) = mappenddefault
|
(<>) = mappenddefault
|
||||||
|
|
||||||
instance Monoid (PrioritisedAlternatives m) where
|
instance Monoid (PrioritisedAlternatives m) where
|
||||||
mempty = memptydefault
|
mempty = memptydefault
|
||||||
mappend = (<>)
|
|
||||||
|
|
||||||
class YesodMail site => ToMailPart site a where
|
class YesodMail site => ToMailPart site a where
|
||||||
type MailPartReturn site a :: Type
|
type MailPartReturn site a :: Type
|
||||||
|
|||||||
@ -122,10 +122,11 @@ data AppSettings = AppSettings
|
|||||||
, appMailObjectDomain :: Text
|
, appMailObjectDomain :: Text
|
||||||
, appMailVerp :: VerpMode
|
, appMailVerp :: VerpMode
|
||||||
, appMailRetainSent :: Maybe NominalDiffTime
|
, appMailRetainSent :: Maybe NominalDiffTime
|
||||||
, appMailEnvelopeFrom :: Text
|
, appMailEnvelopeFrom :: Text
|
||||||
, appMailFrom
|
, appMailFrom
|
||||||
, appMailSender
|
, appMailSender
|
||||||
, appMailSupport :: Address
|
, appMailSupport :: Address
|
||||||
|
, appMailFixedDomainSender :: Bool
|
||||||
, appJobWorkers :: Natural
|
, appJobWorkers :: Natural
|
||||||
, appJobFlushInterval :: Maybe NominalDiffTime
|
, appJobFlushInterval :: Maybe NominalDiffTime
|
||||||
, appJobCronInterval :: Maybe NominalDiffTime
|
, appJobCronInterval :: Maybe NominalDiffTime
|
||||||
@ -556,10 +557,12 @@ instance FromJSON AppSettings where
|
|||||||
appMailFrom <- o .: "mail-from"
|
appMailFrom <- o .: "mail-from"
|
||||||
appMailEnvelopeFrom <- o .:? "mail-envelope-from" .!= addressEmail appMailFrom
|
appMailEnvelopeFrom <- o .:? "mail-envelope-from" .!= addressEmail appMailFrom
|
||||||
appMailSender <- o .:? "mail-sender" .!= appMailFrom
|
appMailSender <- o .:? "mail-sender" .!= appMailFrom
|
||||||
appMailSupport <- o .: "mail-support"
|
|
||||||
appMailObjectDomain <- o .: "mail-object-domain"
|
appMailObjectDomain <- o .: "mail-object-domain"
|
||||||
|
appMailFixedDomainSender <- o .: "mail-sender-fixed" .!= True
|
||||||
|
|
||||||
appMailVerp <- fromMaybe VerpNone . join <$> (o .:? "mail-verp" <|> pure Nothing)
|
appMailVerp <- fromMaybe VerpNone . join <$> (o .:? "mail-verp" <|> pure Nothing)
|
||||||
appMailRetainSent <- o .: "mail-retain-sent"
|
appMailRetainSent <- o .: "mail-retain-sent"
|
||||||
|
appMailSupport <- o .: "mail-support"
|
||||||
|
|
||||||
appJobWorkers <- o .: "job-workers"
|
appJobWorkers <- o .: "job-workers"
|
||||||
appJobFlushInterval <- o .:? "job-flush-interval"
|
appJobFlushInterval <- o .:? "job-flush-interval"
|
||||||
|
|||||||
Reference in New Issue
Block a user