[philiptellis] /bb|[^b]{2}/
Never stop Grokking


Saturday, January 15, 2005

You've got mail! - loud and clear

You've got mail, announces the cheerful voice at AOL.
People who don't use AOL as their ISP will have seen it in advertisements and in the movie too at least.

AOL's program doesn't tell you anything more than that though. Who's the mail from, what's it about, nothing. To do that, one needs to parse a mailbox for the sender and subject, and then use a TTS tool to say it out loud.

Today I installed festival. It's a pretty cool TTS tool — runs on various unixes, which means prolly MacOSX as well.

I played around with festival for a few minutes while additional voices downloaded, and then hacked up this:

#!/usr/local/bin/bash

lock=/tmp/newmailnotify.lock
[ -e $lock ] && exit
touch $lock

awk " /^From / {from_start=1;sub_start=1}
/^From:/ && from_start==1 {print; from_start=0}
/^Subject:/ && sub_start==1 {print; sub_start=0}" /var/mail/philip | \
tail -n2 | \
sed -e '1iYou've got mail
s/:/ /;s/ R[eE]://g;s/$/./' | \
festival --tts

rm -f $lock


Attached it to my Inbox Monitor, to run every time the mailbox size increased, and now I have a (rather drab) British voice announcing my new mail, along with who it came from, and what it's about.

Yes, the script could do with improvements. I'm currently too lazy to figure out why case insensitive matches aren't working with sed or why I can't use alternation in my regexes, but hey, it's past 2:30am

Comments and suggestions welcome.

Oh yeah, I planned on using a single lock file across users, because:
a. The audio device would be busy anyway
b. Parsing large mailfiles takes a lot of time and is disk intensive. I don't want more than one of these to run at a time.

Update:
Festival was having trouble with Indian names, and some of the mailing lists I'm on, so I added some entries to its lexicon. Unfortunately, couldn't figure out how to get those entries loaded. .festivalrc did everything, but select my lexicon. I think it selected the default lexicon after selecting mine.

The only solution was to convert my script up there to one that output a festival script (scheme) rather than plain text.

This is what I came up with:

#!/usr/local/bin/bash

lock=/tmp/newmailnotify.lock
[ -e $lock ] && exit
touch $lock

msg=$1
[ -z "$msg" ] && msg="You've got mail!"

awk --assign msg="$msg" ' /^From / {from_start=1;sub_start=1}
/^From:/ && from_start==1 {from=$0; from_start=0}
/^Subject:/ && sub_start==1 {subject=$0; sub_start=0}
END {printf("%s\n%s\n%s\n", msg, from, subject);}
' /var/mail/philip | \
sed -e 's/:/ /;
s/ R[eE]://g;
2,$s/$/./;
/^From/s/ </, </;
1i
(lex.select "philip")
(SayText "$a")
' | \
festival --pipe

rm -f $lock

and this is what my .festivalrc file looks like:
(lex.create 'philip)

(lex.set.phoneset 'mrpa)
(lex.set.lts.method 'oald_lts_function)
(lex.set.compile.file "/usr/local/share/festival/lib/dicts/oald/oald-0.4.out")

(lex.add.entry '("sachin" n ((( s a ) 0) (( ch i n ) 1))))
(lex.add.entry '("vinayak" n (((v ii) 0) ((n ai) 1) ((@ k) 1) )))
(lex.add.entry '("amarendra" n (((a m) 0) ((@) 0) ((r ei) 1) ((n d r @nil) )))
(lex.add.entry '("vijay" n ((( v ii ) 0) (( ch ei ) 1))))
(lex.add.entry '("ilug-bom" n (((ai ) 1) ((l @ g ) 1) ((b o m) 0) )))
(lex.add.entry '("linuxers" n (((l i) 0) ((n @ k s @ r z ) 1) )))

Interestingly, it reads out mm.ilug-bom as millimetres dot i-lug-bom.

The other changes in the script allow you to customise your leadin message, and also ensure that From is read out before Subject.

Festival has an email mode, but modes only work when reading from a file or using the (tts 'filename mode) syntax. Since my input comes from stdin, there's no way to specify it.

Update 2:

Inspired by jace, I decided to try using procmail for this. The only change to the script is that /var/mail/philip is no longer in there. It reads from standard input. My procmail recipe looks like this:
:1 c

*^From:
|/home/philip/bin/newmailnotify.sh
and I put it at the end of .procmailrc.

I haven't yet been inundated with a deluge of emails, so don't know how it will work with bulk downloads. This of course runs after mails are sorted into folders, so only those that still make it to my inbox get reported.

8 comments :

Manish
January 15, 2005 7:58 PM

I haven't used Linux in six months now, but IIRC Bash gives you mail alerts if you set some environment variables. It does the same thing -- check the size of the mailbox. You might want to use Bash's capability instead of writing your own.

Blues
January 16, 2005 1:51 AM

Bash only tells you that you have new mail (that's what I call an Inbox Monitor), it doesn't tell you who from or what about.

Vineeth
January 17, 2005 3:14 AM

jace has a good functioning script honed over the years and uses lisp

Blues
January 17, 2005 3:18 AM

Yeah, he linked to it on my journal

Daily Article
January 18, 2005 6:29 AM

Nice little hack!
What if your Mailing list has constant pour of mails. Would not you be irritated? It shouts linuxers linuxers linuxers...
I would say shut down you drone, I am already checking it and would eventually be checking upon the newer ones in the stack/queue.

Blues
January 18, 2005 7:23 AM

That's why it only runs on Inbox and not on all mails that come in. All my other mails are sorted by procmail.

Rohith V
January 24, 2005 4:56 AM

Is there a place where I can ask it to read with a female voice. Its that much more pleasant. There are so many scm's..but where is the config file ?

Blues
January 24, 2005 5:15 AM

Download a female voice, and add the diphone command before the SayText command.

Post a Comment

...===...