details,
help,
program,
- summary,
- typFile )
+ summary )
-- Get the version from Cabal.
import Data.Version ( showVersion )
--- We optionally accept input/output files to use instead of
--- stdin/stdout.
data Args = Args { accept_a :: Bool,
- input_file :: Maybe FilePath,
- output_file :: Maybe FilePath,
rfc5322 :: Bool }
deriving (Show, Data)
accept_a_help =
"Accept an 'A' record for the domain instead of requiring an MX record."
-input_file_help :: String
-input_file_help =
- "Path to the input file (default: stdin), one email address per line"
-
-output_file_help :: String
-output_file_help =
- "Path to the output file (default: stdout)"
-
rfc5322_help :: String
rfc5322_help =
"Validate according to RFC 5322 (incredibly lenient)."
arg_spec :: Args
arg_spec =
Args { accept_a = def &= help accept_a_help,
- input_file = def &= typFile &= help input_file_help,
- output_file = def &= typFile &= help output_file_help,
rfc5322 = def &= help rfc5322_help }
&= program program_name
&= summary my_summary
+++ /dev/null
--- | All exit codes that the program can return (excepting
--- ExitSuccess). There's only one, since the program will try and
--- fail forever upon errors.
-module ExitCodes (
- exit_args_parse_failed,
- exit_input_file_doesnt_exist )
-where
-
--- | Indicates that the command-line arguments could not be parsed.
-exit_args_parse_failed :: Int
-exit_args_parse_failed = 1
-
--- | Indicates that the input file given on the command-line does not
--- exist.
-exit_input_file_doesnt_exist :: Int
-exit_input_file_doesnt_exist = 2
import Control.Concurrent.ParallelIO.Global (
parallelInterleaved,
stopGlobalPool )
-import Control.Monad ( unless )
import qualified Data.ByteString.Char8 as BS (
hGetContents,
hPutStrLn,
lines,
null,
- pack,
- readFile )
+ pack )
import Network.DNS (
Domain,
Resolver,
makeResolvSeed,
withResolver )
import Network.DNS.Lookup ( lookupA, lookupMX )
-import System.Directory ( doesFileExist )
-import System.Exit ( exitWith, ExitCode( ExitFailure ) )
import System.IO (
- IOMode( WriteMode ),
- hClose,
hFlush,
- openFile,
stdin,
stdout )
import CommandLine (
- Args( Args, accept_a, input_file, output_file, rfc5322 ),
+ Args( Args, accept_a, rfc5322 ),
get_args )
import EmailAddress(
Address,
parts,
validate_syntax )
-import ExitCodes ( exit_input_file_doesnt_exist )
-- | Resolver parameters. We increase the default timeout from 3 to 10
main = do
Args{..} <- get_args
- -- Get the input from either stdin, or the file given on the command
- -- line.
- input <- case input_file of
- Nothing -> BS.hGetContents stdin
- Just path -> do
- is_file <- doesFileExist path
- unless is_file $
- exitWith (ExitFailure exit_input_file_doesnt_exist)
- BS.readFile path
-
- -- Do the same for the output handle and stdout.
- output_handle <- case output_file of
- Nothing -> return stdout
- Just path -> openFile path WriteMode
-
- -- Split the input into lines.
+ -- Split stdin into lines, which should result in a list of addresses.
+ input <- BS.hGetContents stdin
let addresses = BS.lines input
-- And remove the empty ones.
-- Output the results.
let valid_addresses = map fst valid_results
- mapM_ (BS.hPutStrLn output_handle) valid_addresses
+ mapM_ (BS.hPutStrLn stdout) valid_addresses
stopGlobalPool
-
- -- Clean up. It's safe to try to close stdout.
- hFlush output_handle
- hClose output_handle
+ hFlush stdout