sending email from happs?

7 views
Skip to first unread message

tphyahoo

unread,
Dec 3, 2008, 7:31:22 PM12/3/08
to HAppS
There used to be a way to send email from HAppS proper.

http://www.haskell.org/haskellwiki/HAppS_tutorial#Send_email

did this functionality disappear?

If so, it would be great if someone would post a quick howto for
configuring a happs app to send email, whether internally or calling
postfix or whatever.

I have also come across

http://www.cse.unsw.edu.au/~dons/git/HAppS-SMTP/ (dons's repo, but
patches are all signed alex jacobsen)

but I couldn't load it into ghci on checkout. (Could not find module
`HAppS.Network.DNS.MXClient':)

Much obliged,

thomas.

tphyahoo

unread,
Dec 3, 2008, 7:35:52 PM12/3/08
to HAppS
Come to think of it, happs.org advertises

HAppS-SMTP — send/receive/relay SMTP mail envelopes
darcs get --partial --tag=0.8 http://happs.org/repos/HAppS-SMTP

but this appears to be the same code, also doesn't build. (And there's
no tag .8)

I overlooked this because I usually just grab happs packages off
hackages, and the smtp package isn't cabalized.

thomas.

On Dec 4, 1:31 am, tphyahoo <thomashartm...@googlemail.com> wrote:
> There used to be a way to send email from HAppS proper.
>
> http://www.haskell.org/haskellwiki/HAppS_tutorial#Send_email
>
> did this functionality disappear?
>
> If so, it would be great if someone would post a quick howto for
> configuring a happs app to send email, whether internally or calling
> postfix or whatever.
>
> I have also come across
>
> http://www.cse.unsw.edu.au/~dons/git/HAppS-SMTP/(dons's repo, but

Parnell Flynn

unread,
Dec 4, 2008, 9:16:49 AM12/4/08
to HA...@googlegroups.com
This is a client that I hacked out of the original HAppS. I am sure someone could do better but it should be something for you to chew on at least. Best of all it works!

Parnell

> -----Original Message-----
> From: HA...@googlegroups.com [mailto:HA...@googlegroups.com] On Behalf Of
> tphyahoo
> Sent: Wednesday, December 03, 2008 6:36 PM
> To: HAppS
> Subject: Re: sending email from happs?
>
>
> Come to think of it, happs.org advertises
>
> HAppS-SMTP - send/receive/relay SMTP mail envelopes
SMTPClient.hs

parnell

unread,
Dec 4, 2008, 9:19:13 AM12/4/08
to HAppS
If you already got this message from me than please accept my
apologies for the spam.

This is a client that I hacked out of the original HAppS. I am sure
someone could do better but it should be something for you to chew on
at least. Best of all it works!

Parnell
{-# OPTIONS -fglasgow-exts #-}
module DSO.SMTPClient
(
Envelope(..), ezEnvelope, Address(..),Domain,
hostSend
) where

import Network
import Network.Socket
import Data.Dynamic
import Data.Char
import Data.Int
import Data.List
import Data.Typeable
import Control.Concurrent
import Control.Exception as E
import System.IO
import System.Environment


hPutLine :: Handle -> String -> IO ()
hPutLine handle line =
do
hPutStr handle $ line
hPutStr handle "\r\n"
hFlush handle
return ()

hGetLn :: Handle -> IO String
hGetLn handle = do
let hGetLn' = do
c <- hGetChar handle
case c of
'\n' -> do return []
'\r' -> do c2 <- hGetChar handle
if c2 == '\n' then return [] else getRest c
_ -> do getRest c
getRest c = do fmap (c:) hGetLn'
line <- hGetLn'
return line

ltrim = dropWhile isSpace
rtrim = reverse.ltrim.reverse
trim = ltrim.rtrim

split :: (a -> Bool) -> [a] -> ([a], [a])
split f s = (left, right)
where
(left,right')=break f s
right = if null right' then [] else tail right'


type Domain = String
data Address = Address {mailBox::String,domain::Domain} deriving
(Ord,Eq)

data Envelope msg = Envelope
{ relay :: Domain
, sender :: Address
, recipients :: [Address]
, contents :: msg
} deriving (Read, Show, Typeable)

ezEnvelope fromAddr toAddr contents =
Envelope "host" fromAddr [toAddr] contents

instance Show Address where
show (Address u d) = u++ '@' :d

instance Read Address where
readsPrec _ s = if isAddr then [(Address userId domain,rest)] else
[]
where
(userId,dr) = split (=='@') $ trim s
(domain, rest) = break(\x-> not $ isAlphaNum x || (x `elem`
"-_.")) dr
isAddr = not $ null userId || null domain

data SMTPState = RSET
| HELO Domain
| RCPTTO Domain Address [Address]

data SMTPError = SMTPError String deriving(Show, Typeable)

smtpErrorMajorCode :: SMTPError -> Int
smtpErrorMajorCode (SMTPError (e:_)) = fromEnum e - fromEnum '0'
smtpErrorMajorCode _ = -1




hostSend :: HostName -> Int -> Envelope String -> IO ()
hostSend host portNum msg = bracket (connectTo host (PortNumber $
fromIntegral portNum))
(\h -> hClose h `E.catch`(\_ -> return()))
(flip handleSend msg)

handleSend :: Handle -> Envelope String -> IO ()
handleSend smtpH msg = do
hGetLn smtpH >>= isReady
mapM_ (isAccept=<<) $
doLine smtpH ("HELO "++(relay msg)):
doLine smtpH ("MAIL FROM: <"++(show $ sender msg)++">") :
map (\addr->doLine smtpH $ "RCPT TO: <"++(show addr)++">")
(recipients msg)
isData =<< doLine smtpH "DATA"
hPutLine smtpH (contentData msg)
isAccept =<< doLine smtpH "."
isClose =<< doLine smtpH "QUIT"
where
isReady ('2':'2':'0':' ':_) = print "ISREADY" >> return ()
isReady msg = failure msg
isAccept ('2':'5':'0':' ':_) = return ()
isAccept ('2':'5':'1':' ':_) = return ()
isAccept msg = failure msg
isData ('3':'5':'4':' ':_)= return ()
isData msg = failure msg
isClose ('2':'2':'1':' ':_) = return ()
isClose msg = failure msg
failure s = do hPutLine smtpH "QUIT"
throwDyn $ SMTPError s


contentData msg = unlines $
map (\x->if x/=[] && head x=='.' then ('.':x) else
x) $
lines $ contents msg

doLine h line = hPutLine h line >> hGetLn h



On Dec 3, 6:31 pm, tphyahoo <thomashartm...@googlemail.com> wrote:
> There used to be a way to send email from HAppS proper.
>
> http://www.haskell.org/haskellwiki/HAppS_tutorial#Send_email
>
> did this functionality disappear?
>
> If so, it would be great if someone would post a quick howto for
> configuring a happs app to send email, whether internally or calling
> postfix or whatever.
>
> I have also come across
>
> http://www.cse.unsw.edu.au/~dons/git/HAppS-SMTP/(dons's repo, but

Lemmih

unread,
Dec 4, 2008, 9:35:55 AM12/4/08
to HA...@googlegroups.com
On Thu, Dec 4, 2008 at 1:31 AM, tphyahoo <thomash...@googlemail.com> wrote:
>
> There used to be a way to send email from HAppS proper.
>
> http://www.haskell.org/haskellwiki/HAppS_tutorial#Send_email
>
> did this functionality disappear?

It was disabled when we restructured the packages. I don't know when
it'll come back.

--
Cheers,
Lemmih

tphyahoo

unread,
Dec 5, 2008, 12:40:29 PM12/5/08
to HAppS
Parnell,

Thanks. It would be great if you could provide a one-line example of
using hostSend to send mail using, say, gmail as an smtp server.

Also, for anybody that wants to use this with ghc 6.10.1 you need to
replace Control.Exception with Control.OldException.

As soon as I get this working for me I'll hackagize it as part of
HAppSHelpers.

thomas.
> >http://www.cse.unsw.edu.au/~dons/git/HAppS-SMTP/(dons'srepo, but

tphyahoo

unread,
Dec 5, 2008, 12:52:28 PM12/5/08
to HAppS
On second thought, I think I just don't understand how this code
works.

Does this require having an email server behind a firewall? (Since I
don't see any authentication.)

I hate setting up smtp servers -- it should be simple, but because of
the security issues with spammers, it's not.

Continuing with my own research...

t.

Parnell Flynn

unread,
Dec 5, 2008, 1:01:31 PM12/5/08
to HA...@googlegroups.com
I am sure that you could come up with a better way to create the envelope object. In this example I have hard coded the domain from which and to which I send mails which is probably not to desirable for most people.


-- | This creates an envelope object that is used to send mail.
myenvelope subj mess to = Envelope {
relay = "localhost",
sender = Address "Name of Sender" "Domain" ,
recipients = [Address to "Reciever Domain"],
contents = "Subject: "++ subj ++ "\r\n" ++ mess
}

sendEmail :: String-> String->String->String->IO ()
sendEmail message subject recipients addr= do
hostSend addr 25 (myenvelope message subject recipients)


-- CreateSubject and Create Main message just return Strings from a data set.
(sendEmail (createMainMessage "" "" r) (createSubject (length r) db1) recip addr)

I hope this helps, I will be in 7th heaven once you hackagize this or something like it.

Are you running HAppS with 6.10.1? How has that worked for you?

Cheers,

Parnell

> -----Original Message-----
> From: HA...@googlegroups.com [mailto:HA...@googlegroups.com] On Behalf Of
> tphyahoo
> Sent: Friday, December 05, 2008 11:40 AM
> To: HAppS
> Subject: Re: sending email from happs?
>
>

parnell

unread,
Dec 5, 2008, 1:02:43 PM12/5/08
to HAppS
Yes this is just the client code that connects to an smtp server.
Sorry.

tphyahoo

unread,
Dec 5, 2008, 3:07:04 PM12/5/08
to HAppS
Why is there a recipients argument and an addr argument?

--(sendEmail (createMainMessage "" "" r) (createSubject (length r)
db1) recip addr)
sendEmail :: String-> String->String->String->IO ()
sendEmail message subject recipients addr= do

So far I have come up with example usage

t = sendEmail "test message" "test subject" "tphy...@gmail.com" "???"

Do the first three args seem okay? What should I put for arg 4?

happstutorial on ghc 6.10.1 has worked out for me pretty much without
a hitch.
Oh, there's one problem, the crypto library doesn't install right,
which I submitted a patch for. But nothing major.

I am also looking into http://www.ericstockwell.com/?p=3 as a solution
to sending email from inside webapps without implementing an SMTP
solution in haskell.

thomas.
On Dec 5, 7:01 pm, "Parnell Flynn" <parnell.fl...@ronin-capital.com>
wrote:

tphyahoo

unread,
Dec 5, 2008, 3:09:11 PM12/5/08
to HAppS
I think I see: addr would be the address of your smtp server.

But there's no authentication (user, password) so this would be
unusable with, eg, gmail as smtp server.

On Dec 5, 9:07 pm, tphyahoo <thomashartm...@googlemail.com> wrote:
> Why is there a recipients argument and an addr argument?
>
> --(sendEmail (createMainMessage "" "" r) (createSubject (length r)
> db1) recip addr)
> sendEmail :: String-> String->String->String->IO ()
> sendEmail message subject recipients addr= do
>
> So far I have come up with example usage
>
> t = sendEmail "test message" "test subject" "tphya...@gmail.com" "???"
>
> Do the first three args seem okay? What should I put for arg 4?
>
> happstutorial on ghc 6.10.1 has worked out for me pretty much without
> a hitch.
> Oh, there's one problem, the crypto library doesn't install right,
> which I submitted a patch for. But nothing major.
>
> I am also looking intohttp://www.ericstockwell.com/?p=3as a solution

tphyahoo

unread,
Dec 5, 2008, 3:33:14 PM12/5/08
to HAppS
With regards to outsourcing email needs to gmail, I have successfully
followed the instructions in

http://www.ericstockwell.com/?p=3

to send myself email from the command line. So I will probably use HSH
to run shell commands in my haskell web apps.

On Dec 5, 9:09 pm, tphyahoo <thomashartm...@googlemail.com> wrote:
> I think I see: addr would be the address of your smtp server.
>
> But there's no authentication (user, password) so this would be
> unusable with, eg, gmail as smtp server.
>
> On Dec 5, 9:07 pm, tphyahoo <thomashartm...@googlemail.com> wrote:
>
> > Why is there a recipients argument and an addr argument?
>
> > --(sendEmail (createMainMessage "" "" r) (createSubject (length r)
> > db1) recip addr)
> > sendEmail :: String-> String->String->String->IO ()
> > sendEmail message subject recipients addr= do
>
> > So far I have come up with example usage
>
> > t = sendEmail "test message" "test subject" "tphya...@gmail.com" "???"
>
> > Do the first three args seem okay? What should I put for arg 4?
>
> > happstutorial on ghc 6.10.1 has worked out for me pretty much without
> > a hitch.
> > Oh, there's one problem, the crypto library doesn't install right,
> > which I submitted a patch for. But nothing major.
>
> > I am also looking intohttp://www.ericstockwell.com/?p=3asa solution

tphyahoo

unread,
Dec 5, 2008, 3:45:50 PM12/5/08
to HAppS
Copy-pasting for posterity (because blogs die):

http://www.ericstockwell.com/?p=3

Quickie instructions for sending yourself gmail over the command line:

**********************

The purpose of this setup is to configure Ubuntu Linux so that you can
send an email with a single command from a bash terminal. The idea
behind this is that once set up to do it, your computer can now
actively alert you (or others) to state changes of your choosing (or
not). Phosphorus and Lime deserves accolades for a great deal of this
procedure. My omissions/simplifications assume that you are setting
this up from scratch, and are only planning to use this through an
existing gmail account.

Now then. You’re going to need a mail client and a SMTP handler. For
these purposes, mailx and msmtp, respectively, will serve you well.

$ sudo apt-get install mailx msmtp

Google’s SMTP service (kindly provided free for gmail account holders)
makes use of Thawte SSL certificates. Since /etc is only writeable by
root (meaning “sudo sudo sudo sudo”), let’s dump and configure them in
~/ like so:

$ mkdir -p ~/.etc/.certs
$ chmod 0700 ~/.etc/.certs
$ cd ~/.etc/.certs
$ wget https://www.verisign.com/support/thawte-roots.zip --no-check-
certificate
$ unzip thawte-roots.zip
$ cp Thawte\ Server\ Roots/ThawtePremiumServerCA_b64.txt
ThawtePremiumServerCA.crt

msmtp reads a local config file ( ~/.msmtprc ), containing several
important directives, at runtime. Open a text editor and create it:

$ nano ~/.msmtprc

…then enter the following (customized to your account):

account gmail
auth on
host smtp.gmail.com
port 587
# your email address and password on the next 3 lines...
user yourgmai...@gmail.com
password yourpasswordhere
from yourgmai...@gmail.com
tls on
tls_starttls on
# tls_trust_file argument is the full path to the certificate
# "myusername" is, uh, your user name
tls_trust_file /home/myusername/.etc/.certs/ThawtePremiumServerCA.crt
maildomain gmail.com
account default : gmail

Save and exit (or in nano’s case, exit and save) your editor, then
give only yourself read/write permissions to the file:

code>$ chmod 600 ~/.msmtprc

Now we configure some runtime parameters for mailx:

$ nano ~/.mailrc

Add the following lines, customized to your gmail account:

set from="yourgmai...@gmail.com"
set sendmail="/usr/bin/msmtp"
set message-sendmail-extra-arguments="-a gmail"

Make sure you’ve opened port 587 to the outside world from your
computer through your router!

Save/exit. If you’re so inclined, you can create a preformatted
plaintext file which will serve as the body of the email. As you can
imagine, this opens up all sorts of options to you.

Example:

$ echo "Here's some stuff that will appear in the body of the email."
> /tmp/email_body.txt
$ echo -n "Sent on " >> /tmp/email_body.txt
$ date >> /tmp/email_body.txt

You should be able to fire off an email to exa...@gmail.com using the
syntax shown:

$ mailx -s "O HAI SUBJECT LINE" exa...@gmail.com < /tmp/
email_body.txt

tphyahoo

unread,
Dec 19, 2008, 5:48:30 AM12/19/08
to HAppS
And here's a one-liner for sending email from inside hsh

runIO $ echo "this is an email" -|- "mailx -s \"O HAI SUBJECT LINE\"
thomash...@gmail.com"

I'm now going to use this to work on adding login confirmation via
email to the happstutorial web2.0-like app.

On Dec 5, 9:45 pm, tphyahoo <thomashartm...@googlemail.com> wrote:
> Copy-pasting for posterity (because blogs die):
>
> http://www.ericstockwell.com/?p=3
>
> Quickie instructions for sending yourself gmail over the command line:
>
> **********************
>
> The purpose of this setup is to configure Ubuntu Linux so that you can
> send anemailwith a single command from a bash terminal. The idea
> # youremailaddress and password on the next 3 lines...
> user yourgmailacco...@gmail.com
> password yourpasswordhere
> from yourgmailacco...@gmail.com
> tls on
> tls_starttls on
> # tls_trust_file argument is the full path to the certificate
> # "myusername" is, uh, your user name
> tls_trust_file /home/myusername/.etc/.certs/ThawtePremiumServerCA.crt
> maildomain gmail.com
> account default : gmail
>
> Save and exit (or in nano’s case, exit and save) your editor, then
> give only yourself read/write permissions to the file:
>
> code>$ chmod 600 ~/.msmtprc
>
> Now we configure some runtime parameters for mailx:
>
> $ nano ~/.mailrc
>
> Add the following lines, customized to your gmail account:
>
> set from="yourgmailacco...@gmail.com"
> set sendmail="/usr/bin/msmtp"
> set message-sendmail-extra-arguments="-a gmail"
>
> Make sure you’ve opened port 587 to the outside world from your
> computer through your router!
>
> Save/exit. If you’re so inclined, you can create a preformatted
> plaintext file which will serve as the body of theemail. As you can
> imagine, this opens up all sorts of options to you.
>
> Example:
>
> $ echo "Here's some stuff that will appear in the body of theemail."> /tmp/email_body.txt
>
> $ echo -n "Sent on " >> /tmp/email_body.txt
> $ date >> /tmp/email_body.txt
>
> You should be able to fire off anemailto exam...@gmail.com using the
> syntax shown:
>
> $ mailx -s "O HAI SUBJECT LINE" exam...@gmail.com < /tmp/
> email_body.txt
Reply all
Reply to author
Forward
0 new messages