Beefy Boxes and Bandwidth Generously Provided by pair Networks
There's more than one way to do things

is it possible to use Perl to process Outlook emails?

by mertserger (Curate)
on Jul 26, 2011 at 12:58 UTC ( #916759=perlquestion: print w/ replies, xml ) Need Help??
mertserger has asked for the wisdom of the Perl Monks concerning the following question:

I am about to be given a fairly large amount of emails which have been generated from a web form used by members of the public to input data. I have no control over this part of the system.

Ultimately I need to take information in the body of the email and turn it (probably) into XML data. I can see how to do this bit in Perl but the emails will be in a single folder and all have the same name since that is how the web form has been set up. Are there any Perl modules out there that can handle Outlook files and could cope with multiple files all sharing the same name?

Another part of my company have used similar emails and processed them using VBA in Access but I have no experience with that at all and would prefer to use Perl if possible

Comment on is it possible to use Perl to process Outlook emails?
Replies are listed 'Best First'.
Re: is it possible to use Perl to process Outlook emails?
by Corion (Pope) 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.

      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.

        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
        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
Re: is it possible to use Perl to process Outlook emails?
by VinsWorldcom (Vicar) on Jul 26, 2011 at 13:53 UTC
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.


Re: is it possible to use Perl to process Outlook emails?
by bingos (Vicar) on Jul 26, 2011 at 20:28 UTC

    I'm slightly surprised that no one has mentioned Mail-Outlook

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)
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; } } }

      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

Log In?

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://916759]
Approved by ww
Front-paged by chrestomanci
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others romping around the Monastery: (8)
As of 2016-02-11 18:03 GMT
Find Nodes?
    Voting Booth?

    How many photographs, souvenirs, artworks, trophies or other decorative objects are displayed in your home?

    Results (377 votes), past polls