5 =head1 NAME $RCSfile: announceEmail.pl,v $
7 Monitors an IMAP Server and announce incoming emails by extracting the subject
8 line and from line and then pushing that into "GoogleTalk".
16 Andrew DeFaria <Andrew@DeFaria.com>
24 Thu Apr 4 13:40:10 MST 2019
28 $Date: 2019/04/04 13:40:10 $
34 Usage: announceEmail.pl [-usa|ge] [-h|elp] [-v|erbose] [-de|bug] [-da|emon]
35 [-use|rname <username>] [-p|assword <password>]
39 -usa|ge: Print this usage
41 -v|erbose: Verbose mode (Default: -verbose)
42 -de|bug: Turn on debugging (Default: Off)
43 -da|emon: Run in daemon mode (Default: -daemon)
44 -use|rname: User name to log in with (Default: $USER)
45 -p|assword: Password to use (Default: prompted)
46 -i|map: IMAP server to talk to (Default: defaria.com)
50 This script will connect to an IMAP server, login and then monitor the user's
51 INBOX. When new messages arrive it will extract the From address and Subject
52 from the message and compose a message to be used by "Google Talk" to announce
53 the email. The message will be similar to:
55 "<From> emailed <Subject>"
68 use lib "$FindBin::Bin/../lib";
74 my $defaultIMAPServer = 'defaria.com';
81 'You have received a new message',
82 'Hey I found this in your inbox',
83 'For some unknown reason this guy send you a message',
84 'Did you know you just got a message',
86 'You received a communique',
87 'I was looking in your inbox and found a message',
88 'Not sure you want to hear this message',
93 usage => sub { pod2usage },
94 help => sub { pod2usage(-verbose => 2)},
95 verbose => sub { set_verbose },
96 debug => sub { set_debug },
98 username => $ENV{USER},
99 password => $ENV{PASSWORD},
100 imap => $defaultIMAPServer,
105 $log->msg("Turning off debugging");
108 $log->msg("Turning on debugging");
115 $SIG{USR1} = \&interrupted;
120 $log->msg($msg) if get_debug;
126 $IMAP->select('inbox') or
127 $log->err("Unable to select inbox: " . get_last_error(), 1);
129 return map { $_=> 0 } @{$IMAP->search('not', 'seen')};
133 $log->msg("Connecting to $opts{imap} as $opts{username}");
135 $IMAP = Mail::IMAPTalk->new(
136 Server => $opts{imap},
137 Username => $opts{username},
138 Password => $opts{password},
139 ) or $log->err("Unable to connect to IMAP server $opts{imap}: $@", 1);
141 $log->msg('Connected');
143 # Focus on INBOX only
144 $IMAP->select('inbox');
146 # Setup %unseen to have each unseen message index set to 0 meaning not read
148 %unseen = unseenMsgs;
155 # First close and reselect the INBOX to get its current status
156 debugit "Reconnecting to INBOX";
158 $IMAP->select('INBOX')
159 or $log->err("Unable to select INBOX - ". $IMAP->errstr(), 1);
161 # Go through all of the unseen messages and add them to %unseen if they were
162 # not there already from a prior run and read
163 my %newUnseen = unseenMsgs;
165 # Now clean out any messages in %unseen that were not in the %newUnseen and
166 # marked as previously read
168 if (defined $newUnseen{$_}) {
170 delete $newUnseen{$_};
177 debugit "Processing newUnseen";
178 for (keys %newUnseen) {
181 my $envelope = $IMAP->fetch($_, '(envelope)');
182 my $from = $envelope->{$_}{envelope}{From};
183 my $subject = $envelope->{$_}{envelope}{Subject};
184 $subject //= 'Unknown subject';
186 # Extract the name only when the email is of the format "name <email>"
187 if ($from =~ /^"?(.*?)"?\s*\<(\S*)>/) {
188 $from = $1 if $1 ne '';
191 if ($subject =~ /=?\S+?(Q|B)\?(.+)\?=/) {
192 $subject = decode_base64($2);
195 # Google Talk doesn't like #
199 debugit "Speaking message from $from";
201 my $logmsg = "From $from $subject";
203 my $greeting = $greetings[int rand $#greetings];
204 my $msg = "$greeting from $from... " . quotemeta $subject;
212 my $cmd = "/usr/local/bin/gt \"$msg\"";
214 my $hour = (localtime)[2];
216 # Only announce if after 6 Am. Note this will announce up until
217 # midnight but that's ok. I want midnight to 6 Am as silent time.
219 my ($status, @output) = Execute $cmd;
222 $log->err("Unable to execute $cmd" . join("\n", @output));
234 $IMAP->quit if $IMAP;
236 $log->msg("$FindBin::Script ending!");
253 unless ($opts{password}) {
254 verbose "I need $opts{username}'s password";
255 $opts{password} = GetPassword;
258 $opts{debug} = get_debug;
260 EnterDaemonMode if $opts{daemon};
264 timestamped => 'yes',
270 my $msg = "Now monitoring email for $opts{username}\@$opts{imap}";
274 my $cmd = "/usr/local/bin/gt \"$msg\"";
276 my ($status, @output) = Execute $cmd;
278 $IMAP->idle(\&MonitorMail);