1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071 |
- {-# LANGUAGE OverloadedStrings #-}
- -- Parser of email account
- module Data.SMTP.Parser.Account where
- import Data.SMTP.Types.Account
- import Data.Attoparsec.ByteString.Char8.Extras
- import Data.SMTP.Parser.Host
- import Control.Applicative ((<|>))
- import Data.Attoparsec.ByteString.Char8
- import qualified Data.ByteString as BS
- import qualified Data.ByteString.Lazy as LBS
- import qualified Data.ByteString.Search as Search
- import Data.ByteString (ByteString)
- import qualified Codec.Binary.UTF8.String as UTF8
- import qualified Data.Char as C
- import qualified Data.Word8 as W
- parseAccount :: Parser Account
- parseAccount = quotedAccount <|> escapedAccount <|> plainAccount
- quotedAccount :: Parser Account
- quotedAccount = do
- char '\"'
- a <- parseAccount
- char '\"'
- return a
- plainAccount :: Parser Account
- plainAccount = do
- (fa, AccountName a, h, ts) <- plainAddress
- if BS.null a
- then fail "empty account name"
- else return $ Account fa (PersonalName "") (AccountName a) h ts
-
- escapedAccount :: Parser Account
- escapedAccount = do
- n' <- takeTill (`elem` ("\"'<\r\n" :: String))
- let n = fst . BS.spanEnd W.isSpace $ n'
- char '<'
- (fa, a, h, ts) <- plainAddress
- char '>'
- return $ Account (BS.concat [n', "<", fa, ">"]) (PersonalName n) a h ts
-
- plainAddress :: Parser (ByteString, AccountName, HostName, [AccountTag])
- plainAddress = do
- (fa, a, ts) <- scanAccountName
- (h, hasAt) <-
- (do
- char '@'
- h <- scanHostName
- return (h, True)
- ) <|> return ("", False)
- return (if hasAt then BS.concat [fa, "@", h] else fa, a, HostName h, ts)
- scanAccountName :: Parser (ByteString, AccountName, [AccountTag])
- scanAccountName = do
- f <- quotedString '\\' " ][,:\\;<>\"\r\n@" "\r\n"
- let ff = Search.split "+" f
- case ff of
- [] -> return (f, normalizeA f, [])
- [_] -> return (f, normalizeA f, [])
- (a:aa) -> return (f, normalizeA a, map AccountTag aa)
-
- normalizeA :: ByteString -> AccountName
- normalizeA a = AccountName na
- where
- a' = LBS.unpack $ Search.replace ("([^)]*)"::ByteString) (""::ByteString) a
- a'' = UTF8.encode . map C.toLower . UTF8.decode $ a'
- na = BS.pack a''
|