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.
I don't know exactly what's causing the problem you're having (My SMTP is a little rusty), but I believe part of the problem is that you're connecting on the wrong port. I think these are the correct parameters for using SMTP with Google.
Edit: I did a quick search of Hackage to see if there was an SMTP package that would allow you to login with a username and password, using TLS/SSL, but I didn't see anything. (I could have overlooked something, though!) The closest I found was simplesmtpclient. I don't think it supports SSL, but perhaps you could extend that, or use it as a guide for writing your own.
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: