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)
47 -s|leep: Number of minutes to sleep inbetween checking mail (Default: 1)
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>"
66 use Net::IMAP::Simple;
70 use lib "$FindBin::Bin/../lib";
76 my $defaultIMAPServer = 'defaria.com';
77 my $defaultSleeptime = 1;
83 usage => sub { pod2usage },
84 help => sub { pod2usage(-verbose => 2)},
85 verbose => sub { set_verbose },
86 debug => sub { set_debug },
88 username => $ENV{USER},
89 password => $ENV{PASSWORD},
90 imap => $defaultIMAPServer,
91 sleep => $defaultSleeptime,
96 $log->msg("Turning off debugging");
99 $log->msg("Turning on debugging");
106 $SIG{USR1} = \&interrupted;
111 $log->msg($msg) if get_debug;
119 for (my $i = 1; $i <= $IMAP->status; $i++) {
120 $unseenMsgs{$i} = 0 unless $IMAP->seen($i);
127 $log->msg("Connecting to $opts{imap} as $opts{username}...", 1);
129 $IMAP = Net::IMAP::Simple->new($opts{imap}) ||
130 $log->err("Unable to connect to IMAP server $opts{imap}: " . $Net::IMAP::Simple::errstr, 1);
132 $log->msg(' connected');
134 $log->msg("Logging onto $opts{imap} as $opts{username}...", 1);
136 unless ($IMAP->login($opts{username}, $opts{password})) {
137 $log->err("Login to $opts{imap} as $opts{username} failed: " . $IMAP->errstr, 1);
140 $log->msg(' logged on');
142 # Focus on INBOX only
143 $IMAP->select('INBOX');
145 # Setup %unseen to have each unseen message index set to 0 meaning not read
147 %unseen = unseenMsgs;
153 my $msg = "Now monitoring email for $opts{username}\@$opts{imap}";
157 my $cmd = "/usr/local/bin/gt \"$msg\"";
159 my ($status, @output) = Execute $cmd;
162 # First close and reselect the INBOX to get its current status
163 debugit "Reconnecting to INBOX";
165 $IMAP->select('INBOX')
166 or $log->err("Unable to select INBOX - ". $IMAP->errstr(), 1);
168 # Go through all of the unseen messages and add them to %unseen if they were
169 # not there already from a prior run and read
170 my %newUnseen = unseenMsgs;
172 # Now clean out any messages in %unseen that were not in the %newUnseen and
173 # marked as previously read
175 if (defined $newUnseen{$_}) {
177 delete $newUnseen{$_};
184 debugit "Processing newUnseen";
185 for (keys %newUnseen) {
188 my @msglines = $IMAP->top($_);
190 # What happens at INBOX 0? Does top return empty array?
191 $log->err("Unable to get top for $_ - " . $IMAP->errstr(), 1) unless @msglines;
193 my $email = Email::Simple->new(join '', @msglines);
195 my $from = $email->header('From');
197 # Extract the name only when the email is of the format "name <email>"
198 if ($from =~ /^"?(.*?)"?\s*\<(\S*)>/) {
199 $from = $1 if $1 ne '';
202 my $subject = $email->header('Subject');
204 if ($subject =~ /=?\S+?(Q|B)\?(.+)\?=/) {
205 $subject = decode_base64($2);
208 # Google Talk doesn't like #
212 debugit "Speaking message from $from";
213 my $logmsg = "From $from $subject";
215 $msg = "Message from $from... " . quotemeta $subject;
220 $cmd = "/usr/local/bin/gt \"$msg\"";
222 my $hour = (localtime)[2];
224 # Only announce if after 6 Am. Not this will announce up until
225 # midnight but that's ok. I want midnight to 6 Am as silent time.
227 ($status, @output) = Execute $cmd;
230 $log->err("Unable to execute $cmd" . join("\n", @output));
237 debugit "Sleeping for $opts{sleep} minutes";
238 sleep 60 * $opts{sleep};
239 debugit "Ah that was refreshing!";
245 $SIG{USR2} = \&MonitorMail;
248 $IMAP->quit if $IMAP;
250 $log->msg("$FindBin::Script ending!");
267 unless ($opts{password}) {
268 verbose "I need $opts{username}'s password";
269 $opts{password} = GetPassword;
272 $opts{debug} = get_debug;
274 EnterDaemonMode if $opts{daemon};
278 timestamped => 'yes',