File Coverage

blib/lib/Metabrik/Client/Imap.pm
Criterion Covered Total %
statement 9 98 9.1
branch 0 48 0.0
condition 0 26 0.0
subroutine 3 13 23.0
pod 1 10 10.0
total 13 195 6.6


line stmt bran cond sub pod time code
1             #
2             # $Id$
3             #
4             # client::imap Brik
5             #
6             package Metabrik::Client::Imap;
7 1     1   821 use strict;
  1         2  
  1         29  
8 1     1   5 use warnings;
  1         3  
  1         27  
9              
10 1     1   6 use base qw(Metabrik::String::Uri);
  1         2  
  1         514  
11              
12             sub brik_properties {
13             return {
14 0     0 1   revision => '$Revision$',
15             tags => [ qw(unstable) ],
16             author => 'GomoR ',
17             license => 'http://opensource.org/licenses/BSD-3-Clause',
18             attributes => {
19             datadir => [ qw(datadir) ],
20             input => [ qw(imap_uri) ],
21             as_array => [ qw(0|1) ],
22             strip_crlf => [ qw(0|1) ],
23             username => [ qw(username) ],
24             password => [ qw(password) ],
25             _imap => [ qw(INTERNAL) ],
26             _id => [ qw(INTERNAL) ],
27             _count => [ qw(INTERNAL) ],
28             },
29             attributes_default => {
30             as_array => 0,
31             strip_crlf => 1,
32             },
33             commands => {
34             open => [ qw(imap_uri|OPTIONAL) ],
35             reset_current => [ ],
36             total => [ ],
37             read => [ ],
38             read_next => [ ],
39             read_next_with_subject => [ qw(subject) ],
40             read_next_with_an_attachment => [ qw(regex|OPTIONAL) ],
41             parse => [ qw(message) ],
42             save_attachments => [ qw(message) ],
43             close => [ ],
44             },
45             require_modules => {
46             'URI::imap' => [ ],
47             'URI::imaps' => [ ],
48             'Metabrik::Email::Message' => [ ],
49             'Net::IMAP::Simple' => [ ],
50             },
51             };
52             }
53              
54             sub open {
55 0     0 0   my $self = shift;
56 0           my ($input) = @_;
57              
58 0   0       $input ||= $self->input;
59 0 0         $self->brik_help_set_undef_arg('input', $input) or return;
60              
61 0 0         my $parsed = $self->SUPER::parse($input) or return;
62 0           my $host = $parsed->{host};
63 0           my $port = $parsed->{port};
64 0   0       my $user = $parsed->{user} || $self->username;
65 0   0       my $password = $parsed->{password} || $self->password;
66 0   0       my $path = $parsed->{path} || 'INBOX';
67 0           $path =~ s{^/*}{};
68              
69 0 0 0       if (! defined($user) || ! defined($password) || ! defined($host)) {
      0        
70 0           return $self->log->error("open: invalid uri [$input] ".
71             "missing connection information");
72             }
73              
74 0 0         my $use_ssl = $self->is_imaps_scheme($parsed) ? 1 : 0;
75              
76 0           my $imap = Net::IMAP::Simple->new("$host:$port", use_ssl => $use_ssl);
77 0 0         if (! defined($imap)) {
78 0           return $self->log->error("open: can't connect to IMAP: $Net::IMAP::Simple::errstr");
79             }
80              
81 0           my $r = $imap->login($user, $password);
82 0 0         if (! defined($r)) {
83 0           return $self->log->error("open: login failed [".$imap->errstr."]");
84             }
85              
86 0           my $count = $imap->select($path);
87 0           $self->_count($count);
88 0           $self->_id($count);
89              
90 0           return $self->_imap($imap);
91             }
92              
93             sub reset_current {
94 0     0 0   my $self = shift;
95              
96 0           $self->_id($self->_count);
97              
98 0           return 1;
99             }
100              
101             sub total {
102 0     0 0   my $self = shift;
103              
104 0           my $imap = $self->_imap;
105 0 0         $self->brik_help_run_undef_arg('open', $imap) or return;
106              
107 0           return $self->_count;
108             }
109              
110             sub read_next {
111 0     0 0   my $self = shift;
112              
113 0           my $imap = $self->_imap;
114 0 0         $self->brik_help_run_undef_arg('open', $imap) or return;
115              
116 0           my $current = $self->_id;
117              
118 0           my @lines = $imap->get($current--);
119              
120 0           $self->_id($current);
121              
122 0 0         if ($self->as_array) {
123 0 0         if ($self->strip_crlf) {
124 0           for (@lines) {
125 0           s{[\r\n]*$}{};
126             }
127             }
128 0           return [ @lines ];
129             }
130              
131 0           return join("\n", @lines);
132             }
133              
134             sub read_next_with_subject {
135 0     0 0   my $self = shift;
136 0           my ($subject) = @_;
137              
138 0           my $imap = $self->_imap;
139 0 0         $self->brik_help_run_undef_arg('open', $imap) or return;
140 0 0         $self->brik_help_run_undef_arg('read_next_with_subject', $subject) or return;
141              
142 0           my $total = $self->total;
143              
144 0           for (1..$total) {
145 0 0         my $next = $self->read_next or return;
146 0 0         my $message = $self->parse($next) or return;
147 0           my $headers = $message->[0];
148              
149 0 0         if ($headers->{Subject} =~ m{$subject}i) {
150 0           return $next;
151             }
152             }
153              
154 0           return $self->log->error("read_next_with_subject: no message found with that subject ".
155             "in last $total messages.");
156             }
157              
158             sub read_next_with_an_attachment {
159 0     0 0   my $self = shift;
160 0           my ($regex) = @_;
161              
162 0           my $imap = $self->_imap;
163 0 0         $self->brik_help_run_undef_arg('open', $imap) or return;
164 0   0       $regex ||= qr/^.*$/;
165              
166 0           my $total = $self->total;
167              
168 0           for (1..$total) {
169 0 0         my $next = $self->read_next or return;
170 0 0         my $message = $self->parse($next) or return;
171 0           my $headers = $message->[0];
172              
173 0           for my $part (@$message) {
174 0 0 0       if (exists($part->{filename}) && length($part->{filename})
      0        
175             && $part->{filename} =~ $regex) {
176 0           return $next;
177             }
178             }
179             }
180              
181 0           return $self->log->error("read_next_with_an_attachment: no message found with ".
182             "an attachment in last $total messages.");
183             }
184              
185             sub parse {
186 0     0 0   my $self = shift;
187 0           my ($message) = @_;
188              
189 0 0         $self->brik_help_run_undef_arg('parse', $message) or return;
190              
191 0 0         my $em = Metabrik::Email::Message->new_from_brik_init($self) or return;
192              
193 0           return $em->parse($message);
194             }
195              
196             sub save_attachments {
197 0     0 0   my $self = shift;
198 0           my ($message) = @_;
199              
200 0 0         $self->brik_help_run_undef_arg('save_attachments', $message) or return;
201              
202 0 0         my $em = Metabrik::Email::Message->new_from_brik_init($self) or return;
203 0           $em->datadir($self->datadir);
204              
205 0           return $em->save_attachments($message);
206             }
207              
208             sub close {
209 0     0 0   my $self = shift;
210              
211 0           my $imap = $self->_imap;
212 0 0         if (defined($imap)) {
213 0           $imap->quit;
214 0           $self->_imap(undef);
215 0           $self->_id(undef);
216             }
217              
218 0           return 1;
219             }
220              
221             1;
222              
223             __END__