generated from tpl/purs
feat: check wildcard addresses, retry several times to make sure that it really doesn't exist
This commit is contained in:
parent
825c35969c
commit
687a9c76b8
@ -3,6 +3,7 @@ package:
|
||||
- aff
|
||||
- aff-promise
|
||||
- arrays
|
||||
- bifunctors
|
||||
- effect
|
||||
- either
|
||||
- foldable-traversable
|
||||
@ -11,6 +12,7 @@ package:
|
||||
- nullable
|
||||
- prelude
|
||||
- strings
|
||||
- tailrec
|
||||
- transformers
|
||||
- typelevel-prelude
|
||||
name: email-address
|
||||
|
@ -1,13 +1,16 @@
|
||||
module Effect.Email (EmailError(..), emailErrorToString, deliverable) where
|
||||
module Effect.Email (EmailError(..), emailErrorCode, emailErrorToString, deliverable) where
|
||||
|
||||
import Prelude
|
||||
|
||||
import Control.Monad.Cont (lift)
|
||||
import Control.Monad.Error.Class (throwError)
|
||||
import Control.Monad.Except (ExceptT)
|
||||
import Control.Monad.Error.Class (liftEither, throwError)
|
||||
import Control.Monad.Except (ExceptT(..), runExceptT)
|
||||
import Control.Monad.Rec.Class (Step(..), tailRecM)
|
||||
import Control.Promise (Promise)
|
||||
import Control.Promise as Promise
|
||||
import Data.Array as Array
|
||||
import Data.Bifunctor (lmap)
|
||||
import Data.Either (Either(..))
|
||||
import Data.Email (Email)
|
||||
import Data.Email as Email
|
||||
import Data.Eq.Generic (genericEq)
|
||||
@ -25,14 +28,25 @@ foreign import checkEmailImpl :: String -> Effect $ Promise $ QEDResult
|
||||
|
||||
data EmailError
|
||||
= EmailUnreachable Email
|
||||
| EmailWildcardExists Email
|
||||
| EmailSyntaxInvalid Email
|
||||
| EmailMXInvalid Email
|
||||
| EmailMXNoRecords Email
|
||||
| EmailSMTPInvalid Email
|
||||
| EmailSMTPError Email String
|
||||
|
||||
emailErrorCode :: EmailError -> String
|
||||
emailErrorCode (EmailUnreachable _) = "email_unreachable"
|
||||
emailErrorCode (EmailWildcardExists _) = "email_wildcard"
|
||||
emailErrorCode (EmailSyntaxInvalid _) = "email_invalid"
|
||||
emailErrorCode (EmailMXInvalid _) = "email_mx_bad"
|
||||
emailErrorCode (EmailMXNoRecords _) = "email_mx_missing"
|
||||
emailErrorCode (EmailSMTPInvalid _) = "email_smtp_bad"
|
||||
emailErrorCode (EmailSMTPError _ _) = "email_smtp_error"
|
||||
|
||||
emailErrorToString :: EmailError -> String
|
||||
emailErrorToString (EmailUnreachable e) = "Email <" <> Email.toString e <> "> is unreachable"
|
||||
emailErrorToString (EmailWildcardExists e) = "Wildcard address <*." <> Email.domain e <> "> is registered; cannot definitively say if <" <> Email.toString e <> "> exists."
|
||||
emailErrorToString (EmailSyntaxInvalid e) = "Email <" <> Email.toString e <> "> is invalid"
|
||||
emailErrorToString (EmailMXInvalid e) = "Email <" <> Email.toString e <> "> domain has invalid MX record"
|
||||
emailErrorToString (EmailMXNoRecords e) = "Email <" <> Email.toString e <> "> domain has no MX records"
|
||||
@ -64,10 +78,9 @@ type QEDResult =
|
||||
}
|
||||
}
|
||||
|
||||
deliverable :: Email -> ExceptT EmailError Aff Email
|
||||
deliverable email' = do
|
||||
deliverableOnce :: Email -> ExceptT EmailError Aff Email
|
||||
deliverableOnce email' = do
|
||||
let email = Email.toString email'
|
||||
|
||||
{ reachable, syntax, mx, smtp } <- lift $ Promise.toAffE $ checkEmailImpl email
|
||||
when (not reachable) $ throwError $ EmailUnreachable email'
|
||||
when (not syntax.valid) $ throwError $ EmailSyntaxInvalid email'
|
||||
@ -75,5 +88,24 @@ deliverable email' = do
|
||||
when (not smtp.valid) $ throwError $ EmailSMTPInvalid email'
|
||||
when (maybe true Array.null $ Nullable.toMaybe $ mx.mxRecords) $ throwError $ EmailMXNoRecords email'
|
||||
for_ (Nullable.toMaybe $ smtp.error) $ throwError <<< EmailSMTPError email'
|
||||
|
||||
pure email'
|
||||
|
||||
deliverable :: Email -> ExceptT EmailError Aff Email
|
||||
deliverable email' =
|
||||
let
|
||||
attempt n
|
||||
| n < 10 =
|
||||
do
|
||||
res <- runExceptT $ deliverableOnce email'
|
||||
case res of
|
||||
Left (EmailUnreachable _) -> pure $ Loop $ n + 1
|
||||
Left e -> pure $ Done $ Left e
|
||||
Right ok -> pure $ Done $ Right ok
|
||||
| otherwise = pure $ Done $ Left $ EmailUnreachable email'
|
||||
in
|
||||
do
|
||||
wildcard <- liftEither $ lmap (const $ EmailSyntaxInvalid email') $ Email.parse $ "*@" <> Email.domain email'
|
||||
res <- lift $ runExceptT $ deliverableOnce wildcard
|
||||
case res of
|
||||
Right _ -> throwError $ EmailWildcardExists email'
|
||||
_ -> ExceptT $ tailRecM attempt 0
|
||||
|
Loading…
Reference in New Issue
Block a user