EncodedBody.hs 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. {-# LANGUAGE OverloadedStrings #-}
  2. module Data.SMTP.EncodedBody where
  3. import Data.ByteString.Lazy (ByteString)
  4. import qualified Data.ByteString.Lazy as BS
  5. import qualified Data.ByteString.Base64.Lazy as B64
  6. import qualified Data.ByteString.Lazy.Search as Search
  7. import GHC.Word (Word8)
  8. import Data.Default.Class
  9. import Data.Maybe (fromMaybe)
  10. import Data.SMTP.Email (EmailData)
  11. import Data.SMTP.Mime
  12. reencodeBody :: BodyEncoding -> EmailData -> EmailData
  13. reencodeBody toEncoding = id
  14. b7bitMessage :: EmailData -> EmailData
  15. b7bitMessage = B64.encode
  16. qpDecode :: EmailData -> EmailData
  17. qpDecode dt = unextend $ Search.replace "=\r\n" BS.empty dt
  18. where
  19. unextend d
  20. | BS.null d = d
  21. | BS.head d == 61 = let
  22. (a, rem') = BS.splitAt 2 d
  23. in BS.cons (unascii . reverse . BS.unpack $ a) (unextend rem')
  24. | otherwise = d
  25. unascii :: [Word8] -> Word8
  26. unascii [] = 0
  27. unascii (a:aa) = fromIntegral loc + 16 * unascii aa -- the list is reversed
  28. where
  29. loc = fromMaybe (
  30. fromMaybe (
  31. fromMaybe 0 $ BS.elemIndex a "abcdef" + 10
  32. ) BS.elemIndex a "ABCDEF" + 10
  33. ) BS.elemIndex a "0123456789"
  34. qpEncode :: EmailData -> EmailData
  35. qpEncode = quoteP
  36. where
  37. quoteP :: ByteString -> ByteString
  38. quoteP d = BS.intercalate "=\r\n" lineCount
  39. where
  40. lineCount = splitN 70 cat
  41. cat = BS.concatMap extendCharP d
  42. extendCharP :: Word8 -> ByteString
  43. extendCharP w
  44. | w > 32 && w < 127 && w /= 61= BS.singleton w
  45. | otherwise = BS.cons 61 $ asciicode w
  46. asciicode :: Word8 -> ByteString
  47. asciicode 0 = ""
  48. asciicode w = BS.cons h t
  49. where
  50. m = mod w 16
  51. h = if m < 10 then 48 + m else 65 + m
  52. t = asciicode $ div w 16
  53. splitN _ d | BS.null d = []
  54. splitN n d = h : splitN n t
  55. where
  56. (h, t) = BS.splitAt n d