Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using tls-extra for simple smtp

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.

like image 574
Sarfraz Avatar asked Jul 03 '12 12:07

Sarfraz


People also ask

Can SMTP use TLS?

Secure SMTP can be achieved through the enablement of TLS on your mail server. By enabling TLS, you are encrypting the SMTP protocol on the transport layer by wrapping SMTP inside of a TLS connection.

How do I enable TLS in SMTP?

Enable Outbound TLSSelect a SMTP Virtual Server -> Right Click -> Properties -> Delivery -> Outbound Security -> Check TLS encryption -> Click OK -> Click Apply .

What is TLS mode in SMTP?

SSL and TLS are the standard technology to encrypt connections between two computers. This prevents any third parties from spying on these communications. TLS is the successor to SSL. It is supported by all modern and secure systems that handle internet traffic, including Fastmail.

Does SMTP use TLS or SSL?

TLS and SSL are used for many different reasons on the internet and help make the internet a more secure place. One of the popular uses of TLS is SMTP for securely transmitting email messages between servers.


2 Answers

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
like image 82
Tab Avatar answered Oct 12 '22 03:10

Tab


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.

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 

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.

like image 1
mhwombat Avatar answered Oct 12 '22 04:10

mhwombat