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 -user|name: 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)
47 -uses|sl: Whether or not to use SSL to connect (Default: False)
51 This script will connect to an IMAP server, login and then monitor the user's
52 INBOX. When new messages arrive it will extract the From address and Subject
53 from the message and compose a message to be used by "Google Talk" to announce
54 the email. The message will be similar to:
56 "<From> emailed <Subject>"
69 use lib "$FindBin::Bin/../lib";
75 my $defaultIMAPServer = 'defaria.com';
82 'You have received a new message',
83 'Hey I found this in your inbox',
84 'For some unknown reason this guy send you a message',
85 'Did you know you just got a message',
87 'You received a communique',
88 'I was looking in your inbox and found a message',
89 'Not sure you want to hear this message',
94 usage => sub { pod2usage },
95 help => sub { pod2usage(-verbose => 2)},
96 verbose => sub { set_verbose },
97 debug => sub { set_debug },
99 username => $ENV{USER},
100 password => $ENV{PASSWORD},
101 imap => $defaultIMAPServer,
107 $log->msg("Turning off debugging");
110 $log->msg("Turning on debugging");
117 $SIG{USR1} = \&interrupted;
120 $IMAP->select('inbox') or
121 $log->err("Unable to select inbox: " . get_last_error(), 1);
123 return map { $_=> 0 } @{$IMAP->search('not', 'seen')};
127 $log->msg("Connecting to $opts{imap} as $opts{username}");
129 $IMAP = Mail::IMAPTalk->new(
130 Server => $opts{imap},
131 Username => $opts{username},
132 Password => $opts{password},
133 UseSSL => $opts{usessl},
134 ) or $log->err("Unable to connect to IMAP server $opts{imap}: $@", 1);
136 $log->msg('Connected');
138 # Focus on INBOX only
139 $IMAP->select('inbox');
141 # Setup %unseen to have each unseen message index set to 0 meaning not read
143 %unseen = unseenMsgs;
149 # First close and reselect the INBOX to get its current status
151 $IMAP->select('INBOX')
152 or $log->err("Unable to select INBOX - ". $IMAP->errstr(), 1);
154 # Go through all of the unseen messages and add them to %unseen if they were
155 # not there already from a prior run and read
156 my %newUnseen = unseenMsgs;
158 # Now clean out any messages in %unseen that were not in the %newUnseen and
159 # marked as previously read
161 if (defined $newUnseen{$_}) {
163 delete $newUnseen{$_};
170 for (keys %newUnseen) {
173 my $envelope = $IMAP->fetch($_, '(envelope)');
174 my $from = $envelope->{$_}{envelope}{From};
175 my $subject = $envelope->{$_}{envelope}{Subject};
176 $subject //= 'Unknown subject';
178 # Extract the name only when the email is of the format "name <email>"
179 if ($from =~ /^"?(.*?)"?\s*\<(\S*)>/) {
180 $from = $1 if $1 ne '';
183 if ($subject =~ /=?\S+?(Q|B)\?(.+)\?=/) {
184 $subject = decode_base64($2);
187 # Google Talk doesn't like #
191 my $logmsg = "From $from $subject";
193 my $greeting = $greetings[int rand $#greetings];
194 my $msg = "$greeting from $from... " . quotemeta $subject;
200 my $hour = (localtime)[2];
202 # Only announce if after 6 Am. Note this will announce up until
203 # midnight but that's ok. I want midnight to 6 Am as silent time.
205 my $cmd = "/usr/local/bin/gt \"$msg\"";
206 my ($status, @output) = Execute $cmd;
209 $log->err("Unable to execute $cmd" . join("\n", @output));
216 # Re-establish callback
217 $IMAP->idle(\&MonitorMail);
219 # Should not get here
220 $log->err("Unable to re-establish IDLE callback from IMAP server $opts{imap}", 1);
224 $IMAP->quit if $IMAP;
226 $log->msg("$FindBin::Script ending unexpectedly!");
244 unless ($opts{password}) {
245 verbose "I need $opts{username}'s password";
246 $opts{password} = GetPassword;
249 $opts{debug} = get_debug;
252 EnterDaemonMode unless defined $DB::OUT;
257 timestamped => 'yes',
263 my $msg = "Now monitoring email for $opts{username}\@$opts{imap}";
267 my $cmd = "/usr/local/bin/gt \"$msg\"";
269 my ($status, @output) = Execute $cmd;
271 $IMAP->idle(\&MonitorMail);
273 # Should not get here
274 $log->err("Falling off the edge of $0", 1);