module Network.Mail.SMTP.Auth (
authLogin
) where
import Crypto.Hash.MD5 (hash)
import qualified Data.ByteString.Base16 as B16 (encode)
import qualified Data.ByteString.Base64 as B64 (encode)
import Data.ByteString (ByteString)
import Data.List
import Data.Bits
import Data.Monoid
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as B8
import Network.Mail.SMTP.SMTP
import Network.Mail.SMTP.Types
authLogin :: UserName -> Password -> SMTP ()
authLogin username password = do
reply <- bytes (B8.pack "AUTH LOGIN")
expectCode 334
bytes $ b64Encode username
expectCode 334
bytes $ b64Encode password
expectCode 235
toAscii :: String -> ByteString
toAscii = B.pack . map (toEnum.fromEnum)
b64Encode :: String -> ByteString
b64Encode = B64.encode . toAscii
hmacMD5 :: ByteString -> ByteString -> ByteString
hmacMD5 text key = hash (okey <> hash (ikey <> text))
where key' = if B.length key > 64
then hash key <> B.replicate 48 0
else key <> B.replicate (64B.length key) 0
ipad = B.replicate 64 0x36
opad = B.replicate 64 0x5c
ikey = B.pack $ B.zipWith xor key' ipad
okey = B.pack $ B.zipWith xor key' opad
encodePlain :: UserName -> Password -> ByteString
encodePlain user pass = b64Encode $ intercalate "\0" [user, user, pass]
encodeLogin :: UserName -> Password -> (ByteString, ByteString)
encodeLogin user pass = (b64Encode user, b64Encode pass)
cramMD5 :: String -> UserName -> Password -> ByteString
cramMD5 challenge user pass =
B64.encode $ B8.unwords [user', B16.encode (hmacMD5 challenge' pass')]
where
challenge' = toAscii challenge
user' = toAscii user
pass' = toAscii pass