-validate_mx :: Resolver -> Domain -> IO Bool
-validate_mx resolver domain = do
- result <- lookupMX resolver domain
- case result of
- Nothing -> return False
- _ -> return True
+-- | Check whether the given domain has a valid MX record.
+--
+-- NULLMX (RFC7505) records consisting of a single period must not
+-- be accepted. Moreover, the existence of a NULLMX must be reported
+-- back to the caller because the whole point of a NULLMX is that
+-- its existence should preempt an @A@ record check. We abuse the
+-- return type for this, and return @Nothing@ in the event of a
+-- NULLMX. Otherwise we return @Just True@ or @Just False@ to
+-- indicate the existence (or not) of MX records.
+--
+-- RFC7505 states that a domain MUST NOT have any other MX records
+-- if it has a NULLMX record. We enforce this. If you have a NULLMX
+-- record and some other MX record, we consider the set invalid.
+--
+validate_mx :: Resolver -> Domain -> IO (Maybe Bool)
+validate_mx resolver domain
+ | domain `elem` common_domains = return $ Just True
+ | otherwise = do
+ result <- lookupMX resolver domain
+ case result of
+ Left _ ->
+ return $ Just False
+ Right mxs ->
+ case mxs of
+ [] -> return $ Just False
+ _ -> if any (is_null) mxs
+ then return Nothing
+ else return $ Just True
+ where
+ nullmx :: Domain
+ nullmx = BS.pack "."