summaryrefslogtreecommitdiffstats
path: root/lib/App/ImapNotify.pm
diff options
context:
space:
mode:
Diffstat (limited to 'lib/App/ImapNotify.pm')
-rw-r--r--lib/App/ImapNotify.pm95
1 files changed, 90 insertions, 5 deletions
diff --git a/lib/App/ImapNotify.pm b/lib/App/ImapNotify.pm
index 4cf5354..0b44f68 100644
--- a/lib/App/ImapNotify.pm
+++ b/lib/App/ImapNotify.pm
@@ -1,14 +1,16 @@
package App::ImapNotify;
-use 5.008001;
+use v5.24;
use strict;
use warnings;
our $VERSION = "0.01";
+use App::ImapNotify::ImapClient;
+use App::ImapNotify::Notifier;
-
-1;
-__END__
+use Carp;
+use Function::Parameters;
+use Log::Any qw($log);
=encoding utf-8
@@ -22,7 +24,9 @@ App::ImapNotify - It's new $module
=head1 DESCRIPTION
-App::ImapNotify is ...
+App::ImapNotify is a simple notification script using IMAP NOTIFY. Note that it is very simple and
+implements a custom IMAP client with very limited features. Mostly a proof of
+concept and personal script.
=head1 LICENSE
@@ -37,3 +41,84 @@ Florian Pritz E<lt>bluewind@xinu.atE<gt>
=cut
+method new($class: $config, $deps = {}) {
+ $deps->{imap_client} //= App::ImapNotify::ImapClient->new({$config->%{qw(host port log_id username password keepalive_timeout)}});
+ $deps->{notifier} //= App::ImapNotify::Notifier->new();
+ return $class->new_no_defaults($config, $deps);
+}
+
+method new_no_defaults($class: $config, $deps = {}) {
+ my $self = {};
+ bless $self, $class;
+ $self->{config} = $config;
+ $self->{deps} = $deps;
+ return $self;
+}
+
+method loop() {
+ #my $imap = $self->{deps}->{imap_client}->connect($self->{config}->@{qw(host port log_id)});
+ #$imap->login($self->{config}->@{qw(username password)});
+ my $imap = $self->{deps}->{imap_client};
+ $imap->select($self->{config}->{mailboxes}->@[0]);
+
+ $imap->send_command("notify set (selected (MessageExpunge MessageNew (uid body.peek[header.fields (from to subject)]))) (mailboxes (".join(' ', $self->{config}->{mailboxes}->@*).") (MessageNew MessageExpunge MailboxName))");
+
+ $log->info("Waiting for notify events");
+ while (my $line = $imap->readline_timeout()) {
+ $log->tracef("Got line: '%s'", $line);
+ if ($line =~ m/^\* .* FETCH /) {
+ my $message = $imap->handle_fetch($line);
+ $self->_notify($message);
+ next;
+ }
+ if ($line =~ m/^\* STATUS (?<mailbox>[^ ]+) \(MESSAGES \d+ UIDNEXT (?<uidnext>\d+) UNSEEN \d+\)/) {
+ $log->debugf("Got status change: '%s'", $line);
+ my $mailbox = $+{mailbox};
+ my $uid = $+{uidnext} - 1;
+ #$imap2->select($mailbox);
+ #my $message = $imap2->send_command("uid fetch $uid (body.peek[header.fields (from to subject)])");
+ $imap->select($mailbox);
+ my $message = $imap->send_command("uid fetch $uid (body.peek[header.fields (from to subject)])");
+ pop @{$message};
+ $self->_notify($message);
+ next;
+ }
+
+ next if $line =~ /\* \d+ RECENT/;
+ next if $line =~ /\* \d+ EXISTS/;
+ next if $line =~ /\* \d+ EXPUNGE/;
+
+ confess(sprintf("Got unexpected line: '%s'", $line));
+ }
+}
+
+method _notify($message) {
+ $log->debugf("Got data for notification: %s", $message);
+ my $fields = {};
+ my $current_field;
+
+ return if $message->@* == 0;
+
+ for my $line ($message->@*) {
+ if ($line =~ m/^(?<label>[^\s:]+): (?<value>.*)\r\n$/) {
+ $current_field = lc($+{label});
+ $fields->{$current_field} = $+{value};
+ next;
+ }
+
+ if ($line =~ m/^\s+(.*)$/) {
+ $fields->{$current_field} .= $1;
+ }
+ }
+
+ $log->debugf("Sending notification with data: %s", $fields);
+ my $notify_heading = sprintf("From: %s", $fields->%*->@{qw(from)});
+ my $notify_body = sprintf("Subject: %s", $fields->%*->@{qw(subject)});
+ $self->{deps}->{notifier}->notify($notify_heading, $notify_body);
+}
+
+
+
+1;
+__END__
+