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")
]