1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
|
package App::ImapNotify;
use v5.24;
use strict;
use warnings;
our $VERSION = "0.01";
use App::ImapNotify::ImapClient;
use App::ImapNotify::Notifier;
use Carp;
use Function::Parameters;
use Log::Any qw($log);
=encoding utf-8
=head1 NAME
App::ImapNotify - It's new $module
=head1 SYNOPSIS
use App::ImapNotify;
=head1 DESCRIPTION
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
Copyright (C) Florian Pritz.
This library is free software; you can redistribute it and/or modify
it under the same terms as Perl itself.
=head1 AUTHOR
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__
|