Haskellでメール送信
Google グループ
メールは HaskellNet を使うといいよ、と書かれている。
Author Jun Mukai って入門Haskellの著者かな?
cabal install iconv --global cabal install HaskellNet --global
ソースをDLしてきて example/smtp.hs の通りにすれば英語のメールは送信できた。
しかし日本語が…。
Text.Mime.showMessage はFromやToをMimeエンコードしてくれるのだが、値の全てをエンコードするようになっている。
To: =?ISO-2022-JP?b?〜〜〜?= <user@example.com>
こうなってほしいところだが
To: =?ISO-2022-JP?b?〜〜〜〜メールアドレスもここ〜〜〜?=
こういう動作になっている。
この動作だとメールサーバがホスト名を判別できずに
To: =?ISO-2022-JP?b?〜〜〜〜@example.comが見えない〜〜〜?=@example.com
と後ろにホスト名がくっついて送信された。
あとiso-2022-jpに変換するためにconvert関数を使おうと思ったが、convert関数を使うためには Data.ByteString.Lazy.Char8 を使わないといけない?だけれどHaskellNetのメール送信は Data.ByteString.Char8 を使うようなので若干面倒なことに。
なんかやり方か使いどころが間違ってるのかもわからんが、行き当たりばったりな感じで書いてみた。
import HaskellNet.SMTP (connectSMTP, sendMail, closeSMTP) import qualified Data.ByteString.Char8 as BS import qualified Data.ByteString.Lazy.Char8 as LBS import Codec.Text.IConv (convert) import Codec.Binary.UTF8.String (encodeString) import Text.Mime (showMessage, b64Encode) smtpServer = "localhost" sendFrom = "user1@example.com" sendTo = "user2@example.com" headerFrom = b64Header "\"テストプログラムからの日本語文字テスト送信\"" ++ "<" ++ sendFrom ++ ">" headerTo = b64Header"\"宛先ユーザ\"" ++ "<" ++ sendTo ++ ">" charset = "ISO-2022-JP" main = do con <- connectSMTP smtpServer sendMail sendFrom [sendTo] (BS.pack $ show $ showMessage charset msg) con closeSMTP con msg = ([("From", headerFrom) ,("To", headerTo) ,("Content-Type", "text/plain; charset=" ++ charset) ,("Subject", b64Header "Test 日本語メールテスト、エンコード後に改行あり")], BS.pack (toCharset "\r\nhaskellnet のメール送信。\r\n.")) b64Header :: String -> String b64Header s = "=?" ++ charset ++ "?b?" ++ b64Encode (toCharset s) ++ "?=" toCharset = LBS.unpack . convert "UTF-8" charset . LBS.pack . encodeString
pack、unpackが冗長な気がしてならないが、取り敢えずこれで正しいフォーマットで送れた。
encodeStringとかまだよく分かっていない。
ローカルから別のサーバーにメールを送る場合だと文字列をエンコードさえすればあとはpopen的なものを使ってsendmailに渡せばいいわけだから、無駄なことを色々やってる気がする。
しかしHaskellプログラムからメールを送信するための情報がどこにあるか分からん…。