-- |
-- Send an email from your Gmail account using the
-- simple message transfer protocol with transport
-- layer security. If you have 2-step verification
-- enabled on your account, then you will need to
-- retrieve an application specific password before
-- using this function. Below is an example using
-- ghci, where Alice sends an Excel spreadsheet to
-- Bob.
--
-- > >>> :set -XOverloadedStrings
-- > >>> :module Network.Mail.Mime Network.Mail.Client.Gmail
-- > >>> sendGmail "alice" "password" (Address (Just "Alice") "alice@gmail.com") [Address (Just "Bob") "bob@example.com"] [] [] "Excel Spreadsheet" "Hi Bob,\n\nThe Excel spreadsheet is attached.\n\nRegards,\n\nAlice" ["Spreadsheet.xls"] 10000000
--
sendGmail
  :: L.Text     -- ^ username
  -> L.Text     -- ^ password
  -> Address    -- ^ from
  -> [Address]  -- ^ to
  -> [Address]  -- ^ cc
  -> [Address]  -- ^ bcc
  -> S.Text     -- ^ subject
  -> L.Text     -- ^ body
  -> [FilePath] -- ^ attachments
  -> Int        -- ^ timeout (in microseconds)
  -> IO ()
sendGmail user pass from to cc bcc subject body attachments micros = do
  let handle = connectTo "smtp.gmail.com" $ PortNumber 587
  bracket handle hClose $ \ hdl -> do
    recvSMTP hdl micros "220"
    sendSMTP hdl "EHLO"
    recvSMTP hdl micros "250"
    sendSMTP hdl "STARTTLS"
    recvSMTP hdl micros "220"
    let context = contextNew hdl params
    bracket context cClose $ \ ctx -> do
      handshake ctx
      sendSMTPS ctx "EHLO"
      recvSMTPS ctx micros "250"
      sendSMTPS ctx "AUTH LOGIN"
      recvSMTPS ctx micros "334"
      sendSMTPS ctx username
      recvSMTPS ctx micros "334"
      sendSMTPS ctx password
      recvSMTPS ctx micros "235"
      sendSMTPS ctx sender
      recvSMTPS ctx micros "250"
      sendSMTPS ctx recipient
      recvSMTPS ctx micros "250"
      sendSMTPS ctx "DATA"
      recvSMTPS ctx micros "354"
      sendSMTPS ctx =<< mail
      recvSMTPS ctx micros "250"
      sendSMTPS ctx "QUIT"
      recvSMTPS ctx micros "221"
      where username  = encode $ encodeUtf8 user
            password  = encode $ encodeUtf8 pass
            sender    = "MAIL FROM: " <> angleBracket [from]
            recipient = "RCPT TO: "   <> angleBracket (to ++ cc ++ bcc)
            mail      = renderMail from to cc bcc subject body attachments

-- |
-- Consume the SMTP packet stream.
sendGmail
  :: L.Text     -- ^ username
  -> L.Text     -- ^ password
  -> Address    -- ^ from
  -> [Address]  -- ^ to
  -> [Address]  -- ^ cc
  -> [Address]  -- ^ bcc
  -> S.Text     -- ^ subject
  -> L.Text     -- ^ body
  -> [FilePath] -- ^ attachments
  -> Int        -- ^ timeout (in microseconds)
  -> IO ()
sendGmail user pass from to cc bcc subject body attachments micros = do
  let handle = connectTo "smtp.gmail.com" $ PortNumber 587
  bracket handle hClose $ \ hdl -> do
    recvSMTP hdl micros "220"
    sendSMTP hdl "EHLO"
    recvSMTP hdl micros "250"
    sendSMTP hdl "STARTTLS"
    recvSMTP hdl micros "220"
    let context = contextNew hdl params
    bracket context cClose $ \ ctx -> do
      handshake ctx
      sendSMTPS ctx "EHLO"
      recvSMTPS ctx micros "250"
      sendSMTPS ctx "AUTH LOGIN"
      recvSMTPS ctx micros "334"
      sendSMTPS ctx username
      recvSMTPS ctx micros "334"
      sendSMTPS ctx password
      recvSMTPS ctx micros "235"
      sendSMTPS ctx sender
      recvSMTPS ctx micros "250"
      sendSMTPS ctx recipient
      recvSMTPS ctx micros "250"
      sendSMTPS ctx "DATA"
      recvSMTPS ctx micros "354"
      sendSMTPS ctx =<< mail
      recvSMTPS ctx micros "250"
      sendSMTPS ctx "QUIT"
      recvSMTPS ctx micros "221"
      where username  = encode $ encodeUtf8 user
            password  = encode $ encodeUtf8 pass
            sender    = "MAIL FROM: " <> angleBracket [from]
            recipient = "RCPT TO: "   <> angleBracket (to ++ cc ++ bcc)
            mail      = renderMail from to cc bcc subject body attachments

-- |
-- Consume the SMTP packet stream.
sendGmail user pass from to cc bcc subject body attachments micros = do
  let handle = connectTo "smtp.gmail.com" $ PortNumber 587
  bracket handle hClose $ \ hdl -> do
    recvSMTP hdl micros "220"
    sendSMTP hdl "EHLO"
    recvSMTP hdl micros "250"
    sendSMTP hdl "STARTTLS"
    recvSMTP hdl micros "220"
    let context = contextNew hdl params
    bracket context cClose $ \ ctx -> do
      handshake ctx
      sendSMTPS ctx "EHLO"
      recvSMTPS ctx micros "250"
      sendSMTPS ctx "AUTH LOGIN"
      recvSMTPS ctx micros "334"
      sendSMTPS ctx username
      recvSMTPS ctx micros "334"
      sendSMTPS ctx password
      recvSMTPS ctx micros "235"
      sendSMTPS ctx sender
      recvSMTPS ctx micros "250"
      sendSMTPS ctx recipient
      recvSMTPS ctx micros "250"
      sendSMTPS ctx "DATA"
      recvSMTPS ctx micros "354"
      sendSMTPS ctx =<< mail
      recvSMTPS ctx micros "250"
      sendSMTPS ctx "QUIT"
      recvSMTPS ctx micros "221"
      where username  = encode $ encodeUtf8 user
            password  = encode $ encodeUtf8 pass
            sender    = "MAIL FROM: " <> angleBracket [from]
            recipient = "RCPT TO: "   <> angleBracket (to ++ cc ++ bcc)
            mail      = renderMail from to cc bcc subject body attachments

-- |
-- Consume the SMTP packet stream.