6 |
6 |
use parent qw(SL::BackgroundJob::Base);
|
7 |
7 |
|
8 |
8 |
use SL::IMAPClient;
|
|
9 |
use SL::DB::EmailJournal;
|
9 |
10 |
use SL::DB::Manager::EmailImport;
|
10 |
11 |
use SL::Helper::EmailProcessing;
|
11 |
12 |
use SL::Presenter::Tag qw(link_tag);
|
12 |
|
use SL::Presenter::EscapedText qw(escape);
|
|
13 |
|
|
14 |
use List::MoreUtils qw(any);
|
13 |
15 |
|
14 |
16 |
sub sync_record_email_folder {
|
15 |
|
my ($self, $imap_client, $record_type, $folder) = @_;
|
|
17 |
my ($self, $config) = @_;
|
|
18 |
|
|
19 |
my $imap_client = SL::IMAPClient->new(%$config);
|
|
20 |
return "IMAP client is disabled." unless $imap_client;
|
16 |
21 |
|
17 |
22 |
my $email_import = $imap_client->update_emails_from_folder(
|
18 |
|
$folder,
|
|
23 |
$config->{folder},
|
19 |
24 |
{
|
20 |
25 |
email_journal => {
|
21 |
26 |
status => 'imported',
|
22 |
|
record_type => $record_type,
|
|
27 |
record_type => $config->{record_type},
|
23 |
28 |
},
|
24 |
29 |
}
|
25 |
30 |
);
|
|
31 |
return "No emails to import." unless $email_import;
|
|
32 |
|
|
33 |
my $result = "Created email import with id " . $email_import->id . ".";
|
|
34 |
|
|
35 |
if ($config->{process_imported_emails}) {
|
|
36 |
my @function_names =
|
|
37 |
ref $config->{process_imported_emails} eq 'ARRAY' ?
|
|
38 |
@{$config->{process_imported_emails}}
|
|
39 |
: ($config->{process_imported_emails});
|
|
40 |
foreach my $email_journal (@{$email_import->email_journals}) {
|
|
41 |
my $created_records = 0;
|
|
42 |
foreach my $function_name (@function_names) {
|
|
43 |
eval {
|
|
44 |
my $processed = SL::Helper::EmailProcessing->process_attachments($function_name, $email_journal);
|
|
45 |
$created_records += $processed;
|
|
46 |
1;
|
|
47 |
} or do {
|
|
48 |
# # TODO: link not shown as link
|
|
49 |
# my $email_journal_link = link_tag(
|
|
50 |
# $ENV{HTTP_ORIGIN} . $ENV{REQUEST_URI}
|
|
51 |
# . '?action=EmailJournal/show'
|
|
52 |
# . '&id=' . $email_journal->id
|
|
53 |
# # text
|
|
54 |
# , $email_journal->id
|
|
55 |
# );
|
|
56 |
my $email_journal_id = $email_journal->id;
|
|
57 |
$result .= "Error while processing email journal $email_journal_id attachments with $function_name: $@";
|
|
58 |
};
|
|
59 |
}
|
|
60 |
if ($created_records) {
|
|
61 |
$imap_client->set_flag_for_email(
|
|
62 |
$email_journal, $config->{processed_imap_flag});
|
|
63 |
} else {
|
|
64 |
$imap_client->set_flag_for_email(
|
|
65 |
$email_journal, $config->{not_processed_imap_flag});
|
|
66 |
}
|
|
67 |
}
|
|
68 |
$result .= "Processed attachments with "
|
|
69 |
. join(', ', @function_names) . "."
|
|
70 |
if scalar @function_names;
|
|
71 |
}
|
26 |
72 |
|
27 |
|
return $email_import;
|
|
73 |
return $result;
|
28 |
74 |
}
|
29 |
75 |
|
30 |
76 |
sub delete_email_imports {
|
31 |
|
my ($self) = @_;
|
32 |
|
my $job_obj = $self->{job_obj};
|
33 |
|
|
34 |
|
my $email_import_ids_to_delete =
|
35 |
|
$job_obj->data_as_hash->{email_import_ids_to_delete} || [];
|
|
77 |
my ($self, $email_import_ids_to_delete) = @_;
|
36 |
78 |
|
37 |
|
my @deleted_email_imports_ids;
|
|
79 |
my @not_found_email_import_ids;
|
|
80 |
my @deleted_email_import_ids;
|
38 |
81 |
foreach my $email_import_id (@$email_import_ids_to_delete) {
|
39 |
82 |
my $email_import = SL::DB::Manager::EmailImport->find_by(id => $email_import_id);
|
40 |
|
next unless $email_import;
|
|
83 |
unless ($email_import) {
|
|
84 |
push @not_found_email_import_ids, $email_import_id;
|
|
85 |
next;
|
|
86 |
}
|
41 |
87 |
$email_import->delete(cascade => 1);
|
42 |
|
push @deleted_email_imports_ids, $email_import_id;
|
|
88 |
push @deleted_email_import_ids, $email_import_id;
|
43 |
89 |
}
|
44 |
|
return unless @deleted_email_imports_ids;
|
45 |
90 |
|
46 |
|
return "Deleted email import(s): " . join(', ', @deleted_email_imports_ids) . ".\n";
|
|
91 |
my $result = "";
|
|
92 |
|
|
93 |
$result .= "Deleted email import(s): "
|
|
94 |
. join(', ', @deleted_email_import_ids) . "."
|
|
95 |
if scalar @deleted_email_import_ids;
|
|
96 |
|
|
97 |
$result .= "Could not find email import(s): "
|
|
98 |
. join(', ', @not_found_email_import_ids) . " for deletion."
|
|
99 |
if scalar @not_found_email_import_ids;
|
|
100 |
|
|
101 |
return $result;
|
47 |
102 |
}
|
48 |
103 |
|
49 |
104 |
sub run {
|
... | ... | |
52 |
107 |
|
53 |
108 |
my $data = $job_obj->data_as_hash;
|
54 |
109 |
|
55 |
|
my %configs = map { $_ => {
|
56 |
|
%{$data->{records}->{$_}},
|
57 |
|
config => $::lx_office_conf{"record_emails_imap/record/$_"}
|
58 |
|
|| $::lx_office_conf{record_emails_imap}
|
59 |
|
|| {},
|
60 |
|
} } keys %{$data->{records}};
|
|
110 |
my $email_import_ids_to_delete = $data->{email_import_ids_to_delete} || [];
|
61 |
111 |
|
62 |
|
my @results = ();
|
63 |
|
push @results, $self->delete_email_imports();
|
64 |
|
|
65 |
|
foreach my $import_key (keys %configs) {
|
66 |
|
my @record_results = ();
|
67 |
|
my $record_config = $configs{$import_key};
|
68 |
|
my $imap_client = SL::IMAPClient->new(%{$record_config->{config}});
|
69 |
|
my $record_folder = $record_config->{folder};
|
70 |
|
|
71 |
|
my $email_import = $self->sync_record_email_folder(
|
72 |
|
$imap_client, $import_key, $record_folder,
|
73 |
|
);
|
74 |
|
|
75 |
|
unless ($email_import) {
|
76 |
|
push @results, "$import_key No emails to import";
|
77 |
|
next;
|
78 |
|
}
|
79 |
|
push @record_results, "Created email import with id " . $email_import->id;
|
80 |
|
|
81 |
|
if ($record_config->{process_imported_emails}) {
|
82 |
|
my @function_names =
|
83 |
|
ref $record_config->{process_imported_emails} eq 'ARRAY' ?
|
84 |
|
@{$record_config->{process_imported_emails}}
|
85 |
|
: ($record_config->{process_imported_emails});
|
86 |
|
foreach my $email_journal (@{$email_import->email_journals}) {
|
87 |
|
my $created_records = 0;
|
88 |
|
foreach my $function_name (@function_names) {
|
89 |
|
eval {
|
90 |
|
my $processed = SL::Helper::EmailProcessing->process_attachments($function_name, $email_journal);
|
91 |
|
$created_records += $processed;
|
92 |
|
1;
|
93 |
|
} or do {
|
94 |
|
# TODO: link not shown as link
|
95 |
|
my $email_journal_link = link_tag(
|
96 |
|
$ENV{HTTP_ORIGIN} . $ENV{REQUEST_URI}
|
97 |
|
. '?action=EmailJournal/show'
|
98 |
|
. '&id=' . escape($email_journal->id)
|
99 |
|
# text
|
100 |
|
, $email_journal->id
|
101 |
|
);
|
102 |
|
push @record_results, "Error while processing email journal $email_journal_link attachments with $function_name: $@";
|
103 |
|
};
|
104 |
|
}
|
105 |
|
if ($created_records) {
|
106 |
|
$imap_client->set_flag_for_email(
|
107 |
|
$email_journal, $record_config->{processed_imap_flag});
|
108 |
|
} else {
|
109 |
|
$imap_client->set_flag_for_email(
|
110 |
|
$email_journal, $record_config->{not_processed_imap_flag});
|
111 |
|
}
|
|
112 |
my $record_type = $data->{record_type};
|
|
113 |
my $config = $::lx_office_conf{"record_emails_imap/record_type/$record_type"}
|
|
114 |
|| $::lx_office_conf{record_emails_imap}
|
|
115 |
|| {};
|
|
116 |
# overwrite with background job data
|
|
117 |
$config->{$_} = $data->{$_} for keys %$data;
|
112 |
118 |
|
113 |
|
}
|
114 |
|
push @record_results, "Processed attachments with " . join(', ', @function_names) . ".";
|
|
119 |
$record_type = $config->{record_type};
|
|
120 |
if ($record_type) {
|
|
121 |
my $valid_record_types = SL::DB::EmailJournal->meta->{columns}->{record_type}->{check_in};
|
|
122 |
unless (any {$record_type eq $_} @$valid_record_types) {
|
|
123 |
die "record_type '$record_type' is not valid. Possible values:\n- " . join("\n- ", @$valid_record_types);
|
115 |
124 |
}
|
|
125 |
}
|
116 |
126 |
|
117 |
|
push @results, join("\n- ", "$import_key :", @record_results);
|
|
127 |
my @results;
|
|
128 |
if (scalar $email_import_ids_to_delete) {
|
|
129 |
push @results, $self->delete_email_imports($email_import_ids_to_delete);
|
118 |
130 |
}
|
119 |
131 |
|
|
132 |
push @results, $self->sync_record_email_folder($config);
|
|
133 |
|
120 |
134 |
return join("\n", grep { $_ ne ''} @results);
|
121 |
135 |
}
|
122 |
136 |
|
... | ... | |
139 |
153 |
|
140 |
154 |
=head1 CONFIGURATION
|
141 |
155 |
|
142 |
|
In kivitendo.conf the settings for the IMAP server must be specified. The
|
|
156 |
In kivitendo.conf the settings for the IMAP server can be specified. The
|
143 |
157 |
default config is under [record_emails_imap]. The config for a specific record
|
144 |
|
type is under [record_emails_imap/record/<record_type>]. The config for a
|
145 |
|
specific record type overrides the default config.
|
146 |
|
|
147 |
|
In the data field 'records' of the background job, the record types to sync
|
148 |
|
emails for are specified. The key is the record type, the value is a hashref.
|
149 |
|
The hashref contains the following keys:
|
|
158 |
type is under [record_emails_imap/record_type/<record_type>]. The config for a
|
|
159 |
specific record type overwrites the default config. The data fields can
|
|
160 |
overwrite single configration values.
|
150 |
161 |
|
151 |
162 |
=over 4
|
152 |
163 |
|
|
164 |
=item record_type
|
|
165 |
|
|
166 |
The record type to set for each imported email journal. This is used to get
|
|
167 |
a specific config under [record_emails_imap/record_type/<record_type>].
|
|
168 |
|
153 |
169 |
=item folder
|
154 |
170 |
|
155 |
171 |
The folder to sync emails from. Sub folders are separated by a forward slash,
|
156 |
172 |
e.g. 'INBOX/Archive'. Subfolders are not synced.
|
157 |
173 |
|
158 |
|
=item process_imported_emails
|
159 |
|
|
160 |
|
The function name(s) to process the imported emails with. Multiple function
|
161 |
|
names can be specified as an arrayref. The function names are passed to
|
162 |
|
SL::Helper::EmailProcessing->process_attachments. The function names must be
|
163 |
|
implemented in SL::Helper::EmailProcessing.
|
164 |
|
|
165 |
|
=item processed_imap_flag
|
166 |
|
|
167 |
|
The IMAP flag to set for emails that were processed successfully.
|
168 |
|
|
169 |
|
=item not_processed_imap_flag
|
170 |
|
|
171 |
|
The IMAP flag to set for emails that were not processed successfully.
|
172 |
|
|
173 |
174 |
=back
|
174 |
175 |
|
175 |
|
=head1 METHODS
|
176 |
|
|
177 |
|
|
178 |
|
|
179 |
176 |
=head1 BUGS
|
180 |
177 |
|
181 |
178 |
Nothing here yet.
|
BJ:ImportRecordEmails: Konfiguration vereinfacht