2012-07-03 7 views
9

私のGmailアカウントを介してメールを送る簡単なスクリプトを書こうとしています。しかし、私は初心者ですので、それは簡単ではありません。私はgoogleを試してみましたが、ハッキングのために実行しました。ヘルプや例はまったくありません。簡単なsmtpのためのtls-extraの使用

問題は、tls-extra(またはtls)を使用してSTARTTLS交換を開始する方法が見つからないことです。

[OK]を、ここでのコードは次のとおりです。

import Network 
import Network.TLS.Extra 
import System.IO 
import Text.Printf 

server = "smtp.gmail.com" 
port = 25 --that has to chage, I think 

forever a = a >> forever a 

main = test1 

write :: Handle -> String -> IO() 
write h s = do 
    hPrintf h "%s\r\n" s 
    printf "> %s\n" s 

listen :: Handle -> IO() 
listen h = forever $ hGetLine h >>= putStrLn 

test1 = do h <- connectTo server (PortNumber (fromIntegral port)) 
      hSetBuffering h NoBuffering 
      write h "EHLO" 
      write h "STARTTLS" 
      listen h 

もう一つは、私は何が起こっているかを知るために聞く機能を使用することです。しかし、私は書き込みと一緒にそれを使用する方法を把握することはできません。つまり、私はいくつかのデータを送信しながらサーバ側で何が起こっているのかを見ることができるようにしたいと考えています。

私は私の問題を解決することができる二つの機能が見つかりました:TLSと同時に送受信する第二のための最初の

connectionClient :: CryptoRandomGen g => String -> String -> TLSParams -> g -> IO (TLSCtx Handle) 
forkIO :: IO() -> IO ThreadId 

を。 しかし、それらを機能させるように見えることはできません。

私はここで乱雑ではないと思いますが、どんな助けもありがたいです。

PS:英語は母国語ではありません。

編集: 私はいくつかの進歩を遂げました。

import Network 
import Network.TLS 
import Network.TLS.Extra 
import System.IO 
import Text.Printf 
import Control.Monad (forever) 
import Control.Concurrent (threadDelay) 
import qualified Data.ByteString.Char8 as B 
import Crypto.Random 

serv :: String 
serv = "smtp.gmail.com" 
port :: Int 
port = 25 --that has to chage, I think 

main :: IO() 
main = test1 

write :: Handle -> String -> IO() 
write h s = do 
    hPrintf h "%s\r\n" s 
    printf "> %s\n" s 

listen :: Handle -> IO() 
listen h = forever $ hGetLine h >>= putStrLn 

printSock :: Handle -> String -> IO() 
printSock h s = do write h s 
        hGetLine h >>= putStrLn 
        threadDelay 25 

params :: TLSParams 
params=defaultParams {pConnectVersion=TLS12 
        ,pAllowedVersions=[TLS10, TLS11, TLS12] 
        ,pCiphers=ciphersuite_all} 

test1 = do h <- connectTo serv (PortNumber (fromIntegral port)) 
      hSetBuffering h NoBuffering 
      printSock h "EHLO" 
      printSock h "STARTTLS" 
      --google waits for tls handshake 
      --the problem is from here 
      g <- newGenIO :: IO SystemRandom 
      tlsH <- client params g h 
      handshake tlsH --the handshake is failling 

まだ、私はどのようにtlsハンドシェイクを交渉するのか分かりません。

私は、答えの欠如に非常に驚いています。他にも何度か問題がありましたが、コミュニティはすぐに手伝ってくれました。しかし、これは黙っているようではありません(ただの文章)。ここでは、または#haskellやdeveloppez.comでさえも。

とにかくgoogleとtlsに関するいくつかの参考情報を歓迎します。 私はmsmtpクライアントコードを見ましたが、率直に言って私は必要なレベルを持っていません。

+0

私は全く同じ問題があります。あなたは把握することができましたか? – Salil

+0

本当にあなたの質問には関係ありませんが、私は、永遠にベースライブラリに定義されていることを指摘しておきます。 [Hackage](http://hackage.haskell.org/packages/archive/base/latest/doc/html/Control-Monad.html#v:forever)を参照してください。 –

答えて

5

クライアント接続を簡略化し、これに必要なすべてのビットを提供する接続パッケージを使用できます。次のコードはsmtp.gmail.comへの接続に使用します:

{-# LANGUAGE OverloadedStrings #-} 
import qualified Data.ByteString as B 
import Data.ByteString.Char8() 
import Network.Connection 
import Data.Default 

readHeader con = do 
    l <- connectionGetLine 1024 con 
    putStrLn $ show l 
    if B.isPrefixOf "250 " l 
     then return() 
     else readHeader con 

main = do 
    ctx <- initConnectionContext 
    con <- connectTo ctx $ ConnectionParams 
          { connectionHostname = "smtp.gmail.com" 
          , connectionPort  = 25 
          , connectionUseSecure = Nothing 
          , connectionUseSocks = Nothing 
          } 

    -- read the server banner 
    connectionGetLine 1024 con >>= putStrLn . show 
    -- say ehlo to the smtp server 
    connectionPut con "EHLO\n" 
    -- wait for a reply and print 
    readHeader con 
    -- Tell the server to start a TLS context. 
    connectionPut con "STARTTLS\n" 
    -- wait for a reply and print 
    connectionGetLine 1024 con >>= putStrLn . show 

    -- negociate the TLS context 
    connectionSetSecure ctx con def 

    ------- connection is secure now 
    -- send credential, passwords, ask question, etc. 

    -- then quit politely. 
    connectionPut con "QUIT\n" 
    connectionClose con 
+0

投稿したコードは既に動作していましたが、コードはより洗練されています。とにかく、それ以来、私はネイティブコードソリューションを落として、dosとnixで利用可能なmsmtpコマンドのカスタムラッパーを使用しています。 – Sarfraz

1

あなたの問題の原因を正確にはわかりません(私のSMTPは少し錆びています)が、間違ったポートに接続していると思われます。私はこれらがGoogleとSMTPを使用するための正しいパラメータだと思う。

Gmail SMTP server address: smtp.gmail.com 
Gmail SMTP user name: Your full Gmail address (e.g. [email protected]) 
Gmail SMTP password: Your Gmail password 
Gmail SMTP port: 465 
Gmail SMTP TLS/SSL required: yes 

編集:私はあなたがTLS/SSLを使用して、ユーザ名とパスワードでログインできるようになるSMTPパッケージがあったかどうかを確認するためにHackageの迅速な検索をしましたが、私は何も表示されませんでした。 (私は何か見落としていたかもしれません!)私が見つけた最も近いものはsimplesmtpclientでした。私はそれがSSLをサポートしているとは思わないが、おそらくあなたはそれを拡張することも、自分自身を書くためのガイドとして使うこともできます。

関連する問題