Beefy Boxes and Bandwidth Generously Provided by pair Networks
more useful options
 
PerlMonks  

comment on

( [id://3333]=superdoc: print w/replies, xml ) Need Help??

Years ago i made a Windows service which among other things also saved attachments from incoming messages from an inbox. Then I used IMAP as suggested already.

Also, if you search the internet for doing that with MAPI you learn that this can be a pain if possible at all inside your environment parameters (perl, in a service,...)

But because recently we decided we badly need that functionallity (IMAP will be disabled at some point in the future for the Exchange servers in question), I made a new attempt last month.

The following is a boiled down code from the real code I finally brought to production, which roughly resembles the VB in the OP.

The VB code from the OP remained as perl comments here for orientation, what happens about around that line.
Indented comments are all mine. If that is too distracting that VB code can be filtered out with something like

perl -ne "print unless /^#/" mapi.pl
#Option Explicit use strict; use warnings; use Win32::OLE qw(EVENTS); # Working with MAPI sessions needs other + threading model # # Private Sub Application_NewMail() sub application_newmail { my ($server, $alias) = @_; # connect to mailbox of CN $alias us +ing server $server my $mapikey = "$server\n$alias"; # # On Error GoTo GetAttachments_err #' Declare variables # Dim ns As NameSpace # Dim Inbox As MAPIFolder # Dim Item As Object # Dim Atmt As Attachment # Dim FileName As String # Dim i As Integer my $err; # Set ns = GetNamespace("MAPI") my $session = Win32::OLE->new(qw(MAPI.Session Logoff)) or return W +in32::OLE->LastError(); # Try to logon with dynamic profile under current account. # This may need a reasonable current CDO on your machine. $session->Logon(undef,undef,undef,1,undef,undef,$mapikey); return $err if $err = Win32::OLE->LastError(); # Set Inbox = ns.GetDefaultFolder(olFolderInbox) my $inbox = $mapi->Inbox(); return $err if $err = Win32::OLE->LastError(); # i = 0 # As described in MSDN, relying on Count for (possibly) "big" coll +ections (like items in folder) # can be problematic. Therefore we iterate with GetFirst/GetNext ( +see below) # 'Check Inbox for messages and exit of none found # If Inbox.Items.Count = 0 Then # Exit Sub # End If my $messages = $inbox->Messages() or return Win32::OLE->LastError +(); my $filter = $messages->Filter() or return Win32::OLE->LastError() +; $filter->{Unread} = 1; # Only unread messages $messages->Sort(); # default Sort is ASC on CdoPR_MESSAGE_DELIV +ERY_TIME return $err if $err = Win32::OLE->LastError(); #' Check each message for attachments # For Each Item In Inbox.Items for (my $msg = $messages->GetFirst(); $msg; $msg = $messages->GetN +ext()) { #' Save any attachments found # For Each Atmt In Item.Attachments my $atts = $msg->Attachments; if ($atts and my $count=$atts->Count) { # Count is O.K. for + "small" collections while ($count) { my $atmt = $atts->Item($count) or next; # There shouldn't be a path in the name, but be parano +id # ' This path must exist! Change folder name as necessary. # If Left(Atmt.FileName, 10) = "Flat_file_" Then (my $f = $atmt->Name || '') =~ s#.*[:\\/]##; next if !$f or $f !~ /^Flat_file_/; # FileName = "G:\Input\" & Atmt.FileName my $outfile = "G:\\Input\\$f"; # Beware! Backslashe +s required here! # Atmt.SaveAsFile FileName $atmt->WriteToFile($OutFile); return $err if $err = Win32::OLE->LastError; --$count; # i = i + 1 # End If # Next Atmt } } # Next Item } } # end sub

This code is untested but should work modulo typoes.

Edit: Cleaned up some incoherently on the fly renamed variables

You may comment the added lines with the "filter unread messages only" and the "sort with respect to message delivery time", if not needed.

Final remark: The code makes up a dynamic temporary MAPI profile. This feature is only available with a resonable (?!) current CDO on your machine. You should be fine, if OL 2002 or (2003) is installed on your machine :-/ (not tested otherwise).

Enjoy!

Edit: ADO?? I must have been involved in AD automation too much lately
:1,.-2s/ADO/CDO/g


In reply to Re: How do I convert VBA script to Perl? - Using Win32::OLE by pKai
in thread How do I convert VBA script to Perl? - Using Win32::OLE by Win

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post; it's "PerlMonks-approved HTML":



  • Are you posting in the right place? Check out Where do I post X? to know for sure.
  • Posts may use any of the Perl Monks Approved HTML tags. Currently these include the following:
    <code> <a> <b> <big> <blockquote> <br /> <dd> <dl> <dt> <em> <font> <h1> <h2> <h3> <h4> <h5> <h6> <hr /> <i> <li> <nbsp> <ol> <p> <small> <strike> <strong> <sub> <sup> <table> <td> <th> <tr> <tt> <u> <ul>
  • Snippets of code should be wrapped in <code> tags not <pre> tags. In fact, <pre> tags should generally be avoided. If they must be used, extreme care should be taken to ensure that their contents do not have long lines (<70 chars), in order to prevent horizontal scrolling (and possible janitor intervention).
  • Want more info? How to link or How to display code and escape characters are good places to start.
Log In?
Username:
Password:

What's my password?
Create A New User
Domain Nodelet?
Chatterbox?
and the web crawler heard nothing...

How do I use this?Last hourOther CB clients
Other Users?
Others imbibing at the Monastery: (9)
As of 2024-04-18 08:56 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found