Treat email address as EmailAddress instead of Text including in the mailer

This commit is contained in:
fr33domlover 2018-03-06 02:26:27 +00:00
parent 33af9fb289
commit d026cf0656
9 changed files with 70 additions and 11 deletions

View file

@ -27,7 +27,7 @@ Person
ident SharerId ident SharerId
login Text login Text
passphraseHash ByteString passphraseHash ByteString
email Text email EmailAddress
verified Bool verified Bool
verifiedKey Text verifiedKey Text
resetPassphraseKey Text resetPassphraseKey Text

30
src/Text/Email/Local.hs Normal file
View file

@ -0,0 +1,30 @@
{- This file is part of Vervis.
-
- Written in 2018 by fr33domlover <fr33domlover@riseup.net>.
-
- Copying is an act of love. Please copy, reuse and share.
-
- The author(s) have dedicated all copyright and related and neighboring
- rights to this software to the public domain worldwide. This software is
- distributed without any warranty.
-
- You should have received a copy of the CC0 Public Domain Dedication along
- with this software. If not, see
- <http://creativecommons.org/publicdomain/zero/1.0/>.
-}
module Text.Email.Local
( emailText
)
where
import Prelude
import Text.Email.Validate
import qualified Data.Text as T
import qualified Data.Text.Encoding as TE
import qualified Data.Text.Encoding.Error as TE
emailText :: EmailAddress -> T.Text
emailText = TE.decodeUtf8With TE.lenientDecode . toByteString

View file

@ -20,7 +20,6 @@ import Prelude (init, last)
import Control.Monad.Logger (logWarn) import Control.Monad.Logger (logWarn)
import Control.Monad.Trans.Maybe import Control.Monad.Trans.Maybe
import Database.Persist.Sql (ConnectionPool, runSqlPool) import Database.Persist.Sql (ConnectionPool, runSqlPool)
import Network.Mail.Mime (Address (..))
import Text.Shakespeare.Text (textFile) import Text.Shakespeare.Text (textFile)
import Text.Hamlet (hamletFile) import Text.Hamlet (hamletFile)
--import Text.Jasmine (minifym) --import Text.Jasmine (minifym)
@ -30,6 +29,7 @@ import Yesod.Auth.Message (AuthMessage (IdentifierNotFound))
import Yesod.Core.Types (Logger) import Yesod.Core.Types (Logger)
import Yesod.Default.Util (addStaticContentExternal) import Yesod.Default.Util (addStaticContentExternal)
import Text.Email.Local
import Yesod.Mail.Send import Yesod.Mail.Send
import qualified Yesod.Core.Unsafe as Unsafe import qualified Yesod.Core.Unsafe as Unsafe
@ -423,7 +423,7 @@ instance AccountSendEmail App where
setMessage $ "Mail sending disabed, please contact admin" setMessage $ "Mail sending disabed, please contact admin"
$logWarn $ T.concat $logWarn $ T.concat
[ "Verification email NOT SENT for user " [ "Verification email NOT SENT for user "
, uname, " <", email, ">: " , uname, " <", emailText email, ">: "
, url , url
] ]
sendNewPasswordEmail uname email url = do sendNewPasswordEmail uname email url = do
@ -432,7 +432,7 @@ instance AccountSendEmail App where
setMessage $ "Mail sending disabed, please contact admin" setMessage $ "Mail sending disabed, please contact admin"
$logWarn $ T.concat $logWarn $ T.concat
["Password reset email NOT SENT for user " ["Password reset email NOT SENT for user "
, uname, " <", email, ">: " , uname, " <", emailText email, ">: "
, url , url
] ]

View file

@ -30,6 +30,8 @@ import Vervis.Form.Person
import Text.Blaze.Html (toHtml) import Text.Blaze.Html (toHtml)
import Yesod.Auth.Account (newAccountR) import Yesod.Auth.Account (newAccountR)
import Text.Email.Local
import Vervis.Model.Ident import Vervis.Model.Ident
import Vervis.Secure import Vervis.Secure
import Vervis.Widget (avatarW) import Vervis.Widget (avatarW)

View file

@ -22,9 +22,12 @@ import Yesod hiding (Header, parseTime)
import Database.Persist.Quasi import Database.Persist.Quasi
import Database.Persist.Sql (fromSqlKey) import Database.Persist.Sql (fromSqlKey)
import Text.Email.Validate (EmailAddress)
import Yesod.Auth.Account (PersistUserCredentials (..)) import Yesod.Auth.Account (PersistUserCredentials (..))
import Database.Persist.EmailAddress
import Database.Persist.Local.Class.PersistEntityGraph import Database.Persist.Local.Class.PersistEntityGraph
import Vervis.Model.Group import Vervis.Model.Group
import Vervis.Model.Ident import Vervis.Model.Ident
import Vervis.Model.Repo import Vervis.Model.Repo

View file

@ -34,6 +34,7 @@ module Yesod.Mail.Send
( YesodMailSend (..) ( YesodMailSend (..)
, MailSettings () , MailSettings ()
, MailRecipe () , MailRecipe ()
, Address (..)
, sendMail , sendMail
, submitMail , submitMail
, runMailer , runMailer
@ -50,15 +51,20 @@ import Control.Monad.Trans.Class (lift)
import Control.Monad.Trans.Reader (ReaderT (runReaderT), ask) import Control.Monad.Trans.Reader (ReaderT (runReaderT), ask)
import Data.Aeson import Data.Aeson
import Data.Text (Text) import Data.Text (Text)
--import Database.Persist import Data.Text.Encoding (encodeUtf8)
import Database.Persist.Sql (LogFunc) import Database.Persist.Sql (LogFunc)
import Network.Mail.Mime (Address (..), Mail, simpleMail') import Network.Mail.Mime (Mail, simpleMail')
import Network.Mail.SMTP hiding (sendMail) import Network.Mail.SMTP hiding (Address (..), sendMail)
import Network.Socket (HostName, PortNumber) import Network.Socket (HostName, PortNumber)
import Text.Email.Validate (EmailAddress, validate)
import Text.Shakespeare.Text (TextUrl, renderTextUrl) import Text.Shakespeare.Text (TextUrl, renderTextUrl)
import Yesod.Core (Route, Yesod) import Yesod.Core (Route, Yesod)
import Yesod.Core.Handler (HandlerT {-HandlerFor-}, getsYesod, getUrlRenderParams) import Yesod.Core.Handler (HandlerT {-HandlerFor-}, getsYesod, getUrlRenderParams)
import qualified Network.Mail.Mime as M (Address (..))
import Text.Email.Local
type HandlerFor site = HandlerT site IO type HandlerFor site = HandlerT site IO
class Yesod site => YesodMailSend site where class Yesod site => YesodMailSend site where
@ -105,13 +111,26 @@ instance FromJSON SmtpSettings where
<*> o .: "host" <*> o .: "host"
<*> (fromInteger <$> o .: "port") <*> (fromInteger <$> o .: "port")
data EmailAddress' = EmailAddress' { toEmailAddress :: EmailAddress }
instance FromJSON EmailAddress' where
parseJSON = withText "EmailAddress" $ \ t ->
case validate $ encodeUtf8 t of
Left err -> fail $ "Parsing email address failed: " ++ err
Right email -> return $ EmailAddress' email
data Address = Address
{ addressName :: Maybe Text
, addressEmail :: EmailAddress
}
data Address' = Address' { toAddress :: Address } data Address' = Address' { toAddress :: Address }
instance FromJSON Address' where instance FromJSON Address' where
parseJSON = withObject "Address" $ \ o -> fmap Address' $ parseJSON = withObject "Address" $ \ o -> fmap Address' $
Address Address
<$> o .:? "name" <$> o .:? "name"
<*> o .: "email" <*> (toEmailAddress <$> o .: "email")
data MailSettings = MailSettings data MailSettings = MailSettings
{ mailSmtp :: SmtpSettings { mailSmtp :: SmtpSettings
@ -155,7 +174,8 @@ renderMessage
:: YesodMailSend site => Address -> Bool -> MailRecipe site -> Mail :: YesodMailSend site => Address -> Bool -> MailRecipe site -> Mail
renderMessage from reply (MailRecipe render to msg) = renderMessage from reply (MailRecipe render to msg) =
let (subject, mkbody) = formatMailMessage reply (addressName to) msg let (subject, mkbody) = formatMailMessage reply (addressName to) msg
in simpleMail' to from subject $ renderTextUrl render mkbody conv (Address n e) = M.Address n $ emailText e
in simpleMail' (conv to) (conv from) subject $ renderTextUrl render mkbody
smtp :: SmtpSettings -> Mail -> IO () smtp :: SmtpSettings -> Mail -> IO ()
smtp (SmtpSettings mlogin host port) = smtp (SmtpSettings mlogin host port) =

View file

@ -13,10 +13,11 @@ packages:
- '../hit-harder' - '../hit-harder'
- '../hit-network' - '../hit-network'
- '../persistent-migration' - '../persistent-migration'
- '../persistent-email-address'
# - '../yesod-auth-account' # - '../yesod-auth-account'
- location: - location:
git: https://dev.seek-together.space/s/fr33domlover/r/yesod-auth-account git: https://dev.seek-together.space/s/fr33domlover/r/yesod-auth-account
commit: 75cc90c910d6c897b623392608f6a4ad3f0b8f09 commit: 1bd49ddf91521bbfeb811af430d0e6918276d127
extra-dep: true extra-dep: true
# Packages to be pulled from upstream that are not in the resolver (e.g., # Packages to be pulled from upstream that are not in the resolver (e.g.,

View file

@ -12,7 +12,7 @@ $# You should have received a copy of the CC0 Public Domain Dedication along
$# with this software. If not, see $# with this software. If not, see
$# <http://creativecommons.org/publicdomain/zero/1.0/>. $# <http://creativecommons.org/publicdomain/zero/1.0/>.
^{avatarW secure $ personEmail person} ^{avatarW secure $ emailText $ personEmail person}
<ul> <ul>
<li> <li>

View file

@ -89,6 +89,7 @@ library
Network.SSH.Local Network.SSH.Local
Text.Blaze.Local Text.Blaze.Local
Text.Display Text.Display
Text.Email.Local
Text.FilePath.Local Text.FilePath.Local
Text.Jasmine.Local Text.Jasmine.Local
Web.PathPieces.Local Web.PathPieces.Local
@ -234,6 +235,7 @@ library
-- for Data.Git.Local -- for Data.Git.Local
, directory-tree , directory-tree
, dlist , dlist
, email-validate
, esqueleto , esqueleto
, fast-logger , fast-logger
-- for building a message tree using DFS in -- for building a message tree using DFS in
@ -272,6 +274,7 @@ library
-- for PathPiece instance for CI, Web.PathPieces.Local -- for PathPiece instance for CI, Web.PathPieces.Local
, path-pieces , path-pieces
, persistent , persistent
, persistent-email-address
, persistent-migration , persistent-migration
, persistent-postgresql , persistent-postgresql
, persistent-template , persistent-template