Compare commits

...

58 Commits

Author SHA1 Message Date
Sarah Vaupel
1d346b07fb 0.3.4.1 -> 0.4.0.2 2025-06-12 14:49:44 +02:00
Leza Morais Lutonda
6fe62d91af
Merge pull request #23 from limick/master
Bump dependency on 'network' package so it compiles with LTS-13
2019-01-17 12:31:55 +01:00
limick
4b2ea920e9 Bump dependency on 'network' package so it compiles with Stackage LTS-13. 2019-01-06 12:02:17 +02:00
Leza Lutonda
9bb3c2299f Bump version number to 0.3.4.0. Solves fpco/stackage#2693 2017-08-01 15:42:04 +01:00
Leza Lutonda
94266dd970 Update dependencies. See fpco/stackage#2693 2017-08-01 14:59:33 +01:00
Leza Lutonda (Lemol-C)
631a0bcbbb Fix a bun in the smtp example. 2016-07-29 14:30:00 +01:00
Leza Morais Lutonda (Lemol-C)
00602e297b Bump version number to 0.3.3.0 2016-04-25 00:04:14 +01:00
Leza Morais Lutonda
48a2c8c1c3 Merge pull request #17 from k0ral/master
Derive Eq, Ord and Show instances for Settings data type
2016-04-24 23:44:17 +01:00
koral
7432711d62 Derive Eq, Ord and Show instances for Settings data type 2016-04-23 11:27:42 +02:00
Leza Morais Lutonda (Lemol-C)
702d54f76d Set lemol as a maintainer 2015-11-09 03:37:28 -05:00
Daniel P. Wright
3bbb4a6e05 Merge pull request #15 from lemol/master
Bump HaskellNet version to <0.6
2015-11-09 07:35:17 +09:00
Leza Morais Lutonda (Lemol-C)
61969afabf Bump HaskellNet version to <0.6
(see fpco/stackage#960)
2015-11-06 03:07:03 -05:00
Daniel P. Wright
a777a369d4 Bump version number to 0.3.1.0 2015-10-29 11:50:10 +09:00
Daniel P. Wright
f7e895fb06 Merge pull request #13 from da-x/bump-tls-version
Bump tls version dep, after having verified it worked with tls-1.3.*
2015-09-28 16:21:15 +09:00
Dan Aloni
35c03e8f84 Bump tls version dep, after having verified it worked with tls-1.3.* 2015-09-25 20:03:49 +03:00
Daniel P. Wright
ec5c163e7a Bump version number to 0.3.0.0
Commit bc814b6345 renames one of the
functions, making this a backwards-incompatible change, so I'm upping
the version number to 0.3.0.0 even though the other changes are
relatively minor.
2015-04-20 08:26:00 +09:00
Daniel P. Wright
de90b9b120 Merge pull request #12 from lemol/master
Update gmail example
2015-04-09 15:09:15 +09:00
Leza Morais Lutonda (Lemol-C)
717f8e202a Update gmail example 2015-04-08 23:58:44 -04:00
Daniel P. Wright
9357f7e609 Merge pull request #11 from lemol/master
Re-export Network.HaskellNet.* modules
2015-04-09 09:38:31 +09:00
Leza Morais Lutonda (Lemol-C)
bd46b74785 Make HaskellNet.X.SSL re-exports HaskellNet.X and SSL.Settings
see dpwright#10
2015-04-08 13:26:10 -04:00
Leza Morais Lutonda (Lemol-C)
e61f8db1bc Update gitignore 2015-04-08 12:57:59 -04:00
Daniel P. Wright
c9c0127b6d Merge pull request #9 from lemol/master
Rename sslDisableCertficateValidation to sslDisableCertificateValidation
2015-01-05 09:45:35 +09:00
Leza Morais Lutonda (Lemol-C)
bc814b6345 Rename sslDisableCertficateValidation to sslDisableCertificateValidation 2015-01-04 02:09:27 -05:00
Daniel P. Wright
2dc5878f29 Merge pull request #8 from lemol/master
Allow connection with disabled certificate validation
2014-12-09 12:35:11 +09:00
Leza Morais Lutonda (Lemol-C)
4fd67bbf72 Allow connection with disabled certificate validation 2014-12-08 21:14:38 -05:00
Daniel P. Wright
3ded1c8aef Bump version number 2014-10-23 10:24:35 +09:00
Daniel P. Wright
28ec9b955b Allow NoUpperBounds build to fail
Also set fast_finish to true
2014-10-23 10:23:47 +09:00
Daniel P. Wright
8930d7c983 Manually specify Travis build matrix
Build the normal build with GHC versions 7.4, 7.6 and 7.8, and the
NoUpperBounds build with GHC version 7.8 only.
2014-10-23 10:11:49 +09:00
Daniel P. Wright
9a1f4856db Add NoUpperBounds flag for testing latest packages 2014-10-23 10:09:32 +09:00
Daniel P. Wright
9751145745 Update network dependency to include versions < 2.7 2014-10-23 10:01:05 +09:00
Daniel P. Wright
e9fa5a6d6b Bump HaskellNet dependency 2014-10-07 13:41:41 +09:00
Daniel P. Wright
b934525161 Bump the version number 2014-10-07 13:31:57 +09:00
Daniel P. Wright
263bee1392 Add IMAP session logging as an option
Setting the "sslLogToConsole" parameter to True will now spit out the
IMAP session log inline, prefixed with "HaskellNet-SSL".
2014-10-07 13:31:05 +09:00
Daniel P. Wright
3f2fb2c79b Merge pull request #6 from jcristovao/patch-1
Update HaskellNet-SSL.cabal
2014-05-22 11:34:50 +09:00
Daniel P. Wright
ea58def91a Add build status image to the top of README.md 2014-05-22 11:34:05 +09:00
Daniel P. Wright
4aec92321f Add .travis.yml 2014-05-22 11:28:07 +09:00
João Cristóvão
bb458c529d Update HaskellNet-SSL.cabal
Updated network dependencies.
Cheers
2014-05-21 15:54:57 +01:00
Daniel P. Wright
c32368208a Update version number to 0.2.3 2014-02-10 09:35:25 +09:00
Daniel P. Wright
a54d98a166 Merge pull request #4 from vincenthz/master
move to tls 1.2 and connection 0.2
2014-02-10 09:06:16 +09:00
Vincent Hanquez
273decaf96 move to tls 1.2 and connection 0.2 2014-02-10 00:01:40 +00:00
Daniel P. Wright
35190ba4f0 Update version number to 0.2.2 2014-02-10 07:50:45 +09:00
Daniel P. Wright
a9d4549ba7 Remove unnecessary tls-extra dependency 2014-02-10 07:50:23 +09:00
Daniel P. Wright
a69ad12ec4 Change SMTP example to use AUTH LOGIN
Also, output the response on authentication failure rather than just
carrying on regardless.
2014-02-04 08:34:45 +09:00
Daniel P. Wright
31526e9b79 Increase sslMaxLineLength for the IMAP example 2014-01-30 07:49:27 +09:00
Daniel P. Wright
e703d1c36a Add defaultSettings helpers for each protocol 2014-01-30 07:47:47 +09:00
Daniel P. Wright
b26be26666 Bump dependency version numbers 2014-01-30 07:47:24 +09:00
Daniel P. Wright
c99470b2c1 Expose the HaskellNet.SSL module for Settings
Moved the private stuff into HaskellNet.SSL.Internal, so that
HaskellNet.SSL only exports Settings.

Updated minor version number for this quickfix release.
2014-01-18 10:12:27 +09:00
Daniel P. Wright
f0c2d09122 Upgrade version number to 0.2 2014-01-17 15:43:19 +09:00
Daniel P. Wright
594bd9e1f8 Replace *Port connection functions with Settings equivalents
This fixes Issue 1 by allowing the user to set the maximum line length.
It does slightly break the similarity with HaskellNet, which uses the
*Port suffix to specify a port for each connection, but it seems like
the only sensible way to do it, really.  I opted not to keep the *Port
functions in because the proliferation of functions doing basically the
same thing would be too much, I think.
2014-01-17 15:36:16 +09:00
Daniel P. Wright
f910cef262 Create Settings structure to make maxLineLength configurable
This commit simply adds the structure without actually exposing it in
the interface.
2014-01-17 15:24:48 +09:00
Daniel P. Wright
cee0f0dccd Add Haddock documentation headers
Very minimal -- basically copying the header sections from HaskellNet so
that it's easy to see where the function would belong were it part of
HaskellNet itself.
2013-08-29 12:13:23 +09:00
Daniel P. Wright
440140e859 Explicitly set higher tls/tls-extra dependencies
Hackage is reporting a build failure relating to cryptocipher, a library
which is no longer required with newer versions of tls/tls-extra.
Explicitly setting these library dependencies to the version I have
installed locally in order to try and resolve the build failure.
2013-08-29 11:56:13 +09:00
Daniel P. Wright
7f2b1915bb Update version number to 0.1.1.0 2013-08-28 08:16:06 +09:00
Daniel P. Wright
5075cefb62 Remove redundant include from sample code 2013-08-28 08:16:06 +09:00
Daniel P. Wright
ecd9cf1651 Update sample code to use doSMTPSTARTTLS 2013-08-28 08:15:04 +09:00
Daniel P. Wright
a5e240859c Add doSMTP* functions to match HaskellNet
These are quite useful helpers to stop you from forgetting to close the
connection (like I did).
2013-08-28 08:12:18 +09:00
Daniel P. Wright
849619cab8 Change base dependency to match HaskellNet
This should fix the build failure on Hackage.
2013-08-28 07:57:44 +09:00
Daniel P. Wright
b53f096d4a Logout/Close the connections once we're done 2013-08-27 10:07:28 +09:00
13 changed files with 376 additions and 104 deletions

31
.gitignore vendored
View File

@ -1 +1,32 @@
# Linux
*~
.directory
# Vim
[._]*.s[a-w][a-z]
[._]s[a-w][a-z]
*.un~
Session.vim
.netrwhist
*~
tags
# Haskell
dist
cabal-dev
*.o
*.hi
*.chi
*.chs.h
*.dyn_o
*.dyn_hi
.virtualenv
.hpc
.hsenv
.cabal-sandbox/
cabal.sandbox.config
cabal.config
*.prof
*.aux
*.hp
.stack-work/

6
.travis.yml Normal file
View File

@ -0,0 +1,6 @@
language: haskell
matrix:
fast_finish: true
include:
- ghc: 7.10
- ghc: 7.8

16
CHANGELOG.md Normal file
View File

@ -0,0 +1,16 @@
# Revision history for HaskellNet-SSL
## 0.4.0.0 -- 2025-01-07
- drop support for connection in favour of crypton-connection
- compatibility with GHCs up to ghc 9.8 (bump base and bytestring)
- fix example
- add tested-with stanza
## 0.4.0.1 -- 2025-01-17
- Ignore 502 error on helo - fixes communication with some servers
## 0.4.0.1 -- 2025-02-15
- bump data-default and network

View File

@ -1,19 +1,24 @@
name: HaskellNet-SSL
synopsis: Helpers to connect to SSL/TLS mail servers with HaskellNet
version: 0.1.0.0
version: 0.4.0.2
description: This package ties together the HaskellNet and connection
packages to make it easy to open IMAP and SMTP connections
over SSL.
homepage: https://github.com/dpwright/HaskellNet-SSL
tested-with: GHC ==9.4.8 || ==9.6.5 || ==9.8.2
license: BSD3
license-file: LICENSE
author: Daniel P. Wright
maintainer: dani@dpwright.com
maintainer: Leza M. Lutonda <lemol-c@outlook.com>, dani@dpwright.com, contact@mangoiv.com
copyright: (c) 2013 Daniel P. Wright
category: Network
build-type: Simple
cabal-version: >=1.8
data-files: README.md
cabal-version: 1.18
extra-doc-files: README.md, CHANGELOG.md
flag network-bsd
description: Get Network.BSD from the network-bsd package
default: True
source-repository head
type: git
@ -22,13 +27,30 @@ source-repository head
library
hs-source-dirs: src
ghc-options: -Wall
default-language: Haskell2010
exposed-modules: Network.HaskellNet.IMAP.SSL
Network.HaskellNet.POP3.SSL
Network.HaskellNet.SMTP.SSL
other-modules: Network.HaskellNet.SSL
build-depends: base ==4.5.*,
HaskellNet >= 0.3.1,
connection >= 0.1.3,
network >= 2.3,
bytestring,
data-default
Network.HaskellNet.SSL
other-modules: Network.HaskellNet.SSL.Internal
build-depends: base >= 4 && < 5,
HaskellNet >= 0.3 && < 0.7,
crypton-connection >= 0.3.1 && < 0.5,
bytestring >= 0.9 && < 0.13,
data-default >= 0.2 && < 0.9
if flag(network-bsd)
build-depends: network >= 3.0 && < 3.3,
network-bsd >= 2.7 && < 2.9
else
build-depends: network >= 2.4 && < 3.3
executable HaskellNet-SSL-example
hs-source-dirs: examples
main-is: gmail.hs
other-modules:
build-depends: base,
HaskellNet-SSL,
HaskellNet,
bytestring
default-language: Haskell2010

View File

@ -1,11 +1,12 @@
HaskellNet-SSL
--------------
# HaskellNet-SSL
[![haskell ci](https://github.com/dpwright/HaskellNet-SSL/actions/workflows/haskell.yml/badge.svg)](https://github.com/dpwright/HaskellNet-SSL/actions/workflows/haskell.yml)
This package ties together the excellent [HaskellNet][HaskellNet] and
[connection][connection] packages to make it easy to open IMAP and SMTP
[crypton-connection][crypton-connection] packages to make it easy to open IMAP and SMTP
connections over SSL. This is a simple "glue" library; all credit for a)
connecting to IMAP/SMTP servers and b) making an SSL connection goes to the
aforementioned libraries.
[HaskellNet]: https://github.com/jtdaugherty/HaskellNet
[connection]: https://github.com/vincenthz/hs-connection
[crypton-connection]: https://github.com/kazu-yamamoto/crypton-connection

6
cabal.project Normal file
View File

@ -0,0 +1,6 @@
packages: .
allow-newer:
, HaskellNet:base
, HaskellNet:network
, HaskellNet:data-default

View File

@ -1,38 +1,54 @@
{-# LANGUAGE OverloadedStrings #-}
import Network.HaskellNet.IMAP
import Network.HaskellNet.IMAP.SSL
import Network.HaskellNet.IMAP.SSL
import Network.HaskellNet.SMTP.SSL as SMTP
import Network.HaskellNet.SMTP
import Network.HaskellNet.SMTP.SSL
import Network.HaskellNet.Auth (AuthType(LOGIN), Password)
import Network.Mail.Mime
import Network.HaskellNet.Auth (AuthType(PLAIN))
import Network.BSD (getHostName)
import qualified Data.ByteString.Char8 as B
import Data.String
username :: IsString s => s
username = "username@gmail.com"
password :: Password
password = "password"
recipient :: Address
recipient = "someone@somewhere.com"
imapTest :: IO ()
imapTest = do
c <- connectIMAPSSL "imap.gmail.com"
c <- connectIMAPSSLWithSettings "imap.gmail.com" cfg
login c username password
mboxes <- list c
mapM_ print mboxes
select c "INBOX"
msgs <- search c [ALLs]
let firstMsg = head msgs
msgs@(firstMsg : _) <- search c [ALLs]
msgContent <- fetch c firstMsg
B.putStrLn msgContent
logout c
where cfg = defaultSettingsIMAPSSL { sslMaxLineLength = 100000 }
smtpTest = do
c <- connectSMTPSTARTTLS "smtp.gmail.com"
sendCommand c $ AUTH PLAIN username password
sendMail username [recipient] mailContent c
where mailContent = subject `B.append` body
subject = "Subject: Test message\r\n\r\n"
body = "This is a test message"
smtpTest :: IO ()
smtpTest = doSMTPSTARTTLS "smtp.gmail.com" $ \c -> do
authSucceed <- SMTP.authenticate LOGIN username password c
if authSucceed
then do
mail <- simpleMail
recipient
username
subject
body
mempty
mempty
sendMail mail c -- recipient username subject body
else print "Authentication error."
where subject = "Test message"
body = "This is a test message"
main :: IO ()
main = smtpTest >> imapTest >> return ()
main = do
smtpTest
imapTest

View File

@ -1,15 +1,29 @@
-- | IMAP SSL Connections
module Network.HaskellNet.IMAP.SSL
( connectIMAPSSL
, connectIMAPSSLPort
( -- * Establishing connection
connectIMAPSSL
, connectIMAPSSLWithSettings
-- * Settings
, Settings(..)
, defaultSettingsIMAPSSL
-- * Network.HaskellNet.IMAP re-exports
, module Network.HaskellNet.IMAP
) where
import Network.Socket.Internal (PortNumber)
import Network.HaskellNet.IMAP.Connection
import Network.HaskellNet.IMAP
import Network.HaskellNet.SSL
connectIMAPSSL :: String -> IO IMAPConnection
connectIMAPSSL hostname = connectIMAPSSLPort hostname 993
import Network.HaskellNet.SSL.Internal
connectIMAPSSLPort :: String -> PortNumber -> IO IMAPConnection
connectIMAPSSLPort hostname port = connectSSL hostname port >>= connectStream
-- | Create IMAP connection with default settings
connectIMAPSSL :: String -> IO IMAPConnection
connectIMAPSSL hostname = connectIMAPSSLWithSettings hostname defaultSettingsIMAPSSL
-- | Create IMAP connection with given settings
connectIMAPSSLWithSettings :: String -> Settings -> IO IMAPConnection
connectIMAPSSLWithSettings hostname cfg = connectSSL hostname cfg >>= connectStream
-- | Default IMAP SSL settings, port 993
defaultSettingsIMAPSSL :: Settings
defaultSettingsIMAPSSL = defaultSettingsWithPort 993

View File

@ -1,15 +1,25 @@
module Network.HaskellNet.POP3.SSL
( connectPop3SSL
, connectPop3SSLPort
( -- * Establishing connection
connectPop3SSL
, connectPop3SSLWithSettings
-- * Settings
, Settings(..)
, defaultSettingsPop3SSL
-- * Network.HaskellNet.POP3 re-exports
, module Network.HaskellNet.POP3
) where
import Network.Socket.Internal (PortNumber)
import Network.HaskellNet.POP3.Connection
import Network.HaskellNet.POP3
import Network.HaskellNet.SSL
connectPop3SSL :: String -> IO POP3Connection
connectPop3SSL hostname = connectPop3SSLPort hostname 995
import Network.HaskellNet.SSL.Internal
connectPop3SSLPort :: String -> PortNumber -> IO POP3Connection
connectPop3SSLPort hostname port = connectSSL hostname port >>= connectStream
connectPop3SSL :: String -> IO POP3Connection
connectPop3SSL hostname = connectPop3SSLWithSettings hostname defaultSettingsPop3SSL
connectPop3SSLWithSettings :: String -> Settings -> IO POP3Connection
connectPop3SSLWithSettings hostname cfg = connectSSL hostname cfg >>= connectStream
defaultSettingsPop3SSL :: Settings
defaultSettingsPop3SSL = defaultSettingsWithPort 995

View File

@ -1,43 +1,59 @@
module Network.HaskellNet.SMTP.SSL
( connectSMTPSSL
, connectSMTPSSLPort
( -- * Establishing connection
connectSMTPSSL
, connectSMTPSSLWithSettings
, connectSMTPSTARTTLS
, connectSMTPSTARTTLSPort
, connectSMTPSTARTTLSWithSettings
-- * Other Useful Operations
, doSMTPSSL
, doSMTPSSLWithSettings
, doSMTPSTARTTLS
, doSMTPSTARTTLSWithSettings
-- * Settings
, Settings(..)
, defaultSettingsSMTPSSL
, defaultSettingsSMTPSTARTTLS
-- * Network.HaskellNet.SMTP re-exports
, module Network.HaskellNet.SMTP
) where
import Network.Socket.Internal (PortNumber)
import Network.HaskellNet.SMTP
import Network.HaskellNet.SSL
import Network.HaskellNet.SSL.Internal
import Network.HaskellNet.BSStream
import Network.BSD (getHostName)
import qualified Data.ByteString.Char8 as B
import Control.Exception
import Control.Monad
import Data.IORef
connectSMTPSSL :: String -> IO SMTPConnection
connectSMTPSSL hostname = connectSMTPSSLPort hostname 465
connectSMTPSSL hostname = connectSMTPSSLWithSettings hostname defaultSettingsSMTPSSL
connectSMTPSSLPort :: String -> PortNumber -> IO SMTPConnection
connectSMTPSSLPort hostname port = connectSSL hostname port >>= connectStream
connectSMTPSSLWithSettings :: String -> Settings -> IO SMTPConnection
connectSMTPSSLWithSettings hostname cfg = connectSSL hostname cfg >>= connectStream
connectSMTPSTARTTLS :: String -> IO SMTPConnection
connectSMTPSTARTTLS hostname = connectSMTPSTARTTLSPort hostname 587
connectSMTPSTARTTLS hostname = connectSMTPSTARTTLSWithSettings hostname defaultSettingsSMTPSTARTTLS
connectSMTPSTARTTLSPort :: String -> PortNumber -> IO SMTPConnection
connectSMTPSTARTTLSPort hostname port = connectSTARTTLS hostname port >>= connectStream
connectSMTPSTARTTLSWithSettings :: String -> Settings -> IO SMTPConnection
connectSMTPSTARTTLSWithSettings hostname cfg = connectSTARTTLS hostname cfg >>= connectStream
connectSTARTTLS :: String -> PortNumber -> IO BSStream
connectSTARTTLS hostname port = do
(bs, startTLS) <- connectPlain hostname port
connectSTARTTLS :: String -> Settings -> IO BSStream
connectSTARTTLS hostname cfg = do
(bs, startTLS) <- connectPlain hostname cfg
greeting <- bsGetLine bs
failIfNot bs 220 $ parseResponse greeting
failIfNot bs 220 $ parse $ B.unpack greeting
hn <- getHostName
bsPut bs $ B.pack ("HELO " ++ hn ++ "\r\n")
getResponse bs >>= failIfNotEx bs (`elem` [250, 502])
bsPut bs $ B.pack ("EHLO " ++ hn ++ "\r\n")
getResponse bs >>= failIfNot bs 250
bsPut bs $ B.pack "STARTTLS\r\n"
getResponse bs >>= failIfNot bs 220
@ -46,15 +62,22 @@ connectSTARTTLS hostname port = do
prefixRef <- newIORef [greeting]
return $ bs {bsGetLine = prefixedGetLine prefixRef (bsGetLine bs)}
where parseResponse = parse . B.unpack
parse s = (getCode s, s)
where getFinalResponse bs = do
line <- fmap B.unpack $ bsGetLine bs
if (line !! 3) == '-' then getFinalResponse bs else return line
parse s = (getCode s, s)
getCode = read . head . words
getResponse bs = liftM parseResponse $ bsGetLine bs
getResponse bs = liftM parse $ getFinalResponse bs
failIfNot :: BSStream -> Integer -> (Integer, String) -> IO ()
failIfNot bs code (rc, rs) = when (code /= rc) closeAndFail
where closeAndFail = bsClose bs >> fail ("cannot connect to server: " ++ rs)
-- | Extended version of fail if, can support multiple statuses
failIfNotEx :: BSStream -> (Integer -> Bool) -> (Integer, String) -> IO ()
failIfNotEx bs f (rc, rs) = unless (f rc) closeAndFail
where closeAndFail = bsClose bs >> fail ("cannot connect to server: " ++ rs)
-- This is a bit of a nasty hack. Network.HaskellNet.SMTP.connectStream
-- expects to receive a status 220 from the server as soon as it connects,
-- but we've intercepted it in order to establish a STARTTLS connection.
@ -64,3 +87,24 @@ prefixedGetLine :: IORef [B.ByteString] -> IO B.ByteString -> IO B.ByteString
prefixedGetLine prefix rawGetLine = readIORef prefix >>= deliverLine
where deliverLine [] = rawGetLine
deliverLine (l:ls) = writeIORef prefix ls >> return l
bracketSMTP :: IO SMTPConnection -> (SMTPConnection -> IO a) -> IO a
bracketSMTP = flip bracket closeSMTP
doSMTPSSL :: String -> (SMTPConnection -> IO a) -> IO a
doSMTPSSL host = bracketSMTP $ connectSMTPSSL host
doSMTPSSLWithSettings :: String -> Settings -> (SMTPConnection -> IO a) -> IO a
doSMTPSSLWithSettings host port = bracketSMTP $ connectSMTPSSLWithSettings host port
doSMTPSTARTTLS :: String -> (SMTPConnection -> IO a) -> IO a
doSMTPSTARTTLS host = bracketSMTP $ connectSMTPSTARTTLS host
doSMTPSTARTTLSWithSettings :: String -> Settings -> (SMTPConnection -> IO a) -> IO a
doSMTPSTARTTLSWithSettings host port = bracketSMTP $ connectSMTPSTARTTLSWithSettings host port
defaultSettingsSMTPSSL :: Settings
defaultSettingsSMTPSSL = defaultSettingsWithPort 465
defaultSettingsSMTPSTARTTLS :: Settings
defaultSettingsSMTPSTARTTLS = defaultSettingsWithPort 587

View File

@ -1,44 +1,28 @@
module Network.HaskellNet.SSL ( connectSSL
, connectPlain
) where
{-# LANGUAGE CPP #-}
module Network.HaskellNet.SSL
( Settings (..)
, defaultSettingsWithPort
) where
import Network.Connection
import Network.HaskellNet.BSStream
#if MIN_VERSION_network(3,0,0)
import Network.Socket (PortNumber)
#else
import Network.Socket.Internal (PortNumber)
#endif
import qualified Data.ByteString.Char8 as B
import Data.Default
-- | Settings for configuring HaskellNet connections
data Settings = Settings
{ sslPort :: PortNumber -- ^ Port number to connect to
, sslMaxLineLength :: Int -- ^ Max line lengths
, sslLogToConsole :: Bool -- ^ Log info to console
, sslDisableCertificateValidation :: Bool -- ^ Disable certificate validation
} deriving(Eq, Ord, Show)
type STARTTLS = IO ()
maxLineLength :: Int
maxLineLength = 10000
connectionGetBytes :: Connection -> Int -> IO B.ByteString
connectionGetBytes = loop B.empty where
loop buf _ 0 = return buf
loop buf c l = connectionGet c l >>= nextIteration
where nextIteration b = loop (buf `B.append` b) c $ l - B.length b
connectionToStream :: Connection -> BSStream
connectionToStream c = BSStream
{ bsGet = connectionGetBytes c
, bsPut = connectionPut c
, bsFlush = return ()
, bsClose = connectionClose c
, bsIsOpen = return True
, bsGetLine = connectionGetLine maxLineLength c
}
connectSSL :: String -> PortNumber -> IO BSStream
connectSSL hostname port = do
c <- initConnectionContext >>= flip connectTo params
return $ connectionToStream c
where params = ConnectionParams hostname port (Just def) Nothing
connectPlain :: String -> PortNumber -> IO (BSStream, STARTTLS)
connectPlain hostname port = do
ctx <- initConnectionContext
c <- connectTo ctx params
return (connectionToStream c, connectionSetSecure ctx c def)
where params = ConnectionParams hostname port Nothing Nothing
-- | Construct default settings for a port
defaultSettingsWithPort :: PortNumber -> Settings
defaultSettingsWithPort p = Settings
{ sslPort = p
, sslMaxLineLength = 10000
, sslLogToConsole = False
, sslDisableCertificateValidation = False
}

View File

@ -0,0 +1,56 @@
module Network.HaskellNet.SSL.Internal
( connectSSL
, connectPlain
) where
import Network.Connection
import Network.HaskellNet.SSL
import Network.HaskellNet.BSStream
import qualified Data.ByteString.Char8 as B
import Data.Default
import Control.Monad ((>=>))
type STARTTLS = IO ()
connectionGetBytes :: Connection -> Int -> IO B.ByteString
connectionGetBytes = loop B.empty where
loop buf _ 0 = return buf
loop buf c l = connectionGet c l >>= nextIteration
where nextIteration b = loop (buf `B.append` b) c $ l - B.length b
connectionToStream :: Connection -> Settings -> BSStream
connectionToStream c cfg = BSStream
{ bsGet = connectionGetBytes c >=> withLog "RECV"
, bsPut = withLog "SEND" >=> connectionPut c
, bsFlush = return ()
, bsClose = connectionClose c
, bsIsOpen = return True
, bsGetLine = connectionGetLine maxl c >>= withLog "RECV"
, bsWaitForInput = connectionWaitForInput c
} where maxl = sslMaxLineLength cfg
withLog = if sslLogToConsole cfg then logToConsole
else flip (const . return)
logToConsole :: String -> B.ByteString -> IO B.ByteString
logToConsole dir s = do
putStrLn $ "HaskellNet-SSL " ++ dir ++ ": " ++ show s
return s
connectSSL :: String -> Settings -> IO BSStream
connectSSL hostname cfg = do
c <- initConnectionContext >>= flip connectTo params
return $ connectionToStream c cfg
where params = ConnectionParams hostname port (Just tlsCfg) Nothing
port = sslPort cfg
tlsCfg = def { settingDisableCertificateValidation = sslDisableCertificateValidation cfg }
connectPlain :: String -> Settings -> IO (BSStream, STARTTLS)
connectPlain hostname cfg = do
ctx <- initConnectionContext
c <- connectTo ctx params
return (connectionToStream c cfg, connectionSetSecure ctx c tlsCfg)
where params = ConnectionParams hostname port Nothing Nothing
port = sslPort cfg
tlsCfg = def { settingDisableCertificateValidation = sslDisableCertificateValidation cfg }

66
stack.yaml Normal file
View File

@ -0,0 +1,66 @@
# This file was automatically generated by 'stack init'
#
# Some commonly used options have been documented as comments in this file.
# For advanced use and comprehensive documentation of the format, please see:
# http://docs.haskellstack.org/en/stable/yaml_configuration/
# Resolver to choose a 'specific' stackage snapshot or a compiler version.
# A snapshot resolver dictates the compiler version and the set of packages
# to be used for project dependencies. For example:
#
# resolver: lts-3.5
# resolver: nightly-2015-09-21
# resolver: ghc-7.10.2
# resolver: ghcjs-0.1.0_ghc-7.10.2
# resolver:
# name: custom-snapshot
# location: "./custom-snapshot.yaml"
resolver: lts-7.19
# User packages to be built.
# Various formats can be used as shown in the example below.
#
# packages:
# - some-directory
# - https://example.com/foo/bar/baz-0.0.2.tar.gz
# - location:
# git: https://github.com/commercialhaskell/stack.git
# commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a
# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a
# extra-dep: true
# subdirs:
# - auto-update
# - wai
#
# A package marked 'extra-dep: true' will only be built if demanded by a
# non-dependency (i.e. a user package), and its test suites and benchmarks
# will not be run. This is useful for tweaking upstream packages.
packages:
- '.'
# Dependency packages to be pulled from upstream that are not in the resolver
# (e.g., acme-missiles-0.3)
extra-deps: []
# Override default flag values for local packages and extra-deps
flags: {}
# Extra package databases containing global packages
extra-package-dbs: []
# Control whether we use the GHC we find on the path
# system-ghc: true
#
# Require a specific version of stack, using version ranges
# require-stack-version: -any # Default
# require-stack-version: ">=1.1"
#
# Override the architecture used by stack, especially useful on Windows
# arch: i386
# arch: x86_64
#
# Extra directories used by stack for building
# extra-include-dirs: [/path/to/dir]
# extra-lib-dirs: [/path/to/dir]
#
# Allow a newer minor version of GHC than the snapshot specifies
# compiler-check: newer-minor