From 720ff8080b84181a39d82b11aa49b157232aa3c2 Mon Sep 17 00:00:00 2001 From: Alberto Valverde Date: Thu, 3 Oct 2019 17:11:00 +0200 Subject: [PATCH 1/2] Use CaseInsensitive for domain part to follow RFC --- email-validate.cabal | 3 ++- src/Text/Email/Parser.hs | 15 +++++++++++---- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/email-validate.cabal b/email-validate.cabal index 69d86b0..9b2520d 100644 --- a/email-validate.cabal +++ b/email-validate.cabal @@ -26,7 +26,8 @@ library base >= 4.4 && < 5, attoparsec >= 0.10.0 && < 0.14, bytestring >= 0.9 && < 0.11, - template-haskell >= 2.10.0.0 && < 2.16 + template-haskell >= 2.10.0.0 && < 2.16, + case-insensitive >= 1.2.0.11 && < 1.3 default-language: Haskell2010 hs-source-dirs: src ghc-options: -Wall diff --git a/src/Text/Email/Parser.hs b/src/Text/Email/Parser.hs index a7a5971..d7a2d9d 100644 --- a/src/Text/Email/Parser.hs +++ b/src/Text/Email/Parser.hs @@ -4,6 +4,7 @@ module Text.Email.Parser ( addrSpec , localPart , domainPart + , domainPartOriginal , EmailAddress , unsafeEmailAddress , toByteString @@ -15,12 +16,13 @@ import Control.Monad (guard, void, when) import Data.Attoparsec.ByteString.Char8 import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as BS +import qualified Data.CaseInsensitive as CI import Data.Data (Data, Typeable) import GHC.Generics (Generic) import qualified Text.Read as Read -- | Represents an email address. -data EmailAddress = EmailAddress ByteString ByteString +data EmailAddress = EmailAddress ByteString (CI.CI ByteString) deriving (Eq, Ord, Data, Typeable, Generic) -- | Creates an email address without validating it. @@ -28,7 +30,7 @@ data EmailAddress = EmailAddress ByteString ByteString -- somewhere it has already been validated (e.g. a -- database). unsafeEmailAddress :: ByteString -> ByteString -> EmailAddress -unsafeEmailAddress = EmailAddress +unsafeEmailAddress lp = EmailAddress lp . CI.mk instance Show EmailAddress where show = show . toByteString @@ -43,7 +45,7 @@ instance Read EmailAddress where -- | Converts an email address back to a ByteString toByteString :: EmailAddress -> ByteString -toByteString (EmailAddress l d) = BS.concat [l, BS.singleton '@', d] +toByteString (EmailAddress l d) = BS.concat [l, BS.singleton '@', CI.foldedCase d] -- | Extracts the local part of an email address. localPart :: EmailAddress -> ByteString @@ -51,7 +53,12 @@ localPart (EmailAddress l _) = l -- | Extracts the domain part of an email address. domainPart :: EmailAddress -> ByteString -domainPart (EmailAddress _ d) = d +domainPart (EmailAddress _ d) = CI.foldedCase d + +-- | Extracts the domain part of an email address in its original case +domainPartOriginal :: EmailAddress -> ByteString +domainPartOriginal (EmailAddress _ d) = CI.original d + -- | A parser for email addresses. addrSpec :: Parser EmailAddress From f1066abd8d51c4dab4cf298b1feee02150b76139 Mon Sep 17 00:00:00 2001 From: damianfral Date: Tue, 8 Oct 2019 06:15:52 +0200 Subject: [PATCH 2/2] Use CI ByteString for the local part. --- src/Text/Email/Parser.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Text/Email/Parser.hs b/src/Text/Email/Parser.hs index d7a2d9d..c208013 100644 --- a/src/Text/Email/Parser.hs +++ b/src/Text/Email/Parser.hs @@ -22,7 +22,7 @@ import GHC.Generics (Generic) import qualified Text.Read as Read -- | Represents an email address. -data EmailAddress = EmailAddress ByteString (CI.CI ByteString) +data EmailAddress = EmailAddress (CI.CI ByteString) (CI.CI ByteString) deriving (Eq, Ord, Data, Typeable, Generic) -- | Creates an email address without validating it. @@ -30,7 +30,7 @@ data EmailAddress = EmailAddress ByteString (CI.CI ByteString) -- somewhere it has already been validated (e.g. a -- database). unsafeEmailAddress :: ByteString -> ByteString -> EmailAddress -unsafeEmailAddress lp = EmailAddress lp . CI.mk +unsafeEmailAddress lp dp = EmailAddress ( CI.mk lp ) ( CI.mk dp ) instance Show EmailAddress where show = show . toByteString @@ -45,11 +45,11 @@ instance Read EmailAddress where -- | Converts an email address back to a ByteString toByteString :: EmailAddress -> ByteString -toByteString (EmailAddress l d) = BS.concat [l, BS.singleton '@', CI.foldedCase d] +toByteString (EmailAddress l d) = BS.concat [CI.foldedCase l, BS.singleton '@', CI.foldedCase d] -- | Extracts the local part of an email address. localPart :: EmailAddress -> ByteString -localPart (EmailAddress l _) = l +localPart (EmailAddress l _) = CI.foldedCase l -- | Extracts the domain part of an email address. domainPart :: EmailAddress -> ByteString