{-# LANGUAGE OverloadedStrings, RecordWildCards, ScopedTypeVariables #-}
module Network.Mail.SMTP
(
sendMail
, sendMail'
, sendMailWithLogin
, sendMailWithLogin'
, sendMailWithSender
, sendMailWithSender'
, sendMailTLS
, sendMailTLS'
, sendMailWithLoginTLS
, sendMailWithLoginTLS'
, sendMailWithSenderTLS
, sendMailWithSenderTLS'
, sendMailSTARTTLS
, sendMailSTARTTLS'
, sendMailWithLoginSTARTTLS
, sendMailWithLoginSTARTTLS'
, sendMailWithSenderSTARTTLS
, sendMailWithSenderSTARTTLS'
, simpleMail
, plainTextPart
, htmlPart
, filePart
, module Network.Mail.SMTP.Types
, SMTPConnection
, sendmail
, sendmailCustom
, renderSendMail
, renderSendMailCustom
, connectSMTP
, connectSMTPS
, connectSMTPSTARTTLS
, connectSMTP'
, connectSMTPS'
, connectSMTPSTARTTLS'
, connectSMTPWithHostName
, connectSMTPWithHostNameAndTlsSettings
, connectSMTPWithHostNameAndTlsSettingsSTARTTLS
, sendCommand
, login
, closeSMTP
, renderAndSend
, renderAndSendFrom
)
where
import Network.Mail.SMTP.Auth
import Network.Mail.SMTP.Types
import System.FilePath (takeFileName)
import Control.Monad (unless)
import Data.Char (isDigit)
import Network.Socket
import Network.BSD (getHostName)
import Network.Mail.Mime hiding (filePart, htmlPart, simpleMail)
import qualified Network.Connection as Conn
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import qualified Data.ByteString.Char8 as B8
import qualified Data.ByteString.Lazy as BL
import qualified Data.Text as T
import qualified Data.Text.Lazy as TL
import qualified Data.Text.Lazy.Encoding as TL
import Data.Text.Encoding
data SMTPConnection = SMTPC !Conn.Connection ![ByteString]
instance Eq SMTPConnection where
== :: SMTPConnection -> SMTPConnection -> Bool
(==) (SMTPC a :: Connection
a _) (SMTPC b :: Connection
b _) = Connection -> ConnectionID
Conn.connectionID Connection
a ConnectionID -> ConnectionID -> Bool
forall a. Eq a => a -> a -> Bool
== Connection -> ConnectionID
Conn.connectionID Connection
b
connectSMTP :: HostName
-> IO SMTPConnection
connectSMTP :: HostName -> IO SMTPConnection
connectSMTP hostname :: HostName
hostname = HostName -> PortNumber -> IO SMTPConnection
connectSMTP' HostName
hostname 25
connectSMTPSTARTTLS :: HostName
-> IO SMTPConnection
connectSMTPSTARTTLS :: HostName -> IO SMTPConnection
connectSMTPSTARTTLS hostname :: HostName
hostname = HostName -> PortNumber -> IO SMTPConnection
connectSMTPSTARTTLS' HostName
hostname 587
defaultTlsSettings :: Conn.TLSSettings
defaultTlsSettings :: TLSSettings
defaultTlsSettings = Bool -> Bool -> Bool -> TLSSettings
Conn.TLSSettingsSimple Bool
False Bool
False Bool
False
connectSMTPS :: HostName
-> IO SMTPConnection
connectSMTPS :: HostName -> IO SMTPConnection
connectSMTPS hostname :: HostName
hostname =
HostName -> PortNumber -> IO SMTPConnection
connectSMTPS' HostName
hostname 465
connectSMTP' :: HostName
-> PortNumber
-> IO SMTPConnection
connectSMTP' :: HostName -> PortNumber -> IO SMTPConnection
connectSMTP' hostname :: HostName
hostname port :: PortNumber
port = HostName -> PortNumber -> IO HostName -> IO SMTPConnection
connectSMTPWithHostName HostName
hostname PortNumber
port IO HostName
getHostName
connectSMTPS' :: HostName
-> PortNumber
-> IO SMTPConnection
connectSMTPS' :: HostName -> PortNumber -> IO SMTPConnection
connectSMTPS' hostname :: HostName
hostname port :: PortNumber
port = HostName
-> PortNumber
-> IO HostName
-> Maybe TLSSettings
-> IO SMTPConnection
connectSMTPWithHostNameAndTlsSettings HostName
hostname PortNumber
port IO HostName
getHostName (TLSSettings -> Maybe TLSSettings
forall a. a -> Maybe a
Just TLSSettings
defaultTlsSettings)
connectSMTPSTARTTLS' :: HostName
-> PortNumber
-> IO SMTPConnection
connectSMTPSTARTTLS' :: HostName -> PortNumber -> IO SMTPConnection
connectSMTPSTARTTLS' hostname :: HostName
hostname port :: PortNumber
port = HostName
-> PortNumber -> IO HostName -> TLSSettings -> IO SMTPConnection
connectSMTPWithHostNameAndTlsSettingsSTARTTLS HostName
hostname PortNumber
port IO HostName
getHostName TLSSettings
defaultTlsSettings
connectSMTPWithHostName :: HostName
-> PortNumber
-> IO String
-> IO SMTPConnection
connectSMTPWithHostName :: HostName -> PortNumber -> IO HostName -> IO SMTPConnection
connectSMTPWithHostName hostname :: HostName
hostname port :: PortNumber
port getMailHostName :: IO HostName
getMailHostName =
HostName
-> PortNumber
-> IO HostName
-> Maybe TLSSettings
-> IO SMTPConnection
connectSMTPWithHostNameAndTlsSettings HostName
hostname PortNumber
port IO HostName
getMailHostName Maybe TLSSettings
forall a. Maybe a
Nothing
connectSMTPWithHostNameAndTlsSettings :: HostName
-> PortNumber
-> IO String
-> Maybe Conn.TLSSettings
-> IO SMTPConnection
connectSMTPWithHostNameAndTlsSettings :: HostName
-> PortNumber
-> IO HostName
-> Maybe TLSSettings
-> IO SMTPConnection
connectSMTPWithHostNameAndTlsSettings hostname :: HostName
hostname port :: PortNumber
port getMailHostName :: IO HostName
getMailHostName tlsSettings :: Maybe TLSSettings
tlsSettings = do
ConnectionContext
context <- IO ConnectionContext
Conn.initConnectionContext
ConnectionContext -> ConnectionParams -> IO Connection
Conn.connectTo ConnectionContext
context ConnectionParams
connParams IO Connection
-> (Connection -> IO SMTPConnection) -> IO SMTPConnection
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= IO HostName -> Connection -> IO SMTPConnection
connectStream IO HostName
getMailHostName
where
connParams :: ConnectionParams
connParams = HostName
-> PortNumber
-> Maybe TLSSettings
-> Maybe ProxySettings
-> ConnectionParams
Conn.ConnectionParams HostName
hostname PortNumber
port Maybe TLSSettings
tlsSettings Maybe ProxySettings
forall a. Maybe a
Nothing
connectSMTPWithHostNameAndTlsSettingsSTARTTLS :: HostName
-> PortNumber
-> IO String
-> Conn.TLSSettings
-> IO SMTPConnection
connectSMTPWithHostNameAndTlsSettingsSTARTTLS :: HostName
-> PortNumber -> IO HostName -> TLSSettings -> IO SMTPConnection
connectSMTPWithHostNameAndTlsSettingsSTARTTLS hostname :: HostName
hostname port :: PortNumber
port getMailHostName :: IO HostName
getMailHostName tlsSettings :: TLSSettings
tlsSettings = do
ConnectionContext
context <- IO ConnectionContext
Conn.initConnectionContext
ConnectionContext -> ConnectionParams -> IO Connection
Conn.connectTo ConnectionContext
context ConnectionParams
connParams IO Connection
-> (Connection -> IO SMTPConnection) -> IO SMTPConnection
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= IO HostName
-> ConnectionContext
-> TLSSettings
-> Connection
-> IO SMTPConnection
connectStreamSTARTTLS IO HostName
getMailHostName ConnectionContext
context TLSSettings
tlsSettings
where
connParams :: ConnectionParams
connParams = HostName
-> PortNumber
-> Maybe TLSSettings
-> Maybe ProxySettings
-> ConnectionParams
Conn.ConnectionParams HostName
hostname PortNumber
port Maybe TLSSettings
forall a. Maybe a
Nothing Maybe ProxySettings
forall a. Maybe a
Nothing
tryOnce :: SMTPConnection -> Command -> ReplyCode -> IO ByteString
tryOnce :: SMTPConnection -> Command -> ReplyCode -> IO ByteString
tryOnce = ReplyCode
-> SMTPConnection -> Command -> ReplyCode -> IO ByteString
tryCommand 1
tryCommand :: Int -> SMTPConnection -> Command -> ReplyCode
-> IO ByteString
tryCommand :: ReplyCode
-> SMTPConnection -> Command -> ReplyCode -> IO ByteString
tryCommand tries :: ReplyCode
tries st :: SMTPConnection
st cmd :: Command
cmd expectedReply :: ReplyCode
expectedReply = do
(code :: ReplyCode
code, msg :: ByteString
msg) <- ReplyCode
-> SMTPConnection
-> Command
-> ReplyCode
-> IO (ReplyCode, ByteString)
tryCommandNoFail ReplyCode
tries SMTPConnection
st Command
cmd ReplyCode
expectedReply
if ReplyCode
code ReplyCode -> ReplyCode -> Bool
forall a. Eq a => a -> a -> Bool
== ReplyCode
expectedReply
then ByteString -> IO ByteString
forall (m :: * -> *) a. Monad m => a -> m a
return ByteString
msg
else do
SMTPConnection -> IO ()
closeSMTP SMTPConnection
st
HostName -> IO ByteString
forall (m :: * -> *) a. MonadFail m => HostName -> m a
fail (HostName -> IO ByteString) -> HostName -> IO ByteString
forall a b. (a -> b) -> a -> b
$ "Unexpected reply to: " HostName -> HostName -> HostName
forall a. [a] -> [a] -> [a]
++ Command -> HostName
forall a. Show a => a -> HostName
show Command
cmd HostName -> HostName -> HostName
forall a. [a] -> [a] -> [a]
++
", Expected reply code: " HostName -> HostName -> HostName
forall a. [a] -> [a] -> [a]
++ ReplyCode -> HostName
forall a. Show a => a -> HostName
show ReplyCode
expectedReply HostName -> HostName -> HostName
forall a. [a] -> [a] -> [a]
++
", Got this instead: " HostName -> HostName -> HostName
forall a. [a] -> [a] -> [a]
++ ReplyCode -> HostName
forall a. Show a => a -> HostName
show ReplyCode
code HostName -> HostName -> HostName
forall a. [a] -> [a] -> [a]
++ " " HostName -> HostName -> HostName
forall a. [a] -> [a] -> [a]
++ ByteString -> HostName
forall a. Show a => a -> HostName
show ByteString
msg
tryCommandNoFail :: Int -> SMTPConnection -> Command -> ReplyCode
-> IO (ReplyCode, ByteString)
tryCommandNoFail :: ReplyCode
-> SMTPConnection
-> Command
-> ReplyCode
-> IO (ReplyCode, ByteString)
tryCommandNoFail tries :: ReplyCode
tries st :: SMTPConnection
st cmd :: Command
cmd expectedReply :: ReplyCode
expectedReply = do
(code :: ReplyCode
code, msg :: ByteString
msg) <- SMTPConnection -> Command -> IO (ReplyCode, ByteString)
sendCommand SMTPConnection
st Command
cmd
if ReplyCode
code ReplyCode -> ReplyCode -> Bool
forall a. Eq a => a -> a -> Bool
== ReplyCode
expectedReply
then (ReplyCode, ByteString) -> IO (ReplyCode, ByteString)
forall (m :: * -> *) a. Monad m => a -> m a
return (ReplyCode
code, ByteString
msg)
else if ReplyCode
tries ReplyCode -> ReplyCode -> Bool
forall a. Ord a => a -> a -> Bool
> 1
then ReplyCode
-> SMTPConnection
-> Command
-> ReplyCode
-> IO (ReplyCode, ByteString)
tryCommandNoFail (ReplyCode
tries ReplyCode -> ReplyCode -> ReplyCode
forall a. Num a => a -> a -> a
- 1) SMTPConnection
st Command
cmd ReplyCode
expectedReply
else (ReplyCode, ByteString) -> IO (ReplyCode, ByteString)
forall (m :: * -> *) a. Monad m => a -> m a
return (ReplyCode
code, ByteString
msg)
connectStream :: IO String -> Conn.Connection -> IO SMTPConnection
connectStream :: IO HostName -> Connection -> IO SMTPConnection
connectStream getMailHostName :: IO HostName
getMailHostName st :: Connection
st = do
(code1 :: ReplyCode
code1, _) <- Connection -> IO (ReplyCode, ByteString)
parseResponse Connection
st
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ReplyCode
code1 ReplyCode -> ReplyCode -> Bool
forall a. Eq a => a -> a -> Bool
== 220) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Connection -> IO ()
Conn.connectionClose Connection
st
HostName -> IO ()
forall (m :: * -> *) a. MonadFail m => HostName -> m a
fail "cannot connect to the server"
HostName
senderHost <- IO HostName
getMailHostName
(code :: ReplyCode
code, initialMsg :: ByteString
initialMsg) <- ReplyCode
-> SMTPConnection
-> Command
-> ReplyCode
-> IO (ReplyCode, ByteString)
tryCommandNoFail 3 (Connection -> [ByteString] -> SMTPConnection
SMTPC Connection
st []) (ByteString -> Command
EHLO (ByteString -> Command) -> ByteString -> Command
forall a b. (a -> b) -> a -> b
$ HostName -> ByteString
B8.pack HostName
senderHost) 250
if ReplyCode
code ReplyCode -> ReplyCode -> Bool
forall a. Eq a => a -> a -> Bool
== 250
then SMTPConnection -> IO SMTPConnection
forall (m :: * -> *) a. Monad m => a -> m a
return (Connection -> [ByteString] -> SMTPConnection
SMTPC Connection
st ([ByteString] -> [ByteString]
forall a. [a] -> [a]
tail ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
forall a b. (a -> b) -> a -> b
$ ByteString -> [ByteString]
B8.lines ByteString
initialMsg))
else do
ByteString
msg <- ReplyCode
-> SMTPConnection -> Command -> ReplyCode -> IO ByteString
tryCommand 3 (Connection -> [ByteString] -> SMTPConnection
SMTPC Connection
st []) (ByteString -> Command
HELO (ByteString -> Command) -> ByteString -> Command
forall a b. (a -> b) -> a -> b
$ HostName -> ByteString
B8.pack HostName
senderHost) 250
SMTPConnection -> IO SMTPConnection
forall (m :: * -> *) a. Monad m => a -> m a
return (Connection -> [ByteString] -> SMTPConnection
SMTPC Connection
st ([ByteString] -> [ByteString]
forall a. [a] -> [a]
tail ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
forall a b. (a -> b) -> a -> b
$ ByteString -> [ByteString]
B8.lines ByteString
msg))
connectStreamSTARTTLS :: IO String -> Conn.ConnectionContext -> Conn.TLSSettings -> Conn.Connection -> IO SMTPConnection
connectStreamSTARTTLS :: IO HostName
-> ConnectionContext
-> TLSSettings
-> Connection
-> IO SMTPConnection
connectStreamSTARTTLS getMailHostName :: IO HostName
getMailHostName context :: ConnectionContext
context tlsSettings :: TLSSettings
tlsSettings st :: Connection
st = do
(code1 :: ReplyCode
code1, _) <- Connection -> IO (ReplyCode, ByteString)
parseResponse Connection
st
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ReplyCode
code1 ReplyCode -> ReplyCode -> Bool
forall a. Eq a => a -> a -> Bool
== 220) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Connection -> IO ()
Conn.connectionClose Connection
st
HostName -> IO ()
forall (m :: * -> *) a. MonadFail m => HostName -> m a
fail "cannot connect to the server"
HostName
senderHost <- IO HostName
getMailHostName
ByteString
_ <- ReplyCode
-> SMTPConnection -> Command -> ReplyCode -> IO ByteString
tryCommand 3 (Connection -> [ByteString] -> SMTPConnection
SMTPC Connection
st []) (ByteString -> Command
EHLO (ByteString -> Command) -> ByteString -> Command
forall a b. (a -> b) -> a -> b
$ HostName -> ByteString
B8.pack HostName
senderHost) 250
ByteString
_ <- ReplyCode
-> SMTPConnection -> Command -> ReplyCode -> IO ByteString
tryCommand 1 (Connection -> [ByteString] -> SMTPConnection
SMTPC Connection
st []) Command
STARTTLS 220
()
_ <- ConnectionContext -> Connection -> TLSSettings -> IO ()
Conn.connectionSetSecure ConnectionContext
context Connection
st TLSSettings
tlsSettings
ByteString
msg <- ReplyCode
-> SMTPConnection -> Command -> ReplyCode -> IO ByteString
tryCommand 1 (Connection -> [ByteString] -> SMTPConnection
SMTPC Connection
st []) (ByteString -> Command
EHLO (ByteString -> Command) -> ByteString -> Command
forall a b. (a -> b) -> a -> b
$ HostName -> ByteString
B8.pack HostName
senderHost) 250
SMTPConnection -> IO SMTPConnection
forall (m :: * -> *) a. Monad m => a -> m a
return (Connection -> [ByteString] -> SMTPConnection
SMTPC Connection
st ([ByteString] -> [ByteString]
forall a. [a] -> [a]
tail ([ByteString] -> [ByteString]) -> [ByteString] -> [ByteString]
forall a b. (a -> b) -> a -> b
$ ByteString -> [ByteString]
B8.lines ByteString
msg))
parseResponse :: Conn.Connection -> IO (ReplyCode, ByteString)
parseResponse :: Connection -> IO (ReplyCode, ByteString)
parseResponse conn :: Connection
conn = do
(code :: ByteString
code, bdy :: [ByteString]
bdy) <- IO (ByteString, [ByteString])
readLines
(ReplyCode, ByteString) -> IO (ReplyCode, ByteString)
forall (m :: * -> *) a. Monad m => a -> m a
return (HostName -> ReplyCode
forall a. Read a => HostName -> a
read (HostName -> ReplyCode) -> HostName -> ReplyCode
forall a b. (a -> b) -> a -> b
$ ByteString -> HostName
B8.unpack ByteString
code, [ByteString] -> ByteString
B8.unlines [ByteString]
bdy)
where
readLines :: IO (ByteString, [ByteString])
readLines = do
ByteString
l <- ReplyCode -> Connection -> IO ByteString
Conn.connectionGetLine 1000 Connection
conn
let (c :: ByteString
c, bdy :: ByteString
bdy) = (Char -> Bool) -> ByteString -> (ByteString, ByteString)
B8.span Char -> Bool
isDigit ByteString
l
if Bool -> Bool
not (ByteString -> Bool
B8.null ByteString
bdy) Bool -> Bool -> Bool
&& ByteString -> Char
B8.head ByteString
bdy Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== '-'
then do (c2 :: ByteString
c2, ls :: [ByteString]
ls) <- IO (ByteString, [ByteString])
readLines
(ByteString, [ByteString]) -> IO (ByteString, [ByteString])
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString
c2, ByteString -> ByteString
B8.tail ByteString
bdyByteString -> [ByteString] -> [ByteString]
forall a. a -> [a] -> [a]
:[ByteString]
ls)
else (ByteString, [ByteString]) -> IO (ByteString, [ByteString])
forall (m :: * -> *) a. Monad m => a -> m a
return (ByteString
c, [ByteString -> ByteString
B8.tail ByteString
bdy])
sendCommand :: SMTPConnection -> Command -> IO (ReplyCode, ByteString)
sendCommand :: SMTPConnection -> Command -> IO (ReplyCode, ByteString)
sendCommand (SMTPC conn :: Connection
conn _) (DATA dat :: ByteString
dat) = do
Connection -> ByteString -> IO ()
bsPutCrLf Connection
conn "DATA"
(code :: ReplyCode
code, _) <- Connection -> IO (ReplyCode, ByteString)
parseResponse Connection
conn
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ReplyCode
code ReplyCode -> ReplyCode -> Bool
forall a. Eq a => a -> a -> Bool
== 354) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ HostName -> IO ()
forall (m :: * -> *) a. MonadFail m => HostName -> m a
fail "this server cannot accept any data."
(ByteString -> IO ()) -> [ByteString] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ ByteString -> IO ()
sendLine ([ByteString] -> IO ()) -> [ByteString] -> IO ()
forall a b. (a -> b) -> a -> b
$ ByteString -> [ByteString]
split ByteString
dat
ByteString -> IO ()
sendLine ByteString
dot
Connection -> IO (ReplyCode, ByteString)
parseResponse Connection
conn
where
sendLine :: ByteString -> IO ()
sendLine = Connection -> ByteString -> IO ()
bsPutCrLf Connection
conn
split :: ByteString -> [ByteString]
split = (ByteString -> ByteString) -> [ByteString] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map (ByteString -> ByteString
padDot (ByteString -> ByteString)
-> (ByteString -> ByteString) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> ByteString
stripCR) ([ByteString] -> [ByteString])
-> (ByteString -> [ByteString]) -> ByteString -> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
B8.lines
stripCR :: ByteString -> ByteString
stripCR s :: ByteString
s = if ByteString
cr ByteString -> ByteString -> Bool
`B8.isSuffixOf` ByteString
s then ByteString -> ByteString
B8.init ByteString
s else ByteString
s
padDot :: ByteString -> ByteString
padDot s :: ByteString
s = if ByteString
dot ByteString -> ByteString -> Bool
`B8.isPrefixOf` ByteString
s then ByteString
dot ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
s else ByteString
s
cr :: ByteString
cr = HostName -> ByteString
B8.pack "\r"
dot :: ByteString
dot = HostName -> ByteString
B8.pack "."
sendCommand (SMTPC conn :: Connection
conn _) (AUTH LOGIN username :: HostName
username password :: HostName
password) = do
Connection -> ByteString -> IO ()
bsPutCrLf Connection
conn ByteString
command
(ReplyCode, ByteString)
_ <- Connection -> IO (ReplyCode, ByteString)
parseResponse Connection
conn
Connection -> ByteString -> IO ()
bsPutCrLf Connection
conn ByteString
userB64
(ReplyCode, ByteString)
_ <- Connection -> IO (ReplyCode, ByteString)
parseResponse Connection
conn
Connection -> ByteString -> IO ()
bsPutCrLf Connection
conn ByteString
passB64
(code :: ReplyCode
code, msg :: ByteString
msg) <- Connection -> IO (ReplyCode, ByteString)
parseResponse Connection
conn
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ReplyCode
code ReplyCode -> ReplyCode -> Bool
forall a. Eq a => a -> a -> Bool
== 235) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ HostName -> IO ()
forall (m :: * -> *) a. MonadFail m => HostName -> m a
fail "authentication failed."
(ReplyCode, ByteString) -> IO (ReplyCode, ByteString)
forall (m :: * -> *) a. Monad m => a -> m a
return (ReplyCode
code, ByteString
msg)
where
command :: ByteString
command = "AUTH LOGIN"
(userB64 :: ByteString
userB64, passB64 :: ByteString
passB64) = HostName -> HostName -> (ByteString, ByteString)
encodeLogin HostName
username HostName
password
sendCommand (SMTPC conn :: Connection
conn _) (AUTH at :: AuthType
at username :: HostName
username password :: HostName
password) = do
Connection -> ByteString -> IO ()
bsPutCrLf Connection
conn ByteString
command
(code :: ReplyCode
code, msg :: ByteString
msg) <- Connection -> IO (ReplyCode, ByteString)
parseResponse Connection
conn
Bool -> IO () -> IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
unless (ReplyCode
code ReplyCode -> ReplyCode -> Bool
forall a. Eq a => a -> a -> Bool
== 334) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ HostName -> IO ()
forall (m :: * -> *) a. MonadFail m => HostName -> m a
fail "authentication failed."
Connection -> ByteString -> IO ()
bsPutCrLf Connection
conn (ByteString -> IO ()) -> ByteString -> IO ()
forall a b. (a -> b) -> a -> b
$ AuthType -> HostName -> HostName -> HostName -> ByteString
auth AuthType
at (ByteString -> HostName
B8.unpack ByteString
msg) HostName
username HostName
password
Connection -> IO (ReplyCode, ByteString)
parseResponse Connection
conn
where
command :: ByteString
command = HostName -> ByteString
B8.pack (HostName -> ByteString) -> HostName -> ByteString
forall a b. (a -> b) -> a -> b
$ [HostName] -> HostName
unwords ["AUTH", AuthType -> HostName
forall a. Show a => a -> HostName
show AuthType
at]
sendCommand (SMTPC conn :: Connection
conn _) meth :: Command
meth = do
Connection -> ByteString -> IO ()
bsPutCrLf Connection
conn ByteString
command
Connection -> IO (ReplyCode, ByteString)
parseResponse Connection
conn
where
command :: ByteString
command = case Command
meth of
(HELO param :: ByteString
param) -> "HELO " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
param
(EHLO param :: ByteString
param) -> "EHLO " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
param
(MAIL param :: ByteString
param) -> "MAIL FROM:<" ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
param ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ">"
(RCPT param :: ByteString
param) -> "RCPT TO:<" ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
param ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ">"
(EXPN param :: ByteString
param) -> "EXPN " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
param
(VRFY param :: ByteString
param) -> "VRFY " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
param
(HELP msg :: ByteString
msg) -> if ByteString -> Bool
B8.null ByteString
msg
then "HELP\r\n"
else "HELP " ByteString -> ByteString -> ByteString
forall a. Semigroup a => a -> a -> a
<> ByteString
msg
NOOP -> "NOOP"
RSET -> "RSET"
QUIT -> "QUIT"
STARTTLS -> "STARTTLS"
DATA{} ->
HostName -> ByteString
forall a. HasCallStack => HostName -> a
error "BUG: DATA pattern should be matched by sendCommand patterns"
AUTH{} ->
HostName -> ByteString
forall a. HasCallStack => HostName -> a
error "BUG: AUTH pattern should be matched by sendCommand patterns"
closeSMTP :: SMTPConnection -> IO ()
closeSMTP :: SMTPConnection -> IO ()
closeSMTP c :: SMTPConnection
c@(SMTPC conn :: Connection
conn _) = SMTPConnection -> Command -> IO (ReplyCode, ByteString)
sendCommand SMTPConnection
c Command
QUIT IO (ReplyCode, ByteString) -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Connection -> IO ()
Conn.connectionClose Connection
conn
sendRenderedMail :: ByteString
-> [ByteString]
-> ByteString
-> SMTPConnection
-> IO ()
sendRenderedMail :: ByteString -> [ByteString] -> ByteString -> SMTPConnection -> IO ()
sendRenderedMail sender :: ByteString
sender receivers :: [ByteString]
receivers dat :: ByteString
dat conn :: SMTPConnection
conn = do
ByteString
_ <- SMTPConnection -> Command -> ReplyCode -> IO ByteString
tryOnce SMTPConnection
conn (ByteString -> Command
MAIL ByteString
sender) 250
(ByteString -> IO ByteString) -> [ByteString] -> IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\r :: ByteString
r -> SMTPConnection -> Command -> ReplyCode -> IO ByteString
tryOnce SMTPConnection
conn (ByteString -> Command
RCPT ByteString
r) 250) [ByteString]
receivers
ByteString
_ <- SMTPConnection -> Command -> ReplyCode -> IO ByteString
tryOnce SMTPConnection
conn (ByteString -> Command
DATA ByteString
dat) 250
() -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
renderAndSend ::SMTPConnection -> Mail -> IO ()
renderAndSend :: SMTPConnection -> Mail -> IO ()
renderAndSend conn :: SMTPConnection
conn mail :: Mail
mail@Mail{..} = do
ByteString
rendered <- ByteString -> ByteString
lazyToStrict (ByteString -> ByteString) -> IO ByteString -> IO ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` Mail -> IO ByteString
renderMail' Mail
mail
ByteString -> [ByteString] -> ByteString -> SMTPConnection -> IO ()
sendRenderedMail ByteString
from [ByteString]
to ByteString
rendered SMTPConnection
conn
where enc :: Address -> ByteString
enc = Text -> ByteString
encodeUtf8 (Text -> ByteString) -> (Address -> Text) -> Address -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Address -> Text
addressEmail
from :: ByteString
from = Address -> ByteString
enc Address
mailFrom
to :: [ByteString]
to = (Address -> ByteString) -> [Address] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map Address -> ByteString
enc ([Address] -> [ByteString]) -> [Address] -> [ByteString]
forall a b. (a -> b) -> a -> b
$ [Address]
mailTo [Address] -> [Address] -> [Address]
forall a. [a] -> [a] -> [a]
++ [Address]
mailCc [Address] -> [Address] -> [Address]
forall a. [a] -> [a] -> [a]
++ [Address]
mailBcc
sendMailOnConnection :: Mail -> SMTPConnection -> IO ()
sendMailOnConnection :: Mail -> SMTPConnection -> IO ()
sendMailOnConnection mail :: Mail
mail con :: SMTPConnection
con = do
SMTPConnection -> Mail -> IO ()
renderAndSend SMTPConnection
con Mail
mail
SMTPConnection -> IO ()
closeSMTP SMTPConnection
con
sendMail :: HostName -> Mail -> IO ()
sendMail :: HostName -> Mail -> IO ()
sendMail host :: HostName
host mail :: Mail
mail = HostName -> IO SMTPConnection
connectSMTP HostName
host IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Mail -> SMTPConnection -> IO ()
sendMailOnConnection Mail
mail
sendMail' :: HostName -> PortNumber -> Mail -> IO ()
sendMail' :: HostName -> PortNumber -> Mail -> IO ()
sendMail' host :: HostName
host port :: PortNumber
port mail :: Mail
mail = HostName -> PortNumber -> IO SMTPConnection
connectSMTP' HostName
host PortNumber
port IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Mail -> SMTPConnection -> IO ()
sendMailOnConnection Mail
mail
sendMailWithLogin :: HostName -> UserName -> Password -> Mail -> IO ()
sendMailWithLogin :: HostName -> HostName -> HostName -> Mail -> IO ()
sendMailWithLogin host :: HostName
host user :: HostName
user pass :: HostName
pass mail :: Mail
mail = HostName -> IO SMTPConnection
connectSMTP HostName
host IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= HostName -> HostName -> Mail -> SMTPConnection -> IO ()
sendMailWithLoginIntern HostName
user HostName
pass Mail
mail
sendMailWithLogin' :: HostName -> PortNumber -> UserName -> Password -> Mail -> IO ()
sendMailWithLogin' :: HostName -> PortNumber -> HostName -> HostName -> Mail -> IO ()
sendMailWithLogin' host :: HostName
host port :: PortNumber
port user :: HostName
user pass :: HostName
pass mail :: Mail
mail = HostName -> PortNumber -> IO SMTPConnection
connectSMTP' HostName
host PortNumber
port IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= HostName -> HostName -> Mail -> SMTPConnection -> IO ()
sendMailWithLoginIntern HostName
user HostName
pass Mail
mail
sendMailWithSender :: ByteString -> HostName -> Mail -> IO ()
sendMailWithSender :: ByteString -> HostName -> Mail -> IO ()
sendMailWithSender sender :: ByteString
sender host :: HostName
host mail :: Mail
mail = HostName -> IO SMTPConnection
connectSMTP HostName
host IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteString -> Mail -> SMTPConnection -> IO ()
sendMailWithSenderIntern ByteString
sender Mail
mail
sendMailWithSender' :: ByteString -> HostName -> PortNumber -> Mail -> IO ()
sendMailWithSender' :: ByteString -> HostName -> PortNumber -> Mail -> IO ()
sendMailWithSender' sender :: ByteString
sender host :: HostName
host port :: PortNumber
port mail :: Mail
mail = HostName -> PortNumber -> IO SMTPConnection
connectSMTP' HostName
host PortNumber
port IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteString -> Mail -> SMTPConnection -> IO ()
sendMailWithSenderIntern ByteString
sender Mail
mail
sendMailTLS :: HostName -> Mail -> IO ()
sendMailTLS :: HostName -> Mail -> IO ()
sendMailTLS host :: HostName
host mail :: Mail
mail = HostName -> IO SMTPConnection
connectSMTPS HostName
host IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Mail -> SMTPConnection -> IO ()
sendMailOnConnection Mail
mail
sendMailTLS' :: HostName -> PortNumber -> Mail -> IO ()
sendMailTLS' :: HostName -> PortNumber -> Mail -> IO ()
sendMailTLS' host :: HostName
host port :: PortNumber
port mail :: Mail
mail = HostName -> PortNumber -> IO SMTPConnection
connectSMTPS' HostName
host PortNumber
port IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Mail -> SMTPConnection -> IO ()
sendMailOnConnection Mail
mail
sendMailWithLoginTLS :: HostName -> UserName -> Password -> Mail -> IO ()
sendMailWithLoginTLS :: HostName -> HostName -> HostName -> Mail -> IO ()
sendMailWithLoginTLS host :: HostName
host user :: HostName
user pass :: HostName
pass mail :: Mail
mail = HostName -> IO SMTPConnection
connectSMTPS HostName
host IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= HostName -> HostName -> Mail -> SMTPConnection -> IO ()
sendMailWithLoginIntern HostName
user HostName
pass Mail
mail
sendMailWithLoginTLS' :: HostName -> PortNumber -> UserName -> Password -> Mail -> IO ()
sendMailWithLoginTLS' :: HostName -> PortNumber -> HostName -> HostName -> Mail -> IO ()
sendMailWithLoginTLS' host :: HostName
host port :: PortNumber
port user :: HostName
user pass :: HostName
pass mail :: Mail
mail = HostName -> PortNumber -> IO SMTPConnection
connectSMTPS' HostName
host PortNumber
port IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= HostName -> HostName -> Mail -> SMTPConnection -> IO ()
sendMailWithLoginIntern HostName
user HostName
pass Mail
mail
sendMailWithSenderTLS :: ByteString -> HostName -> Mail -> IO ()
sendMailWithSenderTLS :: ByteString -> HostName -> Mail -> IO ()
sendMailWithSenderTLS sender :: ByteString
sender host :: HostName
host mail :: Mail
mail = HostName -> IO SMTPConnection
connectSMTPS HostName
host IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteString -> Mail -> SMTPConnection -> IO ()
sendMailWithSenderIntern ByteString
sender Mail
mail
sendMailWithSenderTLS' :: ByteString -> HostName -> PortNumber -> Mail -> IO ()
sendMailWithSenderTLS' :: ByteString -> HostName -> PortNumber -> Mail -> IO ()
sendMailWithSenderTLS' sender :: ByteString
sender host :: HostName
host port :: PortNumber
port mail :: Mail
mail = HostName -> PortNumber -> IO SMTPConnection
connectSMTPS' HostName
host PortNumber
port IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteString -> Mail -> SMTPConnection -> IO ()
sendMailWithSenderIntern ByteString
sender Mail
mail
sendMailSTARTTLS :: HostName -> Mail -> IO ()
sendMailSTARTTLS :: HostName -> Mail -> IO ()
sendMailSTARTTLS host :: HostName
host mail :: Mail
mail = HostName -> IO SMTPConnection
connectSMTPSTARTTLS HostName
host IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Mail -> SMTPConnection -> IO ()
sendMailOnConnection Mail
mail
sendMailSTARTTLS' :: HostName -> PortNumber -> Mail -> IO ()
sendMailSTARTTLS' :: HostName -> PortNumber -> Mail -> IO ()
sendMailSTARTTLS' host :: HostName
host port :: PortNumber
port mail :: Mail
mail = HostName -> PortNumber -> IO SMTPConnection
connectSMTPSTARTTLS' HostName
host PortNumber
port IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= Mail -> SMTPConnection -> IO ()
sendMailOnConnection Mail
mail
sendMailWithLoginSTARTTLS :: HostName -> UserName -> Password -> Mail -> IO ()
sendMailWithLoginSTARTTLS :: HostName -> HostName -> HostName -> Mail -> IO ()
sendMailWithLoginSTARTTLS host :: HostName
host user :: HostName
user pass :: HostName
pass mail :: Mail
mail = HostName -> IO SMTPConnection
connectSMTPSTARTTLS HostName
host IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= HostName -> HostName -> Mail -> SMTPConnection -> IO ()
sendMailWithLoginIntern HostName
user HostName
pass Mail
mail
sendMailWithLoginSTARTTLS' :: HostName -> PortNumber -> UserName -> Password -> Mail -> IO ()
sendMailWithLoginSTARTTLS' :: HostName -> PortNumber -> HostName -> HostName -> Mail -> IO ()
sendMailWithLoginSTARTTLS' host :: HostName
host port :: PortNumber
port user :: HostName
user pass :: HostName
pass mail :: Mail
mail = HostName -> PortNumber -> IO SMTPConnection
connectSMTPSTARTTLS' HostName
host PortNumber
port IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= HostName -> HostName -> Mail -> SMTPConnection -> IO ()
sendMailWithLoginIntern HostName
user HostName
pass Mail
mail
sendMailWithSenderSTARTTLS :: ByteString -> HostName -> Mail -> IO ()
sendMailWithSenderSTARTTLS :: ByteString -> HostName -> Mail -> IO ()
sendMailWithSenderSTARTTLS sender :: ByteString
sender host :: HostName
host mail :: Mail
mail = HostName -> IO SMTPConnection
connectSMTPSTARTTLS HostName
host IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteString -> Mail -> SMTPConnection -> IO ()
sendMailWithSenderIntern ByteString
sender Mail
mail
sendMailWithSenderSTARTTLS' :: ByteString -> HostName -> PortNumber -> Mail -> IO ()
sendMailWithSenderSTARTTLS' :: ByteString -> HostName -> PortNumber -> Mail -> IO ()
sendMailWithSenderSTARTTLS' sender :: ByteString
sender host :: HostName
host port :: PortNumber
port mail :: Mail
mail = HostName -> PortNumber -> IO SMTPConnection
connectSMTPSTARTTLS' HostName
host PortNumber
port IO SMTPConnection -> (SMTPConnection -> IO ()) -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= ByteString -> Mail -> SMTPConnection -> IO ()
sendMailWithSenderIntern ByteString
sender Mail
mail
sendMailWithLoginIntern :: UserName -> Password -> Mail -> SMTPConnection -> IO ()
sendMailWithLoginIntern :: HostName -> HostName -> Mail -> SMTPConnection -> IO ()
sendMailWithLoginIntern user :: HostName
user pass :: HostName
pass mail :: Mail
mail con :: SMTPConnection
con = do
(ReplyCode, ByteString)
_ <- SMTPConnection -> Command -> IO (ReplyCode, ByteString)
sendCommand SMTPConnection
con (AuthType -> HostName -> HostName -> Command
AUTH AuthType
LOGIN HostName
user HostName
pass)
SMTPConnection -> Mail -> IO ()
renderAndSend SMTPConnection
con Mail
mail
SMTPConnection -> IO ()
closeSMTP SMTPConnection
con
sendMailWithSenderIntern :: ByteString -> Mail -> SMTPConnection -> IO ()
sendMailWithSenderIntern :: ByteString -> Mail -> SMTPConnection -> IO ()
sendMailWithSenderIntern sender :: ByteString
sender mail :: Mail
mail con :: SMTPConnection
con = do
ByteString -> SMTPConnection -> Mail -> IO ()
renderAndSendFrom ByteString
sender SMTPConnection
con Mail
mail
SMTPConnection -> IO ()
closeSMTP SMTPConnection
con
renderAndSendFrom :: ByteString -> SMTPConnection -> Mail -> IO ()
renderAndSendFrom :: ByteString -> SMTPConnection -> Mail -> IO ()
renderAndSendFrom sender :: ByteString
sender conn :: SMTPConnection
conn mail :: Mail
mail@Mail{..} = do
ByteString
rendered <- ByteString -> ByteString
BL.toStrict (ByteString -> ByteString) -> IO ByteString -> IO ByteString
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
`fmap` Mail -> IO ByteString
renderMail' Mail
mail
ByteString -> [ByteString] -> ByteString -> SMTPConnection -> IO ()
sendRenderedMail ByteString
sender [ByteString]
to ByteString
rendered SMTPConnection
conn
where enc :: Address -> ByteString
enc = Text -> ByteString
encodeUtf8 (Text -> ByteString) -> (Address -> Text) -> Address -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Address -> Text
addressEmail
to :: [ByteString]
to = (Address -> ByteString) -> [Address] -> [ByteString]
forall a b. (a -> b) -> [a] -> [b]
map Address -> ByteString
enc ([Address] -> [ByteString]) -> [Address] -> [ByteString]
forall a b. (a -> b) -> a -> b
$ [Address]
mailTo [Address] -> [Address] -> [Address]
forall a. [a] -> [a] -> [a]
++ [Address]
mailCc [Address] -> [Address] -> [Address]
forall a. [a] -> [a] -> [a]
++ [Address]
mailBcc
login :: SMTPConnection -> UserName -> Password -> IO (ReplyCode, ByteString)
login :: SMTPConnection
-> HostName -> HostName -> IO (ReplyCode, ByteString)
login con :: SMTPConnection
con user :: HostName
user pass :: HostName
pass = SMTPConnection -> Command -> IO (ReplyCode, ByteString)
sendCommand SMTPConnection
con (AuthType -> HostName -> HostName -> Command
AUTH AuthType
LOGIN HostName
user HostName
pass)
simpleMail :: Address
-> [Address]
-> [Address]
-> [Address]
-> T.Text
-> [Part]
-> Mail
simpleMail :: Address
-> [Address]
-> [Address]
-> [Address]
-> Text
-> Alternatives
-> Mail
simpleMail from :: Address
from to :: [Address]
to cc :: [Address]
cc bcc :: [Address]
bcc subject :: Text
subject parts :: Alternatives
parts =
Mail :: Address
-> [Address]
-> [Address]
-> [Address]
-> Headers
-> [Alternatives]
-> Mail
Mail { mailFrom :: Address
mailFrom = Address
from
, mailTo :: [Address]
mailTo = [Address]
to
, mailCc :: [Address]
mailCc = [Address]
cc
, mailBcc :: [Address]
mailBcc = [Address]
bcc
, mailHeaders :: Headers
mailHeaders = [ ("Subject", Text
subject) ]
, mailParts :: [Alternatives]
mailParts = [Alternatives
parts]
}
plainTextPart :: TL.Text -> Part
plainTextPart :: Text -> Part
plainTextPart body :: Text
body = Text -> Encoding -> Disposition -> Headers -> PartContent -> Part
Part "text/plain; charset=utf-8"
Encoding
QuotedPrintableText Disposition
DefaultDisposition [] (ByteString -> PartContent
PartContent (ByteString -> PartContent) -> ByteString -> PartContent
forall a b. (a -> b) -> a -> b
$ Text -> ByteString
TL.encodeUtf8 Text
body)
{-# DEPRECATED plainTextPart "Use plainPart from mime-mail package" #-}
htmlPart :: TL.Text -> Part
htmlPart :: Text -> Part
htmlPart body :: Text
body = Text -> Encoding -> Disposition -> Headers -> PartContent -> Part
Part "text/html; charset=utf-8"
Encoding
QuotedPrintableText Disposition
DefaultDisposition [] (ByteString -> PartContent
PartContent (ByteString -> PartContent) -> ByteString -> PartContent
forall a b. (a -> b) -> a -> b
$ Text -> ByteString
TL.encodeUtf8 Text
body)
{-# DEPRECATED htmlPart "Use htmlPart from mime-mail package" #-}
filePart :: T.Text
-> FilePath
-> IO Part
filePart :: Text -> HostName -> IO Part
filePart ct :: Text
ct fp :: HostName
fp = do
ByteString
content <- HostName -> IO ByteString
BL.readFile HostName
fp
Part -> IO Part
forall (m :: * -> *) a. Monad m => a -> m a
return (Part -> IO Part) -> Part -> IO Part
forall a b. (a -> b) -> a -> b
$ Text -> Encoding -> Disposition -> Headers -> PartContent -> Part
Part Text
ct Encoding
Base64 (Text -> Disposition
AttachmentDisposition (Text -> Disposition) -> Text -> Disposition
forall a b. (a -> b) -> a -> b
$ HostName -> Text
T.pack (HostName -> HostName
takeFileName HostName
fp)) [] (ByteString -> PartContent
PartContent ByteString
content)
{-# DEPRECATED filePart "Use filePart from mime-mail package" #-}
lazyToStrict :: BL.ByteString -> B.ByteString
lazyToStrict :: ByteString -> ByteString
lazyToStrict = [ByteString] -> ByteString
B.concat ([ByteString] -> ByteString)
-> (ByteString -> [ByteString]) -> ByteString -> ByteString
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [ByteString]
BL.toChunks
crlf :: B8.ByteString
crlf :: ByteString
crlf = HostName -> ByteString
B8.pack "\r\n"
bsPutCrLf :: Conn.Connection -> ByteString -> IO ()
bsPutCrLf :: Connection -> ByteString -> IO ()
bsPutCrLf conn :: Connection
conn = Connection -> ByteString -> IO ()
Conn.connectionPut Connection
conn (ByteString -> IO ())
-> (ByteString -> ByteString) -> ByteString -> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ByteString -> ByteString -> ByteString)
-> ByteString -> ByteString -> ByteString
forall a b c. (a -> b -> c) -> b -> a -> c
flip ByteString -> ByteString -> ByteString
B.append ByteString
crlf