I started using mime to parse email and extract attachments. Everything I did, the binary application was always distorted when I wrote it to disk. Then I realized that for some strange reason, all base64 attachments are already decoded when a message is parsed for data types. This is when my problem begins.
If this image is not working. The first thing I did was convert the extracted text attachment to ByteString using TE.encodeUtf8 . Bad luck. I tried all the Text.Encoding functions to convert Text to ByteString - nothing works. Then, for some stupid reason, I converted / encoded the extracted text back to base64, and then decrypted it again with base64, and it worked this time. Why?
So, if I encode the extracted attachment to base64 and decode it back, it works. B.writeFile "tmp/test.jpg" $ B.pack $ decode $ encodeRawString True $ T.unpack attachment Why? Why the simple text encoding in ByteString did not work, but does this stupidity do?
In the end, I played with him a little more and got to the point that he works with Data.ByteString.Char8 , like this B.writeFile "tmp/test.jpg" $ BC.pack $ T.unpack attachment So I still need convert Text to String, then String to ByteString.Char8, and only then does it work, and I get an intact image.
Can someone explain all this. Why is this pain associated with a binary image? Why can't I convert decoded base64 text to ByteString? What am I missing?
Thanks.
UPDATE
This is the code for retrieving attachments on request. I thought this did not apply to text encoding / decoding.
import Codec.MIME.Parse import Codec.MIME.Type import Data.Maybe import Data.Text (Text, unpack, strip) import qualified Data.Text as T (null) import Data.Text.Encoding (encodeUtf8) import Data.ByteString (ByteString) data Attachment = Attachment { attName :: Text , attSize :: Int , attBody :: Text } deriving (Show) genAttach :: Text -> [Attachment] genAttach m = let prs v = if isAttach v then [Just (mkAttach v)] else case mime_val_content v of Single c -> if T.null c then [Nothing] else prs $ parseMIMEMessage c Multi vs -> concatMap prs vs in let atts = filter isJust $ prs $ parseMIMEMessage m in if null atts then [] else map fromJust atts isAttach :: MIMEValue -> Bool isAttach mv = maybe False check $ mime_val_disp mv where check d = if (dispType d) == DispAttachment then True else False mkAttach :: MIMEValue -> Attachment mkAttach v = let prms = dispParams $ fromJust $ mime_val_disp v Single cont = mime_val_content v name = check . filter isFn where isFn (Filename _) = True isFn _ = False check = maybe "" (\(Filename n) -> n) . listToMaybe size = check . filter isSz where isSz (Size _) = True isSz _ = False check = maybe "" (\(Size n) -> n) . listToMaybe in Attachment { attName = name prms , attSize = let s = size prms in if T.null s then 0 else read $ unpack s , attBody = cont }