对简单的smtp使用tls-extra [英] Using tls-extra for simple smtp
问题描述
我试图编写一个简单的脚本来通过我的Gmail账户发送邮件。但我是初学者,所以不是那么简单。我尝试谷歌,但免除了骇客,根本没有帮助或例子。
问题是我没有找到使用tls-extra(或tls )开始STARTTLS交换。
好的,这里是代码:
import Network
import Network.TLS.Extra
import System.IO
import Text.Printf
server =smtp.gmail.com
port = 25 - 必须chage,我认为
forever a = a>>永远是
main = test1
write :: Handle - >字符串 - > IO()
写入hs = do
hPrintf h%s\r\\\
s
printf>%s \ ns
listen :: Handle - > IO()
listen h = forever $ hGetLine h>> = putStrLn
test1 = do h < - connectTo server(PortNumber(fromIntegral port))
hSetBuffering h NoBuffering
写hEHLO
写hSTARTTLS
听h
$ b $另一件事是我使用listen函数来了解正在发生的事情。但我无法弄清楚如何将它与写入一起使用。也就是说,我希望能够在发送一些数据时看到服务器端发生了什么。
我发现了两个可能解决我的问题的函数:
connectionClient :: CryptoRandomGen g =>字符串 - >字符串 - > TLSParams - > g - > IO(TLSCtx句柄)
forkIO :: IO() - > IO ThreadId
第一个是tls,第二个是同时发送和接收。
但似乎无法让他们工作。
我希望我不会在这里混乱,任何帮助将不胜感激。
PS:英文不是我的母语。
编辑:
所以,我取得了一些进展。
import Network
import Network.TLS
import Network.TLS.Extra
import System.IO
导入Text.Printf
导入Control.Monad(永久)
导入Control.Concurrent(threadDelay)
将合格的Data.ByteString.Char8导入为B
import Crypto.Random
serv :: String
serv =smtp.gmail.com
port :: Int
port = 25 - 必须变动,我认为
main :: IO()
main = test1
write :: Handle - >字符串 - > IO()
写入hs = do
hPrintf h%s\r\\\
s
printf>%s \ ns
listen :: Handle - > IO()
listen h = forever $ hGetLine h>> = putStrLn
printSock :: Handle - >字符串 - > IO()
printSock hs =写入hs
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 hEHLO
printSock hSTARTTLS
--google等待握手
- 问题出在这里
g< - newGenIO :: IO SystemRandom
tlsH< - client params gh
handshake tlsH - 握手失败
但是,我不知道如何协商tls握手。
我不得不说,我很惊讶缺乏答案。其他人几次遇到问题,社区很快就会提供帮助。但是这似乎没有意义(只是一个常式)。在SO或甚至在#haskell或developpez.com。
无论如何,一些关于谷歌和tls的指针将受到欢迎。
我看了一下msmtp客户端代码,但是坦率地说我没有要求的级别。
{ - #LANGUAGE OverloadedStrings# - }
将合格的Data.ByteString导入为B
import Data.ByteString.Char8()
import Network.Connection
import Data.Default
readHeader con = do
l < - connectionGetLine 1024 con
putStrLn $ show l
if B.isPrefixOf250l
then return()
else readHeader con
main = do
ctx< - initConnectionContext
con< - connectTo ctx $ ConnectionParams
{connectionHostname =smtp.gmail.com
,connectionPort = 25
,connectionUseSecure = Nothing
,connectionUseSocks = Nothing
}
- 读取服务器标题
connectionGetLine 1024 con>>> = putStrLn。显示
- 说ehlo到smtp服务器
connectionPut conEHLO \\\
- 等待回复并打印
readHeader con
- Tell服务器启动一个TLS上下文。
connectionPut conSTARTTLS\\\
- 等待回复并打印
connectionGetLine 1024 con>> = putStrLn。显示
- 关联TLS上下文
connectionSetSecure ctx con def
-------连接现在是安全的
- 发送凭据,密码,问问题等。
- 然后礼貌地退出。
connectionPut conQUIT\\\
connectionClose con
I am trying to write a simple script to send a mail via my gmail account. But I am a beginner so it is not that simple. I tryed google but exept for hackage, there is no help or examples at all.
The problem is that I did not find the way to use tls-extra(or tls) to initiate the STARTTLS exchange.
Ok, here is the code:
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
Another thing is that I use the listen function to know what is going on. But I cannot figure out how to use it along with write. That is to say, I would like to be able to see what is going on server-side while sending some data.
I found two functions that may resolve my problems:
connectionClient :: CryptoRandomGen g => String -> String -> TLSParams -> g -> IO (TLSCtx Handle)
forkIO :: IO () -> IO ThreadId
The first for tls and the second to send and receive at the same time. But can't seem to make them work.
I hope I am not to messy here, any help would be appreciated.
PS: English is not my native.
EDIT: So, I have made some progress.
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
Still, I cannot figure out how to negotiate that tls handshake.
I have to say, I am quite surprised by the lack of answer. The others few times I had a problem, the community was quite quick to help. But this doesn't seem to interess (just a constatation). Here at SO or even at #haskell or developpez.com.
Anyways some pointers about google and tls would be welcome. I have taken a look at the msmtp client code but frankly I don't have the required level.
You could use the connection package which simplify client connection and provide all the necessary bits for this. The following code will works to connect to 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
这篇关于对简单的smtp使用tls-extra的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!