MT#56555 OAuth2: EWS AttachmentDownloader implementation

AttachmentDownloader is an abstract base class for mail
services, implemented f.ex. for IMAP protocol.

This commit adds an implementation using the EWS Soap
protocol. It is the final part of the OAuth2 PoC.

Change-Id: Ibb1d115570b2ccd0891cfdc51b53266d6b55e923
mr11.3.1
Rene Krenn 3 years ago
parent 79dd0620dc
commit ef285f192f

@ -101,37 +101,38 @@ sub _process_message {
}
sub _process_attachments {
my ($self,$parsed,$subject,$filedir,$files_saved) = @_;
my ($self,$parsed,$subject,$filedir,$files_saved,@attachments) = @_;
my $found = 0;
unless (scalar @attachments) {
my $stripper = Email::MIME::Attachment::Stripper->new($parsed, (force_filename => 1));
my $stripper = Email::MIME::Attachment::Stripper->new($parsed, (force_filename => 1));
my @attachments = $stripper->attachments();
@attachments = $stripper->attachments();
}
foreach my $attachment (@attachments) {
$attachment->{subject} = $subject;
$attachment->{size} = length($attachment->{payload});
$attachment->{match} = undef;
if (defined $self->{checkfilenamecode} and ref $self->{checkfilenamecode} eq 'CODE') {
my $match = &{$self->{checkfilenamecode}}($attachment);
if ($match == $attachment_no_match) {
attachmentdownloaderinfo('attachment ' . $attachment->{filename} . ' (' . humanize_bytes($attachment->{size}, undef, 1) . ' ' . $attachment->{content_type} . ') skipped',getlogger(__PACKAGE__));
next;
} elsif ($match == $attachment_found) {
attachmentdownloaderinfo('attachment ' . $attachment->{filename} . ' (' . humanize_bytes($attachment->{size}, undef, 1) . ' ' . $attachment->{content_type} . ') found',getlogger(__PACKAGE__));
$found = 1;
} elsif ($match == $attachment_match) {
attachmentdownloaderinfo('attachment ' . $attachment->{filename} . ' (' . humanize_bytes($attachment->{size}, undef, 1) . ' ' . $attachment->{content_type} . ') matched',getlogger(__PACKAGE__));
} else {
attachmentdownloaderwarn('attachment ' . $attachment->{filename} . ' (' . humanize_bytes($attachment->{size}, undef, 1) . ' ' . $attachment->{content_type} . ') - unknown match, skipped',getlogger(__PACKAGE__));
next;
}
}
_save_file($attachment,$filedir,$files_saved);
$attachment->{subject} = $subject;
$attachment->{size} = length($attachment->{payload});
$attachment->{match} = undef;
if (defined $self->{checkfilenamecode} and ref $self->{checkfilenamecode} eq 'CODE') {
my $match = &{$self->{checkfilenamecode}}($attachment);
if ($match == $attachment_no_match) {
attachmentdownloaderinfo('attachment ' . $attachment->{filename} . ' (' . kbytes2gigs(int($attachment->{size} / 1024), undef, 1) . ' ' . $attachment->{content_type} . ') skipped',$logger);
next;
} elsif ($match == $attachment_found) {
attachmentdownloaderinfo('attachment ' . $attachment->{filename} . ' (' . kbytes2gigs(int($attachment->{size} / 1024), undef, 1) . ' ' . $attachment->{content_type} . ') found',$logger);
$found = 1;
} elsif ($match == $attachment_match) {
attachmentdownloaderinfo('attachment ' . $attachment->{filename} . ' (' . kbytes2gigs(int($attachment->{size} / 1024), undef, 1) . ' ' . $attachment->{content_type} . ') matched',$logger);
} else {
attachmentdownloaderwarn('attachment ' . $attachment->{filename} . ' (' . kbytes2gigs(int($attachment->{size} / 1024), undef, 1) . ' ' . $attachment->{content_type} . ') - unknown match, skipped',$logger);
next;
}
}
_save_file($attachment,$filedir,$files_saved);
}
return $found;
}

@ -0,0 +1,248 @@
package Downloaders::EWSAttachmentDownloader;
use warnings;
use strict;
use File::Basename;
use Cwd;
use lib File::Basename::dirname(__FILE__);
use lib Cwd::abs_path(File::Basename::dirname(__FILE__) . '/../');
use Logging qw(getlogger
attachmentdownloaderdebug
attachmentdownloaderinfo);
use LogError qw(fileerror
attachmentdownloadererror
attachmentdownloaderwarn);
use Utils qw(kbytes2gigs changemod);
use Office365::EWS::Client;
use AttachmentDownloader;
require Exporter;
our @ISA = qw(Exporter AttachmentDownloader);
our @EXPORT_OK = qw();
my $logger = getlogger(__PACKAGE__);
sub new {
my $class = shift;
my ($server,$mailbox,$tenant_id,$client_id,$client_secret,$foldername,$checkfilenamecode) = @_;
my $self = AttachmentDownloader->new($class,$server,$mailbox,$tenant_id,$client_id,$client_secret,$foldername,$checkfilenamecode);
attachmentdownloaderdebug('ews attachment downloader object created',$logger);
return $self;
}
sub logout {
my $self = shift;
$self->{folder} = undef;
}
sub setup {
my $self = shift;
my ($server,$mailbox,$tenant_id,$client_id,$client_secret,$foldername,$checkfilenamecode) = @_;
$self->logout();
attachmentdownloaderdebug('ews attachment downloader setup - ' . $server,$logger);
my $ews = Office365::EWS::Client->new({
server => $server, #'outlook.office.com',
tenant_id => $tenant_id,
client_id => $client_id,
client_secret => $client_secret,
use_negotiated_auth => 0,
});
my $entries = $ews->folders->retrieve({
impersonate => $mailbox,
});
$self->{impersonation} = {
Impersonation => {
ConnectingSID => {
PrimarySmtpAddress => $mailbox,
}
},
};
$self->{request_version} = {
RequestVersion => {
Version => $ews->server_version,
},
};
$self->{ews} = $ews;
$self->{checkfilenamecode} = $checkfilenamecode;
eval {
while ($entries->has_next) {
my $folder = $entries->next;
#print Dumper($entries->next);
#print $folder->DisplayName, "\n";
my $subfolders = $folder->SubFolders;
#print Dumper($subfolders);
foreach my $folder (@$subfolders) {
#my $subfolder = $entries->next;
#print " " . $folder->DisplayName . "\n";
#print $folder->FolderId . "\n";
if ($foldername eq $folder->DisplayName) { #"Posteingang"
#$self->{folderId} = $folder->FolderId->{Id};
$self->{folder} = $folder;
attachmentdownloaderdebug('folder ' . $foldername . ' found',$logger);
last;
}
}
last if $self->{folder};
}
};
if ($@) {
attachmentdownloadererror($@,$logger);
} else {
attachmentdownloaderinfo('ews login successful',$logger);
}
if (not defined $self->{folder}) {
attachmentdownloadererror('folder ' . $foldername . ' not found',$logger);
}
}
sub download {
my $self = shift;
my $filedir = shift;
my @files_saved = ();
my $message_count = 0;
my $found = 0;
if (defined $self->{folder}) {
attachmentdownloaderinfo('downloading messages from folder ' . $self->{folder}->DisplayName(),$logger);
my $finditem_response = $self->{ews}->FindItem->(
%{$self->{impersonation}},
%{$self->{request_version}},
#ItemShape => {
# BaseShape => Default,
# IncludeMimeContent => true,
#},
#ItemShape => {
# BaseShape => 'IdOnly',
#},
ItemShape => { BaseShape => 'AllProperties' },
Traversal => 'Shallow',
ParentFolderIds => {
#cho_FolderId => {
# FolderID => {
# Id => $folder->FolderId->{Id},
# }
#}
cho_FolderId => [
{
FolderId => {
#(exists $opts->{folderId} ? (
# Id => $folder->FolderId->{Id},
#) : Id => "msgfolderroot",)
Id => $self->{folder}->FolderId->{Id},
},
},
],
},
);
$self->{ews}->folders->_check_for_errors('FindItem', $finditem_response);
my @finditem_messages = $self->{ews}->folders->_list_messages('FindItem', $finditem_response);
my $messages = $finditem_messages[0]->{FindItemResponseMessage}->{RootFolder}->{Items}->{cho_Item};
foreach my $msg (@$messages) {
#print "yyy\n";
if ($msg->{Message}->{HasAttachments}) {
#print Dumper($msg->{Message});
#print "xxx\n";
my $getitem_response = $self->{ews}->GetItem->(
%{$self->{impersonation}},
%{$self->{request_version}},
ItemShape => {
BaseShape => 'Default',
IncludeMimeContent => 'false',
},
ItemIds => {
cho_ItemId => {
# #$msg->{Message}->{ItemId},
ItemId => {
Id => $msg->{Message}->{ItemId}->{Id},
},
},
},
);
#print "bbb";
#print $getitem_response;
#$self->{ews}->_check_for_errors('GetItem', $getitem_response);
#print "aaaa";
my @getitem_messages = $self->{ews}->folders->_list_messages('GetItem', $getitem_response);
my $attachments = $getitem_messages[0]->{GetItemResponseMessage}->{Items}->{cho_Item}->[0]->{Message}->{Attachments}->{cho_ItemAttachment};
#print Dumper($y[0]->{GetItemResponseMessage}->{Items}->{cho_Item}->[0]->{Message}->{Attachments}->{cho_ItemAttachment});
#die();
foreach my $attachment (@$attachments) {
#print "$attachment->{FileAttachment}->{Name}\n";
my $getattachment_response = $self->{ews}->GetAttachment->(
%{$self->{impersonation}},
%{$self->{request_version}},
AttachmentIds => {
cho_AttachmentId => {
AttachmentId => {
Id => $attachment->{FileAttachment}->{AttachmentId}->{Id},
}
}
}
);
#$self->{ews}->_check_for_errors('GetAttachment', $getattachment_response);
my @getattachment_messages = $self->{ews}->folders->_list_messages('GetAttachment', $getattachment_response);
#print Dumper(@z);
attachmentdownloaderinfo('processing message "' . $msg->{Message}->{Subject} . '"',$logger);
$found |= $self->_process_attachments(
#$getattachment_messages[0]->{GetItemResponseMessage}->{Items}->{cho_Item}->[0]->{Message}->{Subject}, #$message->header('Subject'),
undef,
$msg->{Message}->{Subject},
$filedir,
#$attachment->{FileAttachment}->{Name},
#
\@files_saved,
{
filename => $attachment->{FileAttachment}->{Name},
payload => $getattachment_messages[0]->{GetAttachmentResponseMessage}->{Attachments}->{cho_ItemAttachment}->[0]->{FileAttachment}->{Content},
}
);
$message_count++;
last if $found;
}
last if $found;
}
}
}
if (scalar @files_saved == 0) {
attachmentdownloaderwarn('ews attachment download complete - ' . $message_count . ' messages found, but no matching attachments saved',$logger);
} else {
attachmentdownloaderinfo('ews attachment download complete - ' . scalar @files_saved . ' files saved',$logger);
}
return \@files_saved;
}
1;
Loading…
Cancel
Save