Re: is it possible to use Perl to process Outlook emails?
by Corion (Patriarch) on Jul 26, 2011 at 13:09 UTC
|
How does the email get stored respectively how are you supposed to get access to the email?
Personally, I like IMAP servers for storing and accessing email, as Perl has quite good IMAP support. But as you are talking about "Outlook" (which is a client side program), maybe you mean that the data is stored in a Microsoft Exchange Server?
If the data is in fact stored in Microsoft Exchange, the first approach I would take would be to see how Exchange can be accessed through IMAP (see above). If that fails, you can always look at how to automate Outlook (through Win32::OLE) or, better, to use MAPI or Simple MAPI for accessing the Microsoft Exchange Server.
| [reply] [Watch: Dir/Any] |
|
The plan is for the data to arrive in an Outlook mailbox, in the normal work email system (which is an Exchange server). I have experimented with using the Outlook in-built export functionality to get the data into Access but the entire email body ends up as a single field.
As they say I wouldn't have started here but that part of the system was agreed between the corporate IT department and the users before I got involved.
| [reply] [Watch: Dir/Any] |
|
Your exchnage sever may have POP3 mail box access set up. If it has it's fairly easy to get Mail::POP3Client to grab the mail. I've had to do this recently:
#!c:\strawberry\perl\bin\perl.exe
use Modern::Perl;
use Mail::POP3Client;
use MIME::QuotedPrint;
my $pop_user = 'XXXXXXXXXX';
my $pop_pass = 'XXXXXXXXXX';
my $pop_host = 'exchange3';
#connect to POP3 sever
my $pop = new Mail::POP3Client ( HOST => $pop_host );
$pop->User($pop_user);
$pop->Pass($pop_pass);
$pop->Connect()
or die "Unable to connect to POP3 server: ".$pop->Message()."\n";
#count number of items in POP3 mailbox
my $mailcount = $pop->Count();
for (my $i = 1; $i <= $mailcount ; $i++) {
my $header = $pop->Head($i); #gets the header
my $uni = $pop->Uidl($i); # gets the unquie id
my $body = $pop->Body($i);
$body = decode_qp($body); #decode quoted printable body
say "$uni";
say "$header\n";
say "$body";
}
Edit 27/07/2011@10:33BST Removed reference to subroutine not include in code &return_error and replaced with die | [reply] [Watch: Dir/Any] [d/l] [select] |
|
|
|
Well, if you want a really backwards way to do it ( which is how I do it! ), i do it like the following:
1. Set up a complex rule in Outlook so that when a message arrives, the following sequence occurs:
a) Outlook can start up a program for you in the rule, i use it to start my perl program, which waits for:
b) Run the following VB script to save the email to a local file, which your perl script is polling
Sub WriteEmailToFile(MyMail As MailItem)
Dim myMailEntryID As String
Dim myMailBody As String
Dim outlookNameSpace As Outlook.NameSpace
Dim outlookMail As Outlook.MailItem
myMailEntryID = MyMail.EntryID
Set outlookNameSpace = Application.GetNamespace("MAPI")
Set outlookMail = outlookNameSpace.GetItemFromID(myMailEntryID)
Set fileSystemObject = CreateObject("Scripting.FileSystemObject")
/ you can create a dynamic text file name is you want...
Set textFile = fileSystemObject.CreateTextFile("c:\temp\OutlookEma
+il.txt", True)
textFile.WriteLine (outlookMail.SenderEmailAddress)
textFile.WriteLine (outlookMail.SentOn)
textFile.WriteLine (outlookMail.Subject)
outlookMailBody = outlookMail.Body
'strip non-printing characters
For x = 127 To 255
While InStr(outlookMailBody, Chr(x)) > 0
outlookMailBody = Replace(outlookMailBody, Chr(x), "")
Wend
Next x
textFile.WriteLine (outlookMailBody)
textFile.Close
End Sub
| [reply] [Watch: Dir/Any] [d/l] |
Re: is it possible to use Perl to process Outlook emails?
by VinsWorldcom (Prior) on Jul 26, 2011 at 13:53 UTC
|
dtach --no-attach -I body
| [reply] [Watch: Dir/Any] [d/l] |
Re: is it possible to use Perl to process Outlook emails?
by pileofrogs (Priest) on Jul 26, 2011 at 20:10 UTC
|
I use Net::IMAP::Simple to do stuff with emails on our Exchange server.
When will this run? Is this something yuu want to run yourself, something you want to run periodically on it's own (like once a day, even when you're out sick), or something you want to process each email as it arrives? Is this something you're going to run on your desktop* or on a server somewhere?
*I'm defining "server" is a computer you don't turn off and "desktop" as one that you do turn off.
I usually have stuff like this run on a server with cron in unix or Scheduled Tasks in windows.
--Pileofrogs
| [reply] [Watch: Dir/Any] |
Re: is it possible to use Perl to process Outlook emails?
by bingos (Vicar) on Jul 26, 2011 at 20:28 UTC
|
| [reply] [Watch: Dir/Any] |
Re: is it possible to use Perl to process Outlook emails?
by Anonymous Monk on Jul 26, 2011 at 13:05 UTC
|
Mail::Box should work, though years and years ago, some trivial stats were off on win32 (byte counts due to line endings -- not used for parsing) | [reply] [Watch: Dir/Any] |
Re: is it possible to use Perl to process Outlook emails?
by tmaly (Monk) on Jul 27, 2011 at 13:21 UTC
|
I used Redemption together with Win32::OLE module with strawberry perl to parse emails out of a pst file and save attachements and body to disk. Here is some rough code to do this
#!perl
use strict;
use Win32::OLE;
use Win32::OLE::Const;
use Win32::OLE::Const 'Microsoft Outlook';
use Data::Dumper;
use Archive::Zip qw( :ERROR_CODES :CONSTANTS );
use IO::File;
use Win32::OLE::Variant;
my $outlook;
eval {
$outlook = Win32::OLE->GetActiveObject('Outlook.Applic
+ation')
};
if ($@ || !defined($outlook)) {
$outlook = Win32::OLE->new('Outlook.Application', sub
+{$_[0]->Quit;})
or die("Cannot create outlook\n");
}
my $namespace = $outlook->GetNamespace('MAPI');
# get the proper pst file
my $folder = $namespace->{'Folders'}{'somepst'};
# now get the folder within the pst file
my $folder2 = $folder->{'Folders'}{"dailyfolder"};
# get all the messages
my $msgs = $folder2->{Items};
my $ncon = $msgs->{Count};
print "number of contacts - $ncon\n\n"; # this works
my $app = new Win32::OLE('Redemption.SafeMailItem');
my $con;
my $at;
my $fn;
my $obase = 'C:\strawberry\perl\daily\\';
my $out;
my $po = {};
foreach my $ii (1 .. $ncon) {
$con = $msgs->Item($ii);
$app->{'Item'} = $con;
#print_body($app->{Body});
#find_data($app->{Body},$ii,$t);
$at = $app->{'Attachments'};
print "\n\n Attachment count\n";
print $at->{Count} . "\n";
$fn = $at->Item(1)->{FileName};
print "filename is $fn\n" if $fn;
$out = $obase . $fn;
if(!-e $out) {
$at->Item(1)->SaveAsFile($out);
print "SAVING ATTACHMENT TO $out\n";
}
$po->{$out}++;
}
my $z = Archive::Zip->new();
my $i = 1;
my $fh;
my $fl;
my $exf = {};
my $he = 0;
foreach my $zf (keys %$po) {
warn("processing $zf\n");
unless( $z->read($zf) == AZ_OK) {
die("ERROR READING $zf\n");
}
foreach my $m ($z->memberNames()) {
warn("processing member $m\n");
if(! -e "$obase$m") {
$fh = IO::File->new("$obase$m",">") or
+ die($!);
$fl = $z->memberNamed($m);
$fl->extractToFileHandle($fh);
$fh->close() if $fh;
if($m =~ /\.xls$/) {
$exf->{"$obase$m"}++;
$he++;
}
next;
}
}
}
| [reply] [Watch: Dir/Any] [d/l] |
|
Followed ~~David~~ approach which works great, but shouldn't we call the perl script directly from VB rather than set a log watcher? Perhaps with unique file names and pass that as a parameter to the script... then maybe convert it to a binary with perl2exe so it's more easily proliferated throughout the enterprise?
Using this method now...
Re: how to permanently monitor a directory
....must be an easier way... , but it's still kind of cool.
- 3dbc
| [reply] [Watch: Dir/Any] |