Hello community,

here is the log from the commit of package ghc-email-validate for 
openSUSE:Factory checked in at 2017-07-11 08:26:10
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/ghc-email-validate (Old)
 and      /work/SRC/openSUSE:Factory/.ghc-email-validate.new (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "ghc-email-validate"

Tue Jul 11 08:26:10 2017 rev:3 rq:509053 version:2.2.1.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/ghc-email-validate/ghc-email-validate.changes    
2016-07-20 09:27:06.000000000 +0200
+++ 
/work/SRC/openSUSE:Factory/.ghc-email-validate.new/ghc-email-validate.changes   
    2017-07-11 08:26:12.156424440 +0200
@@ -1,0 +2,5 @@
+Fri Jun 30 03:01:55 UTC 2017 - [email protected]
+
+- Update to version 2.2.1.1.
+
+-------------------------------------------------------------------

Old:
----
  email-validate-2.2.0.tar.gz

New:
----
  email-validate-2.2.1.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ ghc-email-validate.spec ++++++
--- /var/tmp/diff_new_pack.odc4it/_old  2017-07-11 08:26:13.556227001 +0200
+++ /var/tmp/diff_new_pack.odc4it/_new  2017-07-11 08:26:13.560226437 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package ghc-email-validate
 #
-# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,15 +19,14 @@
 %global pkg_name email-validate
 %bcond_with tests
 Name:           ghc-%{pkg_name}
-Version:        2.2.0
+Version:        2.2.1.1
 Release:        0
-Summary:        Validating an email address string against RFC 5322
+Summary:        Email address validation
 License:        BSD-3-Clause
-Group:          System/Libraries
+Group:          Development/Languages/Other
 Url:            https://hackage.haskell.org/package/%{pkg_name}
 Source0:        
https://hackage.haskell.org/package/%{pkg_name}-%{version}/%{pkg_name}-%{version}.tar.gz
 BuildRequires:  ghc-Cabal-devel
-# Begin cabal-rpm deps:
 BuildRequires:  ghc-attoparsec-devel
 BuildRequires:  ghc-bytestring-devel
 BuildRequires:  ghc-rpm-macros
@@ -39,7 +38,6 @@
 BuildRequires:  ghc-test-framework-hunit-devel
 BuildRequires:  ghc-test-framework-quickcheck2-devel
 %endif
-# End cabal-rpm deps
 
 %description
 Validating an email address string against RFC 5322.
@@ -62,16 +60,11 @@
 %build
 %ghc_lib_build
 
-
 %install
 %ghc_lib_install
 
-
 %check
-%if %{with tests}
-%{cabal} test
-%endif
-
+%cabal_test
 
 %post devel
 %ghc_pkg_recache

++++++ email-validate-2.2.0.tar.gz -> email-validate-2.2.1.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/email-validate-2.2.0/email-validate.cabal 
new/email-validate-2.2.1.1/email-validate.cabal
--- old/email-validate-2.2.0/email-validate.cabal       2016-01-14 
21:58:59.000000000 +0100
+++ new/email-validate-2.2.1.1/email-validate.cabal     2017-06-26 
01:32:54.000000000 +0200
@@ -1,51 +1,51 @@
-name:           email-validate
-version:        2.2.0
-license:        BSD3
-license-file:   LICENSE
-author:         George Pollard <[email protected]>
-maintainer:     George Pollard <[email protected]>
-homepage:       
http://porg.es/blog/email-address-validation-simpler-faster-more-correct
-category:       Text
-synopsis:       Validating an email address string against RFC 5322
-description:    Validating an email address string against RFC 5322
-build-type:     Simple
-stability:      experimental
-cabal-version:  >= 1.10
-
-source-repository head
-    type: git
-    location: git://github.com/Porges/email-validate-hs.git
-
-source-repository this
-    type: git
-    location: git://github.com/Porges/email-validate-hs.git
-    tag: v2.2.0
-
-library
-    build-depends:
-        base >= 4.4 && < 5,
-        attoparsec >= 0.10.0,
-        bytestring >= 0.9,
-        ghc-prim
-    default-language: Haskell2010
-    default-extensions: DeriveGeneric, DeriveDataTypeable
-    hs-source-dirs: src
-    exposed-modules:
-        Text.Email.Validate,
-        Text.Email.Parser
-
-Test-Suite Main
-    type: exitcode-stdio-1.0
-    main-is: Main.hs
-    hs-source-dirs: tests
-    x-uses-tf: true
-    default-language: Haskell2010
-    build-depends:
-        base >= 4 && < 5,
-        HUnit >= 1.2 && < 2,
-        email-validate,
-        QuickCheck >= 2.4,
-        test-framework >= 0.4.1,
-        test-framework-quickcheck2,
-        test-framework-hunit,
-        bytestring >= 0.9
+name: email-validate
+version: 2.2.1.1
+cabal-version: >=1.10
+build-type: Simple
+license: BSD3
+license-file: LICENSE
+maintainer: George Pollard <[email protected]>
+stability: experimental
+homepage: https://github.com/Porges/email-validate-hs
+synopsis: Email address validation
+description:
+    Validating an email address string against RFC 5322
+category: Text
+author: George Pollard <[email protected]>
+
+source-repository head
+    type: git
+    location: git://github.com/Porges/email-validate-hs.git
+
+source-repository this
+    type: git
+    location: git://github.com/Porges/email-validate-hs.git
+    tag: v2.2.1.1
+
+library
+    exposed-modules:
+        Text.Domain.Parser
+        Text.Email.Validate
+        Text.Email.Parser
+    build-depends:
+        base >=4.4 && <5,
+        attoparsec >=0.10.0 && <0.14,
+        bytestring >=0.9 && <0.11
+    default-language: Haskell2010
+    hs-source-dirs: src
+    ghc-options: -Wall
+
+test-suite Main
+    type: exitcode-stdio-1.0
+    main-is: Main.hs
+    build-depends:
+        base ==4.*,
+        HUnit >=1.2 && <2,
+        email-validate >=2.2.1.1 && <2.3,
+        QuickCheck >=2.4 && <2.11,
+        test-framework >=0.4.1 && <0.9,
+        test-framework-quickcheck2 >=0.3.0.4 && <0.4,
+        test-framework-hunit >=0.3.0.2 && <0.4,
+        bytestring >=0.9 && <0.11
+    default-language: Haskell2010
+    hs-source-dirs: tests
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/email-validate-2.2.0/src/Text/Domain/Parser.hs 
new/email-validate-2.2.1.1/src/Text/Domain/Parser.hs
--- old/email-validate-2.2.0/src/Text/Domain/Parser.hs  1970-01-01 
01:00:00.000000000 +0100
+++ new/email-validate-2.2.1.1/src/Text/Domain/Parser.hs        2017-06-26 
01:25:25.000000000 +0200
@@ -0,0 +1,41 @@
+{-# LANGUAGE DeriveDataTypeable, DeriveGeneric #-}
+
+module Text.Domain.Parser
+    ( domainParser
+    )
+where
+
+import           Control.Applicative
+import           Control.Monad (guard)
+import           Data.Attoparsec.ByteString.Char8
+import qualified Data.ByteString.Char8 as BS
+import           Data.ByteString (ByteString)
+
+domainParser :: Parser ByteString
+domainParser = do
+    domain <- fst <$> match (label `sepBy1` char '.' >> optional (char '.'))
+
+    -- trim off the excess '.' if it is there
+    let trimmed =
+            case BS.last domain of
+                '.' -> BS.init domain
+                _ -> domain
+
+    -- domain name must be no greater than 253 chars
+    guard (BS.length trimmed <= 253)
+    return trimmed
+
+label :: Parser ByteString
+label = do
+    lbl <- fst <$> match (alphaNum >> skipWhile isAlphaNumHyphen)
+
+    -- label must be no greater than 63 chars and cannot end with '-'
+    guard (BS.length lbl <= 63 && BS.last lbl /= '-')
+    return lbl
+
+alphaNum :: Parser Char
+alphaNum = satisfy isAlphaNum
+    where isAlphaNum x = isDigit x || isAlpha_ascii x
+
+isAlphaNumHyphen :: Char -> Bool
+isAlphaNumHyphen x = isDigit x || isAlpha_ascii x || x == '-'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/email-validate-2.2.0/src/Text/Email/Parser.hs 
new/email-validate-2.2.1.1/src/Text/Email/Parser.hs
--- old/email-validate-2.2.0/src/Text/Email/Parser.hs   2016-01-14 
21:55:22.000000000 +0100
+++ new/email-validate-2.2.1.1/src/Text/Email/Parser.hs 2017-06-26 
01:25:25.000000000 +0200
@@ -10,18 +10,17 @@
     )
 where
 
-import Control.Applicative
-import Control.Monad (void)
-
+import           Control.Applicative
+import           Control.Monad (void)
+import           Data.Attoparsec.ByteString.Char8
+import           Data.ByteString (ByteString)
 import qualified Data.ByteString.Char8 as BS
-import Data.ByteString (ByteString)
-
-import Data.Attoparsec.ByteString.Char8
-
-import Data.Data (Data, Typeable)
-import GHC.Generics (Generic)
+import           Data.Data (Data, Typeable)
+import           GHC.Generics (Generic)
 import qualified Text.Read as Read
 
+import           Text.Domain.Parser (domainParser)
+
 -- | Represents an email address.
 data EmailAddress = EmailAddress ByteString ByteString
     deriving (Eq, Ord, Data, Typeable, Generic)
@@ -58,21 +57,25 @@
 
 -- | A parser for email addresses.
 addrSpec :: Parser EmailAddress
-addrSpec = do
-    l <- local
-    _ <- char '@'
-    d <- domain
-    return (EmailAddress l d)
+addrSpec = unsafeEmailAddress <$> local <* char '@' <*> domain
 
 local :: Parser ByteString
 local = dottedAtoms
 
 domain :: Parser ByteString
-domain = dottedAtoms <|> domainLiteral
+domain = domainName <|> domainLiteral
+
+domainName :: Parser ByteString
+domainName = do
+    raw <- BS.append <$> dottedAtoms <*> option BS.empty (string (BS.pack "."))
+    case parseOnly (domainParser <* endOfInput) raw of
+        Left err -> fail err
+        Right result -> return result
 
 dottedAtoms :: Parser ByteString
 dottedAtoms = BS.intercalate (BS.singleton '.') <$>
-        between1 (optional cfws) (atom <|> quotedString) `sepBy1` char '.'
+        between1 (optional cfws)
+            (atom <|> quotedString) `sepBy1` char '.'
 
 atom :: Parser ByteString
 atom = takeWhile1 isAtomText
@@ -91,8 +94,8 @@
 
 quotedString :: Parser ByteString
 quotedString =
-    (\x -> BS.concat [BS.singleton '"', BS.concat x, BS.singleton '"']) <$>
-        between (char '"') (char '"')
+    (BS.cons '"' . flip BS.snoc '"' . BS.concat) <$>
+        between1 (char '"')
             (many (optional fws >> quotedContent) <* optional fws)
 
 quotedContent :: Parser ByteString
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/email-validate-2.2.0/src/Text/Email/Validate.hs 
new/email-validate-2.2.1.1/src/Text/Email/Validate.hs
--- old/email-validate-2.2.0/src/Text/Email/Validate.hs 2016-01-14 
21:57:18.000000000 +0100
+++ new/email-validate-2.2.1.1/src/Text/Email/Validate.hs       2017-06-26 
01:25:25.000000000 +0200
@@ -11,12 +11,10 @@
         )
 where
 
-import           Control.Applicative        ((<*))
-
 import           Data.Attoparsec.ByteString (endOfInput, parseOnly)
 import           Data.ByteString            (ByteString)
 
-import           Text.Email.Parser          (EmailAddress(..), addrSpec, 
domainPart,
+import           Text.Email.Parser          (EmailAddress, addrSpec, 
domainPart,
                                              localPart, toByteString, 
unsafeEmailAddress)
 
 -- | Smart constructor for an email address
@@ -36,4 +34,4 @@
 -- | If you want to find out *why* a particular string is not
 --   an email address, use this.
 validate :: ByteString -> Either String EmailAddress
-validate = parseOnly (addrSpec <* endOfInput)
+validate = parseOnly (addrSpec >>= \r -> endOfInput >> return r)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/email-validate-2.2.0/tests/Main.hs 
new/email-validate-2.2.1.1/tests/Main.hs
--- old/email-validate-2.2.0/tests/Main.hs      2016-01-14 21:52:57.000000000 
+0100
+++ new/email-validate-2.2.1.1/tests/Main.hs    2017-06-26 01:25:25.000000000 
+0200
@@ -1,61 +1,98 @@
-module Main where
+{-# LANGUAGE NamedFieldPuns #-}
+{-# LANGUAGE OverloadedStrings #-}
 
-import Text.Email.Validate
-import Test.HUnit
+module Main where
 
 import Data.ByteString (ByteString)
 import qualified Data.ByteString.Char8 as BS
+import Data.Maybe (Maybe(..), isNothing)
 
 import Test.Framework as TF (defaultMain, testGroup, Test)
-import Test.Framework.Providers.HUnit
+import Test.Framework.Providers.HUnit (testCase)
 import Test.Framework.Providers.QuickCheck2 (testProperty)
 
-import Test.QuickCheck
+import Test.HUnit ((@?=), assert)
+import Test.QuickCheck (Arbitrary(..), suchThat)
+
+import Text.Email.Validate
+    ( EmailAddress
+    , canonicalizeEmail
+    , domainPart
+    , emailAddress
+    , localPart
+    , isValid
+    , toByteString
+    , validate
+    , unsafeEmailAddress
+    )
 
 main :: IO ()
-main = defaultMain tests
+main = defaultMain testGroups
 
-tests :: [TF.Test]
-tests = [
-        testGroup "EmailAddress Show/Read instances" [
-                testProperty "showLikeByteString" prop_showLikeByteString,
-                testProperty "showAndReadBackWithoutQuoteFails" 
prop_showAndReadBackWithoutQuoteFails,
-                testProperty "showAndReadBack" prop_showAndReadBack
-                ],
-
-        testGroup "QuickCheck Text.Email.Validate" [
-                testProperty "doubleCanonicalize" prop_doubleCanonicalize
-                ],
-
-        testGroup "Unit tests Text.Email.Validate" $ flip concatMap units
-            (\(em, valid, _) -> let email = BS.pack em
-                in
-                    [
-                    testCase ("doubleCanonicalize '" ++ em ++ "'") (True @=? 
case emailAddress email of { Nothing -> True; Just ok -> 
prop_doubleCanonicalize ok }),
-                    testCase ("validity test '" ++ em ++ "'") (valid @=? 
isValid email)
-                    ]),
+{- Tests -}
+
+testGroups :: [Test]
+testGroups =
+    [ showAndRead
+    , canonicalization
+    , exampleTests
+    , specificFailures
+    , simpleAccessors
+    ]
+
+canonicalization =
+    testGroup "QuickCheck Text.Email.Validate"
+    [ testProperty "doubleCanonicalize" prop_doubleCanonicalize
+    ]
 
-        testGroup "Issues" [
-            testCase "#12" (let (Right em) = validate (BS.pack "\"\"@1") in em 
@=? read (show em))
+exampleTests =
+    testGroup "Unit tests Text.Email.Validate" (concatMap exampleTest examples)
+    where
+    exampleTest Example{example, valid, reason} =
+        if valid
+        then
+            [ testCase ("Ensure valid " ++ name) (assert (isValid example))
+            , testCase ("doubleCanonicalize test " ++ name) (assert (case 
emailAddress example of { Just ok -> prop_doubleCanonicalize ok; Nothing -> 
False }))
             ]
-       ]
+        else
+            [ testCase ("Ensure invalid " ++ name) (assert (not (isValid 
example))) ]
+
+        where name = show example ++ (if null reason then "" else " (" ++ 
reason ++ ")")
+
+showAndRead =
+    testGroup "EmailAddress Show/Read instances"
+    [ testProperty "showLikeByteString" prop_showLikeByteString
+    , testProperty "showAndReadBackWithoutQuoteFails" 
prop_showAndReadBackWithoutQuoteFails
+    , testProperty "showAndReadBack" prop_showAndReadBack
+    ]
+
+specificFailures =
+    testGroup "Specifics"
+    [ testCase "Issue #12" (let (Right em) = validate (BS.pack "\"\"@1") in em 
@?= read (show em))
+    , testCase "Check canonicalization of trailing dot" (canonicalizeEmail 
"[email protected]." @?= Just "[email protected]")
+    ]
+
+simpleAccessors = 
+    testGroup "Simple accessors"
+    [ testCase "local-part" (localPart (unsafeEmailAddress "local" undefined) 
@?= "local")
+    , testCase "domain-part" (domainPart (unsafeEmailAddress undefined 
"domain") @?= "domain")
+    ]
 
 instance Arbitrary ByteString where
     arbitrary = fmap BS.pack arbitrary
 
 instance Arbitrary EmailAddress where
     arbitrary = do
-        local <- suchThat arbitrary (\x -> isEmail x (BS.pack "example.com"))
-        domain <- suchThat arbitrary (isEmail (BS.pack "example"))
-        let email = makeEmailLike local domain
-        let (Just result) = emailAddress email
-        return result
+        local <- suchThat arbitrary (\l -> isEmail l (BS.pack "example.com"))
+        domain <- suchThat arbitrary (\d -> isEmail (BS.pack "example") d)
+        let (Just result) = emailAddress (makeEmailLike local domain)
+        pure result
+
+        where
+        isEmail l d = isValid (makeEmailLike l d)
+        makeEmailLike l d = BS.concat [l, BS.singleton '@', d]
 
-isEmail :: ByteString -> ByteString -> Bool
-isEmail l d = isValid (makeEmailLike l d)
-
-makeEmailLike :: ByteString -> ByteString -> ByteString
-makeEmailLike l d = BS.concat [l, BS.singleton '@', d]
+{- Properties -}
 
 prop_doubleCanonicalize :: EmailAddress -> Bool
 prop_doubleCanonicalize email =  Just email == emailAddress (toByteString 
email)
@@ -66,247 +103,253 @@
 prop_showAndReadBack :: EmailAddress -> Bool
 prop_showAndReadBack email = read (show email) == email
 
-readMaybe :: String -> Maybe EmailAddress
-readMaybe s = case reads s of
-              [(x, "")] -> Just x
-              _ -> Nothing
-
 prop_showAndReadBackWithoutQuoteFails :: EmailAddress -> Bool
 prop_showAndReadBackWithoutQuoteFails email =
-    readMaybe (init s) == Nothing &&
-    readMaybe (tail s) == Nothing
-    where s = show email
-
---unitTest (x, y, z) = if not (isValid (BS.pack x) == y) then "" else (x ++" 
became "++ (case emailAddress (BS.pack x) of {Nothing -> "fail"; Just em -> 
show em}) ++": Should be "++show y ++", got "++show (not y)++"\n\t"++z++"\n")
-
-units :: [(String, Bool, String)]
-units = [
-    ("[email protected]", True, ""),
-    
("1234567890123456789012345678901234567890123456789012345678901...@example.com",
 True, ""),
-    ("\"first last\"@example.com", True, ""),
-    ("\"first\\\"last\"@example.com", True, ""),
-    ("first\\@[email protected]", False, "Escaping can only happen within a 
quoted string"),
-    ("\"first@last\"@example.com", True, ""),
-    ("\"first\\\\last\"@example.com", True, ""),
-    
("x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x234",
 True, ""),
-    
("123456789012345678901234567890123456789012345678901234567...@12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.123456789012345678901234567890123456789012345678901234567890123.example.com",
 True, ""),
-    ("first.last@[12.34.56.78]", True, ""),
-    ("first.last@[IPv6:::12.34.56.78]", True, ""),
-    ("first.last@[IPv6:1111:2222:3333::4444:12.34.56.78]", True, ""),
-    ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:12.34.56.78]", True, ""),
-    ("first.last@[IPv6:::1111:2222:3333:4444:5555:6666]", True, ""),
-    ("first.last@[IPv6:1111:2222:3333::4444:5555:6666]", True, ""),
-    ("first.last@[IPv6:1111:2222:3333:4444:5555:6666::]", True, ""),
-    ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888]", True, ""),
-    
("first.l...@x23456789012345678901234567890123456789012345678901234567890123.example.com",
 True, ""),
-    ("[email protected]", True, ""),
-    ("[email protected]", True, ""),
-    ("first.last", False, "No @"),
-    ("[email protected]", False, "Local part starts with a dot"),
-    ("[email protected]", False, "Local part ends with a dot"),
-    ("[email protected]", False, "Local part has consecutive dots"),
-    ("\"first\"last\"@example.com", False, "Local part contains unescaped 
excluded characters"),
-    ("\"first\\last\"@example.com", True, "Any character can be escaped in a 
quoted string"),
-    ("\"\"\"@example.com", False, "Local part contains unescaped excluded 
characters"),
-    ("\"\\\"@example.com", False, "Local part cannot end with a backslash"),
-    ("first\\\\@[email protected]", False, "Local part contains unescaped 
excluded characters"),
-    ("first.last@", False, "No domain"),
-    ("\"Abc\\@def\"@example.com", True, ""),
-    ("\"Fred\\ Bloggs\"@example.com", True, ""),
-    ("\"Joe.\\\\Blow\"@example.com", True, ""),
-    ("\"Abc@def\"@example.com", True, ""),
-    ("\"Fred Bloggs\"@example.com", True, ""),
-    ("[email protected]", True, ""),
-    ("customer/[email protected]", True, ""),
-    ("[email protected]", True, ""),
-    ("!def!xyz%[email protected]", True, ""),
-    ("[email protected]", True, ""),
-    ("[email protected]", True, ""),
-    ("abc\\@[email protected]", False, "This example from RFC3696 was corrected 
in an erratum"),
-    ("abc\\\\@example.com", False, "This example from RFC3696 was corrected in 
an erratum"),
-    ("[email protected]", True, ""),
-    ("Doug\\ \\\"Ace\\\"\\ [email protected]", False, "Escaping can only 
happen in a quoted string"),
-    ("\"Doug \\\"Ace\\\" L.\"@example.com", True, ""),
-    ("abc@[email protected]", False, "Doug Lovell says this should fail"),
-    ("abc\\\\@[email protected]", False, "Doug Lovell says this should fail"),
-    ("abc\\@example.com", False, "Doug Lovell says this should fail"),
-    ("@example.com", False, "No local part"),
-    ("doug@", False, "Doug Lovell says this should fail"),
-    ("\"[email protected]", False, "Doug Lovell says this should fail"),
-    ("ote\"@example.com", False, "Doug Lovell says this should fail"),
-    ("[email protected]", False, "Doug Lovell says this should fail"),
-    ("[email protected]", False, "Doug Lovell says this should fail"),
-    ("[email protected]", False, "Doug Lovell says this should fail"),
-    ("\"Doug \"Ace\" L.\"@example.com", False, "Doug Lovell says this should 
fail"),
-    ("Doug\\ \\\"Ace\\\"\\ L\\[email protected]", False, "Doug Lovell says this 
should fail"),
-    ("hello [email protected]", False, "Doug Lovell says this should fail"),
-    ("[email protected].", False, "Doug Lovell says this should 
fail"),
-    ("[email protected]", True, ""),
-    ("[email protected]", True, ""),
-    ("[email protected]", True, ""),
-    ("[email protected]", True, ""),
-    ("[email protected]", True, ""),
-    ("t*[email protected]", True, ""),
-    ("[email protected]", True, ""),
-    ("{_test_}@example.com", True, ""),
-    ("\"[[ test ]]\"@example.com", True, ""),
-    ("[email protected]", True, ""),
-    ("\"test.test\"@example.com", True, ""),
-    ("test.\"test\"@example.com", True, "Obsolete form, but documented in 
RFC2822"),
-    ("\"test@test\"@example.com", True, ""),
-    ("[email protected]", True, ""),
-    ("test@[123.123.123.123]", True, ""),
-    ("[email protected]", True, ""),
-    ("[email protected]", True, ""),
-    ("test.example.com", False, ""),
-    ("[email protected]", False, ""),
-    ("[email protected]", False, ""),
-    ("[email protected]", False, ""),
-    ("test@[email protected]", False, ""),
-    ("test@@example.com", False, ""),
-    ("-- test [email protected]", False, "No spaces allowed in local part"),
-    ("[test]@example.com", False, "Square brackets only allowed within 
quotes"),
-    ("\"test\\test\"@example.com", True, "Any character can be escaped in a 
quoted string"),
-    ("\"test\"test\"@example.com", False, "Quotes cannot be nested"),
-    ("()[]\\;:,><@example.com", False, "Disallowed Characters"),
-    ("test@.", False, "Dave Child says so"),
-    ("test@example.", False, "Dave Child says so"),
-    ("[email protected]", False, "Dave Child says so"),
-    ("test@[123.123.123.123", False, "Dave Child says so"),
-    ("[email protected]]", False, "Dave Child says so"),
-    ("NotAnEmail", False, "Phil Haack says so"),
-    ("@NotAnEmail", False, "Phil Haack says so"),
-    ("\"test\\\\blah\"@example.com", True, ""),
-    ("\"test\\blah\"@example.com", True, "Any character can be escaped in a 
quoted string"),
-    ("\"test\\\rblah\"@example.com", True, "Quoted string specifically 
excludes carriage returns unless escaped"),
-    ("\"test\rblah\"@example.com", False, "Quoted string specifically excludes 
carriage returns"),
-    ("\"test\\\"blah\"@example.com", True, ""),
-    ("\"test\"blah\"@example.com", False, "Phil Haack says so"),
-    ("customer/[email protected]", True, ""),
-    ("[email protected]", True, ""),
-    ("[email protected]", True, ""),
-    ("[email protected]", False, "Phil Haack says so"),
-    ("[email protected]", False, "Phil Haack says so"),
-    ("[email protected]", False, "Phil Haack says so"),
-    ("[email protected]", False, "Phil Haack says so"),
-    ("\"Austin@Powers\"@example.com", True, ""),
-    ("[email protected]", True, ""),
-    ("\"Ima.Fool\"@example.com", True, ""),
-    ("\"Ima Fool\"@example.com", True, ""),
-    ("Ima [email protected]", False, "Phil Haack says so"),
-    ("phil.h\\@\\@[email protected]", False, "Escaping can only happen in a 
quoted string"),
-    ("\"first\".\"last\"@example.com", True, ""),
-    ("\"first\".middle.\"last\"@example.com", True, ""),
-    ("\"first\\\\\"last\"@example.com", False, "Contains an unescaped quote"),
-    ("\"first\"[email protected]", True, "obs-local-part form as described in 
RFC 2822"),
-    ("first.\"last\"@example.com", True, "obs-local-part form as described in 
RFC 2822"),
-    ("\"first\".\"middle\".\"last\"@example.com", True, "obs-local-part form 
as described in RFC 2822"),
-    ("\"first.middle\".\"last\"@example.com", True, "obs-local-part form as 
described in RFC 2822"),
-    ("\"first.middle.last\"@example.com", True, "obs-local-part form as 
described in RFC 2822"),
-    ("\"first..last\"@example.com", True, "obs-local-part form as described in 
RFC 2822"),
-    ("foo@[\\1.2.3.4]", False, "RFC 5321 specifies the syntax for 
address-literal and does not allow escaping"),
-    ("\"first\\\\\\\"last\"@example.com", True, ""),
-    ("first.\"mid\\dle\".\"last\"@example.com", True, "Backslash can escape 
anything but must escape something"),
-    ("Test.\r\n Folding.\r\n [email protected]", True, ""),
-    ("first\\[email protected]", False, "Unquoted string must be an atom"),
-    ("Abc\\@[email protected]", False, "Was incorrectly given as a valid 
address in the original RFC3696"),
-    ("Fred\\ [email protected]", False, "Was incorrectly given as a valid 
address in the original RFC3696"),
-    ("Joe.\\\\[email protected]", False, "Was incorrectly given as a valid 
address in the original RFC3696"),
-    ("\"test\\\r\n blah\"@example.com", False, "Folding white space can\'t 
appear within a quoted pair"),
-    ("\"test\r\n blah\"@example.com", True, "This is a valid quoted string 
with folding white space"),
-    ("{^c\\@**Dog^}@cartoon.com", False, "This is a throwaway example from 
Doug Lovell\'s article. Actually it\'s not a valid address."),
-    ("(foo)cal(bar)@(baz)iamcal.com(quux)", True, "A valid address containing 
comments"),
-    ("cal@iamcal(woo).(yay)com", True, "A valid address containing comments"),
-    ("cal(woo(yay)hoopla)@iamcal.com", True, "A valid address containing 
comments"),
-    ("cal(foo\\@bar)@iamcal.com", True, "A valid address containing comments"),
-    ("cal(foo\\)bar)@iamcal.com", True, "A valid address containing comments 
and an escaped parenthesis"),
-    ("cal(foo(bar)@iamcal.com", False, "Unclosed parenthesis in comment"),
-    ("cal(foo)bar)@iamcal.com", False, "Too many closing parentheses"),
-    ("cal(foo\\)@iamcal.com", False, "Backslash at end of comment has nothing 
to escape"),
-    ("first()[email protected]", True, "A valid address containing an empty 
comment"),
-    ("first.(\r\n middle\r\n )[email protected]", True, "Comment with folding 
white space"),
-    
("first(12345678901234567890123456789012345678901234567890)last@(1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890)example.com",
 False, "Too long with comments, not too long without"),
-    ("first(Welcome to\r\n the (\"wonderful\" (!)) world\r\n of 
email)@example.com", True, "Silly example from my blog post"),
-    ("pete(his account)@silly.test(his host)", True, "Canonical example from 
RFC5322"),
-    ("c@(Chris\'s host.)public.example", True, "Canonical example from 
RFC5322"),
-    ("jdoe@machine(comment).  example", True, "Canonical example from 
RFC5322"),
-    ("1234   @   local(blah)  .machine .example", True, "Canonical example 
from RFC5322"),
-    ("first(middle)[email protected]", False, "Can\'t have a comment or white 
space except at an element boundary"),
-    ("first(abc.def)[email protected]", True, "Comment can contain a dot"),
-    ("first(a\"bc.def)[email protected]", True, "Comment can contain double 
quote"),
-    ("first.(\")middle.last(\")@example.com", True, "Comment can contain a 
quote"),
-    
("first(abc(\"def\".ghi).mno)middle(abc(\"def\".ghi).mno).last@(abc(\"def\".ghi).mno)example(abc(\"def\".ghi).mno).(abc(\"def\".ghi).mno)com(abc(\"def\".ghi).mno)",
 False, "Can\'t have comments or white space except at an element boundary"),
-    ("first(abc\\(def)@example.com", True, "Comment can contain quoted-pair"),
-    
("first.last@x(1234567890123456789012345678901234567890123456789012345678901234567890).com",
 True, "Label is longer than 63 octets, but not with comment removed"),
-    ("a(a(b(c)d(e(f))g)h(i)j)@example.com", True, ""),
-    ("a(a(b(c)d(e(f))g)(h(i)j)@example.com", False, "Braces are not properly 
matched"),
-    ("[email protected]", True, ""),
-    (".@", False, ""),
-    ("@bar.com", False, ""),
-    ("@@bar.com", False, ""),
-    ("[email protected]", True, ""),
-    ("aaa.com", False, ""),
-    ("[email protected]", False, ""),
-    ("[email protected]", False, ""),
-    ("aaa@[123.123.123.123]", True, ""),
-    ("aaa@[123.123.123.123]a", False, "extra data outside ip"),
-    ("[email protected].", False, ""),
-    ("[email protected]", True, ""),
-    ("[email protected]", True, "TLDs can be any length"),
-    ("[email protected]", True, ""),
-    ("[email protected]", False, ""),
-    ("[email protected]", False, ""),
-    ("[email protected]", True, ""),
-    ("\"hello my name is\"@stutter.com", True, ""),
-    ("\"Test \\\"Fail\\\" Ing\"@example.com", True, ""),
-    ("[email protected]", True, ""),
-    ("[email protected]", True, "Disagree with Paul Gregg 
here"),
-    ("[email protected]", False, "......"),
-    ("\"Joe\\\\Blow\"@example.com", True, ""),
-    ("Invalid \\\n Folding \\\n [email protected]", False, "This isn\'t 
FWS so Dominic Sayers says it\'s invalid"),
-    ("HM2Kinsists@(that comments are allowed)this.is.ok", True, ""),
-    ("user%[email protected]", True, ""),
-    ("\"first(last)\"@example.com", True, ""),
-    (" \r\n (\r\n x \r\n ) \r\n first\r\n ( \r\n x\r\n ) \r\n .\r\n ( \r\n x) 
\r\n last \r\n (  x \r\n ) \r\n @example.com", True, ""),
-    ("test.\r\n \r\n [email protected]", True, "obs-fws allows multiple lines"),
-    ("test. \r\n \r\n [email protected]", True, "obs-fws allows multiple lines 
(test 2: space before break)"),
-    ("test.\r\n\r\n [email protected]", False, "obs-fws must have at least one 
WSP per line"),
-    ("\"null \\\0\"@char.com", True, "can have escaped null character"),
-    ("\"null \0\"@char.com", False, "cannot have unescaped null character")
+    isNothing (readMaybe (init s)) && isNothing (readMaybe (tail s))
+    where
+    s = show email
+    readMaybe :: String -> Maybe EmailAddress
+    readMaybe s = case reads s of
+                [(x, "")] -> Just x
+                _ -> Nothing
+
+{- Examples -}
+
+data Example = Example { example :: ByteString, valid :: Bool, reason :: 
String }
+
+examples :: [Example]
+examples =
+    map (\(e, v, r) -> Example e v r)
+    [ ("[email protected]", True, "")
+    , ("[email protected].", True, "Dot allowed on end of domain")
+    , ("local@exam_ple.com", False, "Underscore not permitted in domain")
+    , 
("1234567890123456789012345678901234567890123456789012345678901...@example.com",
 True, "")
+    , ("\"first last\"@example.com", True, "")
+    , ("\"first\\\"last\"@example.com", True, "")
+    , ("first\\@[email protected]", False, "Escaping can only happen within a 
quoted string")
+    , ("\"first@last\"@example.com", True, "")
+    , ("\"first\\\\last\"@example.com", True, "")
+    , 
("x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23",
 True, "Max length is 253")
+    , 
("x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23.",
 True, "Trailing dot doesn't increase length")
+    , 
("x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x234",
 False, "Max length is 253")
+    , 
("123456789012345678901234567890123456789012345678901234567...@12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.123456789012345678901234567890123456789012345678901234567890123.example.com",
 True, "")
+    , ("first.last@[12.34.56.78]", True, "")
+    , ("first.last@[IPv6:::12.34.56.78]", True, "")
+    , ("first.last@[IPv6:1111:2222:3333::4444:12.34.56.78]", True, "")
+    , ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:12.34.56.78]", True, "")
+    , ("first.last@[IPv6:::1111:2222:3333:4444:5555:6666]", True, "")
+    , ("first.last@[IPv6:1111:2222:3333::4444:5555:6666]", True, "")
+    , ("first.last@[IPv6:1111:2222:3333:4444:5555:6666::]", True, "")
+    , ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888]", True, "")
+    , 
("first.l...@x23456789012345678901234567890123456789012345678901234567890123.example.com",
 True, "")
+    , ("[email protected]", True, "")
+    , ("[email protected]", True, "")
+    , ("first.last", False, "No @")
+    , ("[email protected]", False, "Local part starts with a dot")
+    , ("[email protected]", False, "Local part ends with a dot")
+    , ("[email protected]", False, "Local part has consecutive dots")
+    , ("\"first\"last\"@example.com", False, "Local part contains unescaped 
excluded characters")
+    , ("\"first\\last\"@example.com", True, "Any character can be escaped in a 
quoted string")
+    , ("\"\"\"@example.com", False, "Local part contains unescaped excluded 
characters")
+    , ("\"\\\"@example.com", False, "Local part cannot end with a backslash")
+    , ("first\\\\@[email protected]", False, "Local part contains unescaped 
excluded characters")
+    , ("first.last@", False, "No domain")
+    , ("\"Abc\\@def\"@example.com", True, "")
+    , ("\"Fred\\ Bloggs\"@example.com", True, "")
+    , ("\"Joe.\\\\Blow\"@example.com", True, "")
+    , ("\"Abc@def\"@example.com", True, "")
+    , ("\"Fred Bloggs\"@example.com", True, "")
+    , ("[email protected]", True, "")
+    , ("customer/[email protected]", True, "")
+    , ("[email protected]", True, "")
+    , ("!def!xyz%[email protected]", True, "")
+    , ("[email protected]", True, "")
+    , ("[email protected]", True, "")
+    , ("abc\\@[email protected]", False, "This example from RFC3696 was 
corrected in an erratum")
+    , ("abc\\\\@example.com", False, "This example from RFC3696 was corrected 
in an erratum")
+    , ("[email protected]", True, "")
+    , ("Doug\\ \\\"Ace\\\"\\ [email protected]", False, "Escaping can only 
happen in a quoted string")
+    , ("\"Doug \\\"Ace\\\" L.\"@example.com", True, "")
+    , ("abc@[email protected]", False, "Doug Lovell says this should fail")
+    , ("abc\\\\@[email protected]", False, "Doug Lovell says this should fail")
+    , ("abc\\@example.com", False, "Doug Lovell says this should fail")
+    , ("@example.com", False, "No local part")
+    , ("doug@", False, "Doug Lovell says this should fail")
+    , ("\"[email protected]", False, "Doug Lovell says this should fail")
+    , ("ote\"@example.com", False, "Doug Lovell says this should fail")
+    , ("[email protected]", False, "Doug Lovell says this should fail")
+    , ("[email protected]", False, "Doug Lovell says this should fail")
+    , ("[email protected]", False, "Doug Lovell says this should fail")
+    , ("\"Doug \"Ace\" L.\"@example.com", False, "Doug Lovell says this should 
fail")
+    , ("Doug\\ \\\"Ace\\\"\\ L\\[email protected]", False, "Doug Lovell says this 
should fail")
+    , ("hello [email protected]", False, "Doug Lovell says this should fail")
+    , ("[email protected].", True, "")
+    , ("[email protected]", True, "")
+    , ("[email protected]", True, "")
+    , ("[email protected]", True, "")
+    , ("[email protected]", True, "")
+    , ("[email protected]", True, "")
+    , ("t*[email protected]", True, "")
+    , ("[email protected]", True, "")
+    , ("{_test_}@example.com", True, "")
+    , ("\"[[ test ]]\"@example.com", True, "")
+    , ("[email protected]", True, "")
+    , ("\"test.test\"@example.com", True, "")
+    , ("test.\"test\"@example.com", True, "Obsolete form, but documented in 
RFC2822")
+    , ("\"test@test\"@example.com", True, "")
+    , ("[email protected]", True, "")
+    , ("test@[123.123.123.123]", True, "")
+    , ("[email protected]", True, "")
+    , ("[email protected]", True, "")
+    , ("test.example.com", False, "")
+    , ("[email protected]", False, "")
+    , ("[email protected]", False, "")
+    , ("[email protected]", False, "")
+    , ("test@[email protected]", False, "")
+    , ("test@@example.com", False, "")
+    , ("-- test [email protected]", False, "No spaces allowed in local part")
+    , ("[test]@example.com", False, "Square brackets only allowed within 
quotes")
+    , ("\"test\\test\"@example.com", True, "Any character can be escaped in a 
quoted string")
+    , ("\"test\"test\"@example.com", False, "Quotes cannot be nested")
+    , ("()[]\\;:,><@example.com", False, "Disallowed Characters")
+    , ("test@.", False, "Dave Child says so")
+    , ("test@example.", True, "")
+    , ("[email protected]", False, "Dave Child says so")
+    , ("test@[123.123.123.123", False, "Dave Child says so")
+    , ("[email protected]]", False, "Dave Child says so")
+    , ("NotAnEmail", False, "Phil Haack says so")
+    , ("@NotAnEmail", False, "Phil Haack says so")
+    , ("\"test\\\\blah\"@example.com", True, "")
+    , ("\"test\\blah\"@example.com", True, "Any character can be escaped in a 
quoted string")
+    , ("\"test\\\rblah\"@example.com", True, "Quoted string specifically 
excludes carriage returns unless escaped")
+    , ("\"test\rblah\"@example.com", False, "Quoted string specifically 
excludes carriage returns")
+    , ("\"test\\\"blah\"@example.com", True, "")
+    , ("\"test\"blah\"@example.com", False, "Phil Haack says so")
+    , ("customer/[email protected]", True, "")
+    , ("[email protected]", True, "")
+    , ("[email protected]", True, "")
+    , ("[email protected]", False, "Phil Haack says so")
+    , ("[email protected]", False, "Phil Haack says so")
+    , ("[email protected]", False, "Phil Haack says so")
+    , ("[email protected]", False, "Phil Haack says so")
+    , ("\"Austin@Powers\"@example.com", True, "")
+    , ("[email protected]", True, "")
+    , ("\"Ima.Fool\"@example.com", True, "")
+    , ("\"Ima Fool\"@example.com", True, "")
+    , ("Ima [email protected]", False, "Phil Haack says so")
+    , ("phil.h\\@\\@[email protected]", False, "Escaping can only happen in a 
quoted string")
+    , ("\"first\".\"last\"@example.com", True, "")
+    , ("\"first\".middle.\"last\"@example.com", True, "")
+    , ("\"first\\\\\"last\"@example.com", False, "Contains an unescaped quote")
+    , ("\"first\"[email protected]", True, "obs-local-part form as described 
in RFC 2822")
+    , ("first.\"last\"@example.com", True, "obs-local-part form as described 
in RFC 2822")
+    , ("\"first\".\"middle\".\"last\"@example.com", True, "obs-local-part form 
as described in RFC 2822")
+    , ("\"first.middle\".\"last\"@example.com", True, "obs-local-part form as 
described in RFC 2822")
+    , ("\"first.middle.last\"@example.com", True, "obs-local-part form as 
described in RFC 2822")
+    , ("\"first..last\"@example.com", True, "obs-local-part form as described 
in RFC 2822")
+    , ("foo@[\\1.2.3.4]", False, "RFC 5321 specifies the syntax for 
address-literal and does not allow escaping")
+    , ("\"first\\\\\\\"last\"@example.com", True, "")
+    , ("first.\"mid\\dle\".\"last\"@example.com", True, "Backslash can escape 
anything but must escape something")
+    , ("Test.\r\n Folding.\r\n [email protected]", True, "")
+    , ("first\\[email protected]", False, "Unquoted string must be an atom")
+    , ("Abc\\@[email protected]", False, "Was incorrectly given as a valid 
address in the original RFC3696")
+    , ("Fred\\ [email protected]", False, "Was incorrectly given as a valid 
address in the original RFC3696")
+    , ("Joe.\\\\[email protected]", False, "Was incorrectly given as a valid 
address in the original RFC3696")
+    , ("\"test\\\r\n blah\"@example.com", False, "Folding white space can\'t 
appear within a quoted pair")
+    , ("\"test\r\n blah\"@example.com", True, "This is a valid quoted string 
with folding white space")
+    , ("{^c\\@**Dog^}@cartoon.com", False, "This is a throwaway example from 
Doug Lovell\'s article. Actually it\'s not a valid address.")
+    , ("(foo)cal(bar)@(baz)iamcal.com(quux)", True, "A valid address 
containing comments")
+    , ("cal@iamcal(woo).(yay)com", True, "A valid address containing comments")
+    , ("cal(woo(yay)hoopla)@iamcal.com", True, "A valid address containing 
comments")
+    , ("cal(foo\\@bar)@iamcal.com", True, "A valid address containing 
comments")
+    , ("cal(foo\\)bar)@iamcal.com", True, "A valid address containing comments 
and an escaped parenthesis")
+    , ("cal(foo(bar)@iamcal.com", False, "Unclosed parenthesis in comment")
+    , ("cal(foo)bar)@iamcal.com", False, "Too many closing parentheses")
+    , ("cal(foo\\)@iamcal.com", False, "Backslash at end of comment has 
nothing to escape")
+    , ("first()[email protected]", True, "A valid address containing an empty 
comment")
+    , ("first.(\r\n middle\r\n )[email protected]", True, "Comment with folding 
white space")
+    , 
("first(12345678901234567890123456789012345678901234567890)last@(1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890)example.com",
 False, "Too long with comments, not too long without")
+    , ("first(Welcome to\r\n the (\"wonderful\" (!)) world\r\n of 
email)@example.com", True, "Silly example from my blog post")
+    , ("pete(his account)@silly.test(his host)", True, "Canonical example from 
RFC5322")
+    , ("c@(Chris\'s host.)public.example", True, "Canonical example from 
RFC5322")
+    , ("jdoe@machine(comment).  example", True, "Canonical example from 
RFC5322")
+    , ("1234   @   local(blah)  .machine .example", True, "Canonical example 
from RFC5322")
+    , ("first(middle)[email protected]", False, "Can\'t have a comment or white 
space except at an element boundary")
+    , ("first(abc.def)[email protected]", True, "Comment can contain a dot")
+    , ("first(a\"bc.def)[email protected]", True, "Comment can contain double 
quote")
+    , ("first.(\")middle.last(\")@example.com", True, "Comment can contain a 
quote")
+    , 
("first(abc(\"def\".ghi).mno)middle(abc(\"def\".ghi).mno).last@(abc(\"def\".ghi).mno)example(abc(\"def\".ghi).mno).(abc(\"def\".ghi).mno)com(abc(\"def\".ghi).mno)",
 False, "Can\'t have comments or white space except at an element boundary")
+    , ("first(abc\\(def)@example.com", True, "Comment can contain quoted-pair")
+    , 
("first.last@x(1234567890123456789012345678901234567890123456789012345678901234567890).com",
 True, "Label is longer than 63 octets, but not with comment removed")
+    , ("a(a(b(c)d(e(f))g)h(i)j)@example.com", True, "")
+    , ("a(a(b(c)d(e(f))g)(h(i)j)@example.com", False, "Braces are not properly 
matched")
+    , ("[email protected]", True, "")
+    , (".@", False, "")
+    , ("@bar.com", False, "")
+    , ("@@bar.com", False, "")
+    , ("[email protected]", True, "")
+    , ("aaa.com", False, "")
+    , ("[email protected]", False, "")
+    , ("[email protected]", False, "")
+    , ("aaa@[123.123.123.123]", True, "")
+    , ("aaa@[123.123.123.123]a", False, "extra data outside ip")
+    , ("[email protected].", True, "")
+    , ("[email protected]", True, "")
+    , ("[email protected]", True, "TLDs can be any length")
+    , ("[email protected]", True, "")
+    , ("[email protected]", False, "")
+    , ("[email protected]", False, "")
+    , ("[email protected]", True, "")
+    , ("\"hello my name is\"@stutter.com", True, "")
+    , ("\"Test \\\"Fail\\\" Ing\"@example.com", True, "")
+    , ("[email protected]", True, "")
+    , ("[email protected]", True, "Disagree with Paul Gregg 
here")
+    , ("[email protected]", False, "......")
+    , ("\"Joe\\\\Blow\"@example.com", True, "")
+    , ("Invalid \\\n Folding \\\n [email protected]", False, "This isn\'t 
FWS so Dominic Sayers says it\'s invalid")
+    , ("HM2Kinsists@(that comments are allowed)this.is.ok", True, "")
+    , ("user%[email protected]", True, "")
+    , ("\"first(last)\"@example.com", True, "")
+    , (" \r\n (\r\n x \r\n ) \r\n first\r\n ( \r\n x\r\n ) \r\n .\r\n ( \r\n 
x) \r\n last \r\n (  x \r\n ) \r\n @example.com", True, "")
+    , ("test.\r\n \r\n [email protected]", True, "obs-fws allows multiple lines")
+    , ("test. \r\n \r\n [email protected]", True, "obs-fws allows multiple lines 
(test 2: space before break)")
+    , ("test.\r\n\r\n [email protected]", False, "obs-fws must have at least one 
WSP per line")
+    , ("\"null \\\0\"@char.com", True, "can have escaped null character")
+    , ("\"null \0\"@char.com", False, "cannot have unescaped null character")
     -- items below here are invalid according to other RFCs (or opinions)
-    --("\"\"@example.com", False, "Local part is effectively empty"),
-    --("[email protected]", False, "ip need to be []"),
-    --("first.last@[.12.34.56.78]", False, "Only char that can precede IPv4 
address is \':\'"),
-    --("first.last@[12.34.56.789]", False, "Can\'t be interpreted as IPv4 so 
IPv6 tag is missing"),
-    --("first.last@[::12.34.56.78]", False, "IPv6 tag is missing"),
-    --("first.last@[IPv5:::12.34.56.78]", False, "IPv6 tag is wrong"),
-    --("first.last@[IPv6:1111:2222:3333::4444:5555:12.34.56.78]", False, "Too 
many IPv6 groups (4 max)"),
-    --("first.last@[IPv6:1111:2222:3333:4444:5555:12.34.56.78]", False, "Not 
enough IPv6 groups"),
-    --("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:12.34.56.78]", 
False, "Too many IPv6 groups (6 max)"),
-    --("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777]", False, "Not 
enough IPv6 groups"),
-    --("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888:9999]", 
False, "Too many IPv6 groups (8 max)"),
-    --("first.last@[IPv6:1111:2222::3333::4444:5555:6666]", False, "Too many 
\'::\' (can be none or one)"),
-    --("first.last@[IPv6:1111:2222:3333::4444:5555:6666:7777]", False, "Too 
many IPv6 groups (6 max)"),
-    --("first.last@[IPv6:1111:2222:333x::4444:5555]", False, "x is not valid 
in an IPv6 address"),
-    --("first.last@[IPv6:1111:2222:33333::4444:5555]", False, "33333 is not a 
valid group in an IPv6 address"),
-    --("[email protected]", False, "TLD can\'t be all digits"),
-    --("aaa@[123.123.123.333]", False, "not a valid IP"),
-    --("first.last@[IPv6:1111:2222:3333:4444:5555:6666:12.34.567.89]", False, 
"IPv4 part contains an invalid octet"),
-    --("a@b", False, ""),
-    --("a@bar", False, ""),
-    --("[email protected]", False, ""),
-    --("[email protected]", False, ""),
-    --("[email protected]", False, ""),
-    --("\"foo\"(yay)@(hoopla)[1.2.3.4]", False, "Address literal can\'t be 
commented (RFC5321)"),
-    --("first.\"\"[email protected]", False, "Contains a zero-length element"),
-    --("test@example", False, "Dave Child says so"),
-    
--("12345678901234567890123456789012345678901234567890123456789012...@example.com",
 False, "Local part more than 64 characters"),
-    
--("x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456",
 False, "Domain exceeds 255 chars"),
-    
--("t...@123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012.com",
 False, "255 characters is maximum length for domain. This is 256."),
-    
--("123456789012345678901234567890123456789012345678901234567...@12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.1234.example.com",
 False, "Entire address is longer than 256 characters"),
-    --("[email protected]", False, "Top Level Domain won\'t be all-numeric 
(see RFC3696 Section 2). I disagree with Dave Child on this one."),
-    
--("first.l...@x234567890123456789012345678901234567890123456789012345678901234.example.com",
 False, "Label can\'t be longer than 63 octets"),
-    --("first.last@com", False, "Mail host must be second- or lower level"),
-    --("[email protected]", False, "Label can\'t begin with a hyphen"),
-    --("[email protected]", False, "Label can\'t end with a hyphen"),
+    --, ("\"\"@example.com", False, "Local part is effectively empty")
+    --, ("[email protected]", False, "ip need to be []")
+    --, ("first.last@[.12.34.56.78]", False, "Only char that can precede IPv4 
address is \':\'")
+    --, ("first.last@[12.34.56.789]", False, "Can\'t be interpreted as IPv4 so 
IPv6 tag is missing")
+    --, ("first.last@[::12.34.56.78]", False, "IPv6 tag is missing")
+    --, ("first.last@[IPv5:::12.34.56.78]", False, "IPv6 tag is wrong")
+    --, ("first.last@[IPv6:1111:2222:3333::4444:5555:12.34.56.78]", False, 
"Too many IPv6 groups (4 max)")
+    --, ("first.last@[IPv6:1111:2222:3333:4444:5555:12.34.56.78]", False, "Not 
enough IPv6 groups")
+    --, ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:12.34.56.78]", 
False, "Too many IPv6 groups (6 max)")
+    --, ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777]", False, "Not 
enough IPv6 groups")
+    --, ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:7777:8888:9999]", 
False, "Too many IPv6 groups (8 max)")
+    --, ("first.last@[IPv6:1111:2222::3333::4444:5555:6666]", False, "Too many 
\'::\' (can be none or one)")
+    --, ("first.last@[IPv6:1111:2222:3333::4444:5555:6666:7777]", False, "Too 
many IPv6 groups (6 max)")
+    --, ("first.last@[IPv6:1111:2222:333x::4444:5555]", False, "x is not valid 
in an IPv6 address")
+    --, ("first.last@[IPv6:1111:2222:33333::4444:5555]", False, "33333 is not 
a valid group in an IPv6 address")
+    --, ("[email protected]", False, "TLD can\'t be all digits")
+    --, ("aaa@[123.123.123.333]", False, "not a valid IP")
+    --, ("first.last@[IPv6:1111:2222:3333:4444:5555:6666:12.34.567.89]", 
False, "IPv4 part contains an invalid octet")
+    --, ("a@b", False, "")
+    --, ("a@bar", False, "")
+    , ("[email protected]", False, "")
+    , ("[email protected]", False, "")
+    , ("[email protected]", False, "")
+    --, ("\"foo\"(yay)@(hoopla)[1.2.3.4]", False, "Address literal can\'t be 
commented (RFC5321)")
+    --, ("first.\"\"[email protected]", False, "Contains a zero-length 
element")
+    --, ("test@example", False, "Dave Child says so")
+    --, 
("12345678901234567890123456789012345678901234567890123456789012...@example.com",
 False, "Local part more than 64 characters")
+    , 
("x@x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456789.x23456",
 False, "Domain exceeds 255 chars")
+    , 
("t...@123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012.com",
 False, "255 characters is maximum length for domain. This is 256.")
+    --, 
("123456789012345678901234567890123456789012345678901234567...@12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.12345678901234567890123456789012345678901234567890123456789.1234.example.com",
 False, "Entire address is longer than 256 characters")
+    --, ("[email protected]", False, "Top Level Domain won\'t be 
all-numeric (see RFC3696 Section 2). I disagree with Dave Child on this one.")
+    , 
("first.l...@x234567890123456789012345678901234567890123456789012345678901234.example.com",
 False, "Label can\'t be longer than 63 octets")
+    --, ("first.last@com", False, "Mail host must be second- or lower level")
+    , ("[email protected]", False, "Label can\'t begin with a hyphen")
+    , ("[email protected]", False, "Label can\'t end with a hyphen")
     ]


Reply via email to