Skip to content

Commit 6b3d6d2

Browse files
author
Andrew Cady
committed
add domain name validation module
1 parent eab2150 commit 6b3d6d2

File tree

3 files changed

+55
-0
lines changed

3 files changed

+55
-0
lines changed

email-validate.cabal

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ library
3232
hs-source-dirs: src
3333
exposed-modules:
3434
Text.Email.Validate,
35+
Text.Domain.Validate,
3536
Text.Email.Parser
3637

3738
Test-Suite Main

src/Text/Domain/Validate.hs

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
module Text.Domain.Validate
2+
( isValid
3+
, validate
4+
, domainName
5+
, DomainName
6+
, toByteString
7+
)
8+
where
9+
10+
import Control.Applicative ((<*))
11+
12+
import Data.Attoparsec.ByteString (endOfInput, parseOnly)
13+
import Data.ByteString (ByteString)
14+
15+
import Data.Data (Data, Typeable)
16+
import GHC.Generics (Generic)
17+
import Text.Email.Parser (dottedAtoms)
18+
import qualified Text.Read as Read
19+
20+
21+
-- | Represents a domain name.
22+
data DomainName = DomainName ByteString
23+
deriving (Eq, Ord, Data, Typeable, Generic)
24+
25+
-- | Smart constructor for a domain name
26+
domainName :: ByteString -> Maybe DomainName
27+
domainName = either (const Nothing) Just . validate
28+
29+
-- | Validates whether a particular string is a domain name
30+
-- according to RFC5322.
31+
isValid :: ByteString -> Bool
32+
isValid = either (const False) (const True) . validate
33+
34+
-- | If you want to find out *why* a particular string is not
35+
-- a domain name, use this.
36+
37+
validate :: ByteString -> Either String DomainName
38+
validate = fmap DomainName . parseOnly (dottedAtoms <* endOfInput)
39+
40+
instance Show DomainName where
41+
show = show . toByteString
42+
43+
instance Read DomainName where
44+
readListPrec = Read.readListPrecDefault
45+
readPrec = Read.parens (do
46+
bs <- Read.readPrec
47+
case parseOnly (dottedAtoms <* endOfInput) bs of
48+
Left _ -> Read.pfail
49+
Right a -> return $ DomainName a)
50+
51+
-- | Converts an email address back to a ByteString
52+
toByteString :: DomainName -> ByteString
53+
toByteString (DomainName d) = d

src/Text/Email/Parser.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ module Text.Email.Parser
77
, EmailAddress
88
, unsafeEmailAddress
99
, toByteString
10+
, dottedAtoms
1011
)
1112
where
1213

0 commit comments

Comments
 (0)