Revision e453ae7c
Von Tamino Steinert vor 11 Monaten hinzugefügt
SL/IMAPClient.pm | ||
---|---|---|
5 | 5 |
use utf8; |
6 | 6 |
|
7 | 7 |
use Carp; |
8 |
use Params::Validate qw(:all); |
|
9 |
use List::MoreUtils qw(any); |
|
8 | 10 |
use IO::Socket::INET; |
9 | 11 |
use IO::Socket::SSL; |
10 | 12 |
use Mail::IMAPClient; |
... | ... | |
19 | 21 |
use SL::DB::EmailImport; |
20 | 22 |
use SL::DB::EmailJournal; |
21 | 23 |
use SL::DB::EmailJournalAttachment; |
24 |
use SL::DB::Order::TypeData; |
|
22 | 25 |
|
23 | 26 |
use SL::DB::Order; |
24 | 27 |
|
25 | 28 |
sub new { |
26 |
my ($class, %params) = @_; |
|
27 |
my $config = $::lx_office_conf{imap_client} || {}; |
|
29 |
my $class = shift; |
|
30 |
my %params = validate(@_, { |
|
31 |
enabled => { |
|
32 |
type => BOOLEAN, |
|
33 |
callbacks => {'is enabled' => sub { !!shift }} |
|
34 |
}, |
|
35 |
hostname => { type => SCALAR, }, |
|
36 |
port => { type => SCALAR, optional => 1, }, |
|
37 |
ssl => { type => BOOLEAN, }, |
|
38 |
username => { type => SCALAR, }, |
|
39 |
password => { type => SCALAR, }, |
|
40 |
base_folder => { type => SCALAR, default => 'INBOX', }, |
|
41 |
}); |
|
42 |
|
|
43 |
# get translation at runtime |
|
44 |
my $client_locale = $::locale; |
|
28 | 45 |
my $server_locale = Locale->new($::lx_office_conf{server}->{language}); |
29 |
my %record_type_to_folder = ( |
|
30 |
sales_quotation => $server_locale->text('Sales Quotations'), |
|
31 |
sales_order => $server_locale->text('Sales Orders'), |
|
32 |
); |
|
46 |
$::locale = $server_locale; |
|
47 |
my %record_type_to_folder = |
|
48 |
map { $_ => SL::DB::Order::TypeData->can('get3')->($_, 'text', 'list') } |
|
49 |
@{SL::DB::Order::TypeData->valid_types()}; |
|
50 |
$::locale = $client_locale; |
|
33 | 51 |
my %record_folder_to_type = reverse %record_type_to_folder; |
52 |
|
|
34 | 53 |
my $self = bless { |
35 |
enabled => $config->{enabled}, |
|
36 |
hostname => $config->{hostname}, |
|
37 |
port => $config->{port}, |
|
38 |
ssl => $config->{ssl}, |
|
39 |
username => $config->{username}, |
|
40 |
password => $config->{password}, |
|
41 |
base_folder => $config->{base_folder} || 'INBOX', |
|
54 |
%params, |
|
42 | 55 |
record_type_to_folder => \%record_type_to_folder, |
43 | 56 |
record_folder_to_type => \%record_folder_to_type, |
44 |
%params, |
|
45 | 57 |
}, $class; |
46 |
return unless $self->{enabled}; |
|
47 | 58 |
$self->_create_imap_client(); |
48 | 59 |
return $self; |
49 | 60 |
} |
... | ... | |
56 | 67 |
} |
57 | 68 |
|
58 | 69 |
sub store_email_in_email_folder { |
59 |
my ($self, $email_string, $folder_path) = @_; |
|
60 |
$folder_path ||= $self->{base_folder}; |
|
70 |
my $self = shift; |
|
71 |
my %params = validate(@_, { |
|
72 |
email_as_string => { |
|
73 |
type => SCALAR, |
|
74 |
callbacks => {'is not empty' => sub {shift ne ''}}, |
|
75 |
}, |
|
76 |
folder => { |
|
77 |
type => SCALAR, |
|
78 |
callbacks => {'is not empty' => sub {shift ne ''}}, |
|
79 |
}, |
|
80 |
}); |
|
61 | 81 |
|
62 |
my $folder_string = $self->get_folder_string_from_path($folder_path);
|
|
63 |
$self->{imap_client}->append_string($folder_string, $email_string)
|
|
82 |
my $folder_string = $self->get_folder_string_from_path(folder_path => $params{folder});
|
|
83 |
$self->{imap_client}->append_string($folder_string, $params{email_as_string})
|
|
64 | 84 |
or die "Could not store email in folder '$folder_string': " |
65 | 85 |
. $self->{imap_client}->LastError() . "\n"; |
66 | 86 |
} |
67 | 87 |
|
68 | 88 |
sub set_flag_for_email { |
69 |
my ($self, $email_journal, $imap_flag) = @_; |
|
70 |
return unless $imap_flag; |
|
89 |
my $self = shift; |
|
90 |
my %params = validate(@_, { |
|
91 |
email_journal => { isa => 'SL::DB::EmailJournal', }, |
|
92 |
flag => { type => SCALAR, }, |
|
93 |
}); |
|
94 |
my $email_journal = $params{email_journal}; |
|
95 |
my $flag = $params{flag}; |
|
71 | 96 |
|
72 | 97 |
my $folder_string = $email_journal->folder; |
73 | 98 |
|
... | ... | |
82 | 107 |
} |
83 | 108 |
|
84 | 109 |
my $uid = $email_journal->uid; |
85 |
$self->{imap_client}->set_flag($imap_flag, [$uid])
|
|
86 |
or die "Could not add flag '$imap_flag' to message '$uid': "
|
|
110 |
$self->{imap_client}->set_flag($flag, [$uid]) |
|
111 |
or die "Could not add flag '$flag' to message '$uid': " |
|
87 | 112 |
. $self->{imap_client}->LastError() . "\n"; |
88 | 113 |
} |
89 | 114 |
|
90 | 115 |
sub update_emails_from_folder { |
91 |
my ($self, $folder_path, $params) = @_; |
|
92 |
$folder_path ||= $self->{base_folder}; |
|
116 |
my $self = shift; |
|
117 |
my %params = validate(@_, { |
|
118 |
folder => { |
|
119 |
type => SCALAR | UNDEF, |
|
120 |
optional => 1, |
|
121 |
}, |
|
122 |
email_journal_params => { |
|
123 |
type => HASHREF | UNDEF, |
|
124 |
optional => 1, |
|
125 |
}, |
|
126 |
}); |
|
127 |
my $folder_path = $params{folder} || $self->{base_folder}; |
|
93 | 128 |
|
94 |
my $folder_string = $self->get_folder_string_from_path($folder_path); |
|
129 |
my $folder_string = $self->get_folder_string_from_path(folder_path => $folder_path);
|
|
95 | 130 |
my $email_import = |
96 |
_update_emails_from_folder_strings($self, $folder_path, [$folder_string], $params); |
|
131 |
$self->_update_emails_from_folder_strings( |
|
132 |
base_folder_path => $folder_path, |
|
133 |
folder_strings => [$folder_string], |
|
134 |
email_journal_params => $params{email_journal_params}, |
|
135 |
); |
|
97 | 136 |
|
98 | 137 |
return $email_import; |
99 | 138 |
} |
100 | 139 |
|
101 | 140 |
sub update_emails_from_subfolders { |
102 |
my ($self, $base_folder_path, $params) = @_; |
|
103 |
$base_folder_path ||= $self->{base_folder}; |
|
104 |
my $base_folder_string = $self->get_folder_string_from_path($base_folder_path); |
|
141 |
my $self = shift; |
|
142 |
my %params = validate(@_, { |
|
143 |
base_folder => { |
|
144 |
type => SCALAR, |
|
145 |
optional => 1, |
|
146 |
}, |
|
147 |
email_journal_params => { |
|
148 |
type => HASHREF | UNDEF, |
|
149 |
optional => 1, |
|
150 |
}, |
|
151 |
}); |
|
152 |
my $base_folder_path = $params{base_folder} || $self->{base_folder}; |
|
105 | 153 |
|
154 |
my $base_folder_string = $self->get_folder_string_from_path(folder_path => $base_folder_path); |
|
106 | 155 |
my @subfolder_strings = $self->{imap_client}->folders($base_folder_string) |
107 | 156 |
or die "Could not get subfolders via IMAP: $@\n"; |
108 | 157 |
@subfolder_strings = grep { $_ ne $base_folder_string } @subfolder_strings; |
109 | 158 |
|
110 | 159 |
my $email_import = |
111 |
_update_emails_from_folder_strings($self, $base_folder_path, \@subfolder_strings, $params); |
|
160 |
$self->_update_emails_from_folder_strings( |
|
161 |
base_folder_path => $base_folder_path, |
|
162 |
folder_strings => \@subfolder_strings, |
|
163 |
email_journal_params => $params{email_journal_params}, |
|
164 |
); |
|
112 | 165 |
|
113 | 166 |
return $email_import; |
114 | 167 |
} |
115 | 168 |
|
116 | 169 |
sub _update_emails_from_folder_strings { |
117 |
my ($self, $base_folder_path, $folder_strings, $params) = @_; |
|
170 |
my $self = shift; |
|
171 |
my %params = validate(@_, { |
|
172 |
base_folder_path => { type => SCALAR, }, |
|
173 |
folder_strings => { type => ARRAYREF, }, |
|
174 |
email_journal_params => { |
|
175 |
type => HASHREF | UNDEF, |
|
176 |
optional => 1, |
|
177 |
}, |
|
178 |
}); |
|
118 | 179 |
|
119 | 180 |
my $dbh = SL::DB->client->dbh; |
120 | 181 |
|
121 | 182 |
my $email_import; |
122 | 183 |
SL::DB->client->with_transaction(sub { |
123 |
foreach my $folder_string (@$folder_strings) {
|
|
184 |
foreach my $folder_string (@{$params{folder_strings}}) {
|
|
124 | 185 |
$self->{imap_client}->select($folder_string) |
125 | 186 |
or die "Could not select IMAP folder '$folder_string': $@\n"; |
126 | 187 |
|
... | ... | |
148 | 209 |
|
149 | 210 |
next unless @new_msg_uids; |
150 | 211 |
|
151 |
$email_import ||= $self->_create_email_import($base_folder_path)->save();
|
|
212 |
$email_import ||= $self->_create_email_import(folder_path => $params{base_folder_path})->save();
|
|
152 | 213 |
|
153 | 214 |
foreach my $new_uid (@new_msg_uids) { |
154 | 215 |
my $new_email_string = $self->{imap_client}->message_string($new_uid); |
155 | 216 |
my $email = Email::MIME->new($new_email_string); |
156 | 217 |
my $email_journal = $self->_create_email_journal( |
157 |
$email, $email_import, $new_uid, $folder_string, $folder_uidvalidity, $params->{email_journal} |
|
218 |
email => $email, |
|
219 |
email_import => $email_import, |
|
220 |
uid => $new_uid, |
|
221 |
folder_string => $folder_string, |
|
222 |
folder_uidvalidity => $folder_uidvalidity, |
|
223 |
email_journal_params => $params{email_journal_params}, |
|
158 | 224 |
); |
159 | 225 |
$email_journal->save(); |
160 | 226 |
} |
... | ... | |
165 | 231 |
} |
166 | 232 |
|
167 | 233 |
sub _create_email_import { |
168 |
my ($self, $folder_path) = @_; |
|
234 |
my $self = shift; |
|
235 |
my %params = validate(@_, { |
|
236 |
folder_path => { type => SCALAR, }, |
|
237 |
}); |
|
169 | 238 |
my $email_import = SL::DB::EmailImport->new( |
170 | 239 |
host_name => $self->{hostname}, |
171 | 240 |
user_name => $self->{username}, |
172 |
folder => $folder_path,
|
|
241 |
folder => $params{folder_path},
|
|
173 | 242 |
); |
174 | 243 |
return $email_import; |
175 | 244 |
} |
176 | 245 |
|
177 | 246 |
sub _create_email_journal { |
178 |
my ($self, $email, $email_import, $uid, $folder_string, $folder_uidvalidity, $params) = @_; |
|
247 |
my $self = shift; |
|
248 |
my %params = validate(@_, { |
|
249 |
email => { isa => 'Email::MIME', }, |
|
250 |
email_import => { isa => 'SL::DB::EmailImport', }, |
|
251 |
uid => { type => SCALAR, }, |
|
252 |
folder_string => { type => SCALAR, }, |
|
253 |
folder_uidvalidity => { type => SCALAR, }, |
|
254 |
email_journal_params => { type => HASHREF | UNDEF, optional => 1}, |
|
255 |
}); |
|
179 | 256 |
|
257 |
my $email = $params{email}; |
|
180 | 258 |
if ($email->content_type) { # decode header |
181 | 259 |
my $charset = $email->content_type =~ /charset="(.+)"/ ? $1 : undef; |
182 | 260 |
if ($charset) { |
... | ... | |
187 | 265 |
|
188 | 266 |
my $text_part; |
189 | 267 |
my %text_parts; |
190 |
_find_text_parts(\%text_parts, $email->parts); |
|
268 |
my @parts = $email->parts; |
|
269 |
_find_text_parts( |
|
270 |
text_parts => \%text_parts, |
|
271 |
parts => \@parts, |
|
272 |
); |
|
191 | 273 |
my @accepted_text_content_types = ('text/html', 'text/plain', ''); |
192 | 274 |
$text_part ||= $text_parts{$_} for @accepted_text_content_types; |
193 | 275 |
confess "can't find body text in email" unless $text_part; |
... | ... | |
199 | 281 |
my $header_string = join "\r\n", |
200 | 282 |
(map { $_ . ': ' . $header_map{$_} } keys %header_map); |
201 | 283 |
|
202 |
my $date = $self->_parse_date($email->header_str('Date'));
|
|
284 |
my $date = _parse_date($email->header_str('Date')); |
|
203 | 285 |
|
204 | 286 |
my $recipients = $email->header_str('To'); |
205 | 287 |
$recipients .= ', ' . $email->header_str('Cc') if ($email->header_str('Cc')); |
... | ... | |
222 | 304 |
}); |
223 | 305 |
|
224 | 306 |
my $email_journal = SL::DB::EmailJournal->new( |
225 |
email_import_id => $email_import->id,
|
|
226 |
folder => $folder_string,
|
|
227 |
folder_uidvalidity => $folder_uidvalidity,
|
|
228 |
uid => $uid,
|
|
307 |
email_import_id => $params{email_import}->id,
|
|
308 |
folder => $params{folder_string},
|
|
309 |
folder_uidvalidity => $params{folder_uidvalidity},
|
|
310 |
uid => $params{uid},
|
|
229 | 311 |
status => 'imported', |
230 | 312 |
extended_status => '', |
231 | 313 |
from => $email->header_str('From') || '', |
... | ... | |
235 | 317 |
body => $body_text, |
236 | 318 |
headers => $header_string, |
237 | 319 |
attachments => \@attachments, |
238 |
%$params,
|
|
320 |
%{$params{email_journal_params}},
|
|
239 | 321 |
); |
240 | 322 |
|
241 | 323 |
return $email_journal; |
242 | 324 |
} |
243 | 325 |
|
326 |
sub _find_text_parts { |
|
327 |
my %params = validate(@_,{ |
|
328 |
text_parts => {type => HASHREF,}, |
|
329 |
parts => { |
|
330 |
type => ARRAYREF, |
|
331 |
callbacks => { |
|
332 |
"contains only 'Email::MIME'" => sub { |
|
333 |
!scalar grep {ref $_ ne 'Email::MIME'} @{$_[0]} |
|
334 |
}, |
|
335 |
}, |
|
336 |
}, |
|
337 |
}); |
|
338 |
for my $part (@{$params{parts}}) { |
|
339 |
my $content_type = _cleanup_content_type($part->content_type); |
|
340 |
if ($content_type =~ m!^text/! or $content_type eq '') { |
|
341 |
$params{text_parts}->{$content_type} ||= $part; |
|
342 |
} |
|
343 |
my @subparts = $part->subparts; |
|
344 |
if (scalar @subparts) { |
|
345 |
_find_text_parts( |
|
346 |
text_parts => $params{text_parts}, |
|
347 |
parts => \@subparts, |
|
348 |
); |
|
349 |
} |
|
350 |
} |
|
351 |
}; |
|
352 |
|
|
244 | 353 |
sub _cleanup_content_type { |
245 | 354 |
my ($content_type) = @_; |
246 | 355 |
$content_type =~ s/\A\s+//; # Remove whitespaces at begin |
... | ... | |
249 | 358 |
return $content_type; |
250 | 359 |
}; |
251 | 360 |
|
252 |
sub _find_text_parts { |
|
253 |
my ($text_parts, @parts) = @_; |
|
254 |
for my $part (@parts) { |
|
255 |
my $content_type = _cleanup_content_type($part->content_type); |
|
256 |
if ($content_type =~ m!^text/! or $content_type eq '') { |
|
257 |
$text_parts->{$content_type} ||= $part; |
|
258 |
} |
|
259 |
_find_text_parts($text_parts, $part->subparts); |
|
260 |
} |
|
261 |
}; |
|
262 |
|
|
263 | 361 |
sub _parse_date { |
264 |
my ($self, $date) = @_;
|
|
362 |
my ($date) = @_; |
|
265 | 363 |
return '' unless $date; |
266 | 364 |
my $parse_date = $date; |
267 | 365 |
# replace whitespaces with single space |
... | ... | |
282 | 380 |
} |
283 | 381 |
|
284 | 382 |
sub update_email_files_for_record { |
285 |
my ($self, $record) = @_; |
|
286 |
|
|
287 |
my $folder_string = $self->_get_folder_string_for_record($record); |
|
383 |
my $self = shift; |
|
384 |
my %params = validate(@_,{ |
|
385 |
record => { |
|
386 |
isa => [qw(SL::DB::Order)], |
|
387 |
can => ['id', 'type'], |
|
388 |
}, |
|
389 |
}); |
|
390 |
my $record = $params{record}; |
|
391 |
my $folder_string = $self->_get_folder_string_for_record(record => $record); |
|
288 | 392 |
return unless $self->{imap_client}->exists($folder_string); |
289 | 393 |
$self->{imap_client}->select($folder_string) |
290 | 394 |
or die "Could not select IMAP folder '$folder_string': $@\n"; |
... | ... | |
333 | 437 |
sub update_email_subfolders_and_files_for_records { |
334 | 438 |
my ($self) = @_; |
335 | 439 |
my $base_folder_path = $self->{base_folder}; |
336 |
my $base_folder_string = $self->get_folder_string_from_path($base_folder_path); |
|
440 |
my $base_folder_string = $self->get_folder_string_from_path(folder_path => $base_folder_path);
|
|
337 | 441 |
|
338 | 442 |
my $folder_strings = $self->{imap_client}->folders($base_folder_string) |
339 | 443 |
or die "Could not get folders via IMAP: $@\n"; |
... | ... | |
341 | 445 |
|
342 | 446 |
# Store the emails to the records |
343 | 447 |
foreach my $subfolder_string (@subfolder_strings) { |
344 |
my $ilike_folder_path = $self->get_ilike_folder_path_from_string($subfolder_string); |
|
448 |
my $ilike_folder_path = $self->get_ilike_folder_path_from_string(folder_string => $subfolder_string);
|
|
345 | 449 |
my ( |
346 | 450 |
$ilike_record_folder_path, # is greedily matched |
347 | 451 |
$ilike_customer_number, # no spaces allowed |
... | ... | |
353 | 457 |
my $record_type = $self->{record_folder_to_type}->{$record_folder}; |
354 | 458 |
next unless $record_type; |
355 | 459 |
|
356 |
# TODO make it generic for all records |
|
357 |
my $is_quotation = $record_type eq 'sales_quotation' ? 1 : 0; |
|
358 |
my $number_field = $is_quotation ? 'quonumber' : 'ordnumber'; |
|
460 |
my $number_field = SL::DB::Order::TypeData->can('get3')->( |
|
461 |
$record_type, 'properties', 'nr_key'); |
|
359 | 462 |
my $record = SL::DB::Manager::Order->get_first( |
360 | 463 |
query => [ |
361 | 464 |
and => [ |
362 |
vendor_id => undef, |
|
363 |
quotation => $is_quotation, |
|
465 |
record_type => $record_type, |
|
364 | 466 |
$number_field => { ilike => $ilike_record_number }, |
365 | 467 |
], |
366 | 468 |
]); |
367 | 469 |
next unless $record; |
368 |
$self->update_email_files_for_record($record); |
|
470 |
$self->update_email_files_for_record(record => $record);
|
|
369 | 471 |
} |
370 | 472 |
|
371 | 473 |
return \@subfolder_strings; |
372 | 474 |
} |
373 | 475 |
|
374 | 476 |
sub create_folder { |
375 |
my ($self, $folder_name) = @_; |
|
376 |
return if $self->{imap_client}->exists($folder_name); |
|
377 |
$self->{imap_client}->create($folder_name) |
|
378 |
or die "Could not create IMAP folder '$folder_name': $@\n"; |
|
379 |
$self->{imap_client}->subscribe($folder_name) |
|
380 |
or die "Could not subscribe to IMAP folder '$folder_name': $@\n"; |
|
477 |
my $self = shift; |
|
478 |
my %params = validate(@_, { |
|
479 |
folder_string => {type => SCALAR}, |
|
480 |
}); |
|
481 |
my $folder_string = $params{folder_string}; |
|
482 |
return if $self->{imap_client}->exists($folder_string); |
|
483 |
$self->{imap_client}->create($folder_string) |
|
484 |
or die "Could not create IMAP folder '$folder_string': $@\n"; |
|
485 |
$self->{imap_client}->subscribe($folder_string) |
|
486 |
or die "Could not subscribe to IMAP folder '$folder_string': $@\n"; |
|
381 | 487 |
return; |
382 | 488 |
} |
383 | 489 |
|
384 | 490 |
sub get_folder_string_from_path { |
385 |
my ($self, $folder_path) = @_; |
|
491 |
my $self = shift; |
|
492 |
my %params = validate(@_, { |
|
493 |
folder_path => {type => SCALAR}, |
|
494 |
}); |
|
495 |
my $folder_path = $params{folder_path}; |
|
386 | 496 |
my $separator = $self->{imap_client}->separator(); |
387 | 497 |
if ($separator ne '/') { |
388 | 498 |
my $replace_sep = $separator ne '_' ? '_' : '-'; |
... | ... | |
394 | 504 |
} |
395 | 505 |
|
396 | 506 |
sub get_ilike_folder_path_from_string { |
397 |
my ($self, $folder_string) = @_; |
|
507 |
my $self = shift; |
|
508 |
my %params = validate(@_, { |
|
509 |
folder_string => {type => SCALAR}, |
|
510 |
}); |
|
511 |
my $folder_string = $params{folder_string}; |
|
398 | 512 |
my $separator = $self->{imap_client}->separator(); |
399 | 513 |
my $folder_path = decode('IMAP-UTF-7', $folder_string); |
400 | 514 |
$folder_path =~ s|\Q${separator}|/|g; # \Q -> escape special chars |
... | ... | |
403 | 517 |
} |
404 | 518 |
|
405 | 519 |
sub create_folder_for_record { |
406 |
my ($self, $record) = @_; |
|
407 |
my $folder_string = $self->_get_folder_string_for_record($record); |
|
408 |
$self->create_folder($folder_string); |
|
520 |
my $self = shift; |
|
521 |
my %params = validate(@_,{ |
|
522 |
record => { |
|
523 |
isa => [qw(SL::DB::Order)], |
|
524 |
}, |
|
525 |
}); |
|
526 |
my $record = $params{record}; |
|
527 |
my $folder_string = $self->_get_folder_string_for_record(record => $record); |
|
528 |
$self->create_folder(folder_string => $folder_string); |
|
409 | 529 |
return; |
410 | 530 |
} |
411 | 531 |
|
412 | 532 |
sub clean_up_imported_emails_from_folder { |
413 |
my ($self, $folder_path) = @_; |
|
414 |
$folder_path ||= $self->{base_folder}; |
|
415 |
|
|
416 |
my $folder_string = $self->get_folder_string_from_path($folder_path); |
|
533 |
my $self = shift; |
|
534 |
my %params = validate(@_, { |
|
535 |
folder_path => {type => SCALAR}, |
|
536 |
}); |
|
537 |
my $folder_path = $params{folder_path}; |
|
538 |
my $folder_string = $self->get_folder_string_from_path(folder_path => $folder_path); |
|
417 | 539 |
$self->_clean_up_imported_emails_from_folder_strings([$folder_string]); |
418 | 540 |
} |
419 | 541 |
|
420 | 542 |
|
421 | 543 |
sub _clean_up_imported_emails_from_folder_strings { |
422 |
my ($self, $folder_strings) = @_; |
|
544 |
my $self = shift; |
|
545 |
my %params = validate(@_, { |
|
546 |
folder_strings => {type => ARRAYREF}, |
|
547 |
}); |
|
548 |
my $folder_strings = $params{folder_strings}; |
|
423 | 549 |
my $dbh = SL::DB->client->dbh; |
424 | 550 |
|
425 | 551 |
foreach my $folder_string (@$folder_strings) { |
... | ... | |
456 | 582 |
} |
457 | 583 |
|
458 | 584 |
sub clean_up_record_subfolders { |
459 |
my ($self, $active_records) = @_; |
|
585 |
my $self = shift; |
|
586 |
my %params = validate(@_, { |
|
587 |
active_records => {type => ARRAYREF}, |
|
588 |
}); |
|
589 |
my $active_records = $params{active_records}; |
|
460 | 590 |
|
461 | 591 |
my $subfolder_strings = |
462 | 592 |
$self->update_email_subfolders_and_files_for_records(); |
463 | 593 |
|
464 |
my @active_folder_strings = map { $self->_get_folder_string_for_record($_) } |
|
594 |
my @active_folder_strings = map { $self->_get_folder_string_for_record(record => $_) }
|
|
465 | 595 |
@$active_records; |
466 | 596 |
|
467 | 597 |
my %keep_folder = map { $_ => 1 } @active_folder_strings; |
... | ... | |
474 | 604 |
} |
475 | 605 |
|
476 | 606 |
sub _get_folder_string_for_record { |
477 |
my ($self, $record) = @_; |
|
607 |
my $self = shift; |
|
608 |
my %params = validate(@_, { |
|
609 |
record => { |
|
610 |
isa => [qw(SL::DB::Order)], |
|
611 |
can => ['record_type', 'customervendor', 'number'], |
|
612 |
}, |
|
613 |
}); |
|
614 |
my $record = $params{record}; |
|
478 | 615 |
|
479 | 616 |
my $customer_vendor = $record->customervendor; |
480 | 617 |
|
... | ... | |
490 | 627 |
my $record_folder_path = |
491 | 628 |
$self->{base_folder} . '/' . |
492 | 629 |
$string_parts{cv_number} . ' ' . $string_parts{cv_name} . '/' . |
493 |
$self->{record_type_to_folder}->{$record->type} . '/' . |
|
630 |
$self->{record_type_to_folder}->{$record->record_type} . '/' .
|
|
494 | 631 |
$string_parts{record_number}; |
495 |
my $folder_string = $self->get_folder_string_from_path($record_folder_path); |
|
632 |
my $folder_string = $self->get_folder_string_from_path(folder_path => $record_folder_path);
|
|
496 | 633 |
return $folder_string; |
497 | 634 |
} |
498 | 635 |
|
... | ... | |
553 | 690 |
use SL::IMAPClient; |
554 | 691 |
|
555 | 692 |
# uses the config in config/kivitendo.conf |
556 |
my $imap_client = SL::IMAPClient->new(); |
|
693 |
my $imap_client = SL::IMAPClient->new(%{$::lx_office_conf{imap_client}});
|
|
557 | 694 |
|
558 |
# can also be used with a custom config, overriding the global config
|
|
695 |
# can also be used with a custom config |
|
559 | 696 |
my %config = ( |
560 | 697 |
enabled => 1, |
561 | 698 |
hostname => 'imap.example.com', |
... | ... | |
574 | 711 |
|
575 | 712 |
# update emails for record |
576 | 713 |
# fetches all emails from the IMAP server and saves them as attachments |
577 |
$imap_client->update_email_files_for_record($record); |
|
714 |
$imap_client->update_email_files_for_record(record => $record);
|
|
578 | 715 |
|
579 | 716 |
=head1 OVERVIEW |
580 | 717 |
|
... | ... | |
603 | 740 |
|
604 | 741 |
=item C<new> |
605 | 742 |
|
606 |
Creates a new SL::IMAPClient object. If no config is passed, the config |
|
607 |
from config/kivitendo.conf is used. If a config is passed, the global |
|
608 |
config is overridden. |
|
743 |
Creates a new SL::IMAPClient object with the given config. |
|
609 | 744 |
|
610 | 745 |
=item C<DESTROY> |
611 | 746 |
|
... | ... | |
654 | 789 |
on unix filesystem. The folder string is the path on the IMAP server. |
655 | 790 |
The folder string is encoded in IMAP-UTF-7. It can happend that |
656 | 791 |
C<get_folder_string_from_path> and C<get_ilike_folder_path_from_string> |
657 |
don't cancel each other out. This is because the IMAP server can has a
|
|
658 |
different Ieparator than the unix filesystem. The changes are made so that a
|
|
792 |
don't cancel each other out. This is because the IMAP server can have a
|
|
793 |
different separator than the unix filesystem. The changes are made so that a
|
|
659 | 794 |
ILIKE query on the database works. |
660 | 795 |
|
661 | 796 |
=item C<create_folder_for_record> |
Auch abrufbar als: Unified diff
IMAPClient: validiere Parameter bei der Übergabe