Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

I am in need of a script that will log on to an Exchange Server (possibly using IMAP as the code below demonstrates), loop through several mailboxes, and extract all attachments from any messages that have attachments.

Here are my questions
1. Is it possible to use IMAP to log on using a master accout that has access to all mailboxes so that it can actually change from one mailbox to another without logging on as each individual user? If so, how?

2. How would one go about finding and extracting attachments using IMAP? I don't see any options for this?

3. I was thinking about storing this in a directory structure such as follows:
{User Name}
 {Folder Name}
  {Message Subject}
   {Attachment File}
However, the potential exists for the same folder to contain messages with the same subject and attachment name. Suggestion on handling this?

Below is some simple code that opens a connection to my server and then loops through the folders. It is a start, but the questions above must be answered before I can continue.
use Net::IMAP::Simple; # open a connection to the IMAP server $server = new Net::IMAP::Simple("myserver.mydomain.com"); print "server=$server\n"; # login $server->login( "MasterUser", "Password" ); # run through each mailbox (or folder) my @boxes = $server->mailboxes; foreach my $box (@boxes) { print "box=$box\n"; }
Any code or other help getting started would be much appreciated.

Replies are listed 'Best First'.
Re: Exchange Server and IMAP
by daddyefsacks (Pilgrim) on Nov 18, 2004 at 17:18 UTC

    2. When you say storing this in a directory structure, do you mean on a different machine or on the Exchange server?

    If you just want to download the messages, strip the attachments and store them locally this can be done with something like Email::Mime::Attachment::Stripper:
    my $message_count = $server->select( 'folder' ); print "Found $message_count messages\n"; foreach my $message_number ( 1 .. $message_count ) { print "Processing message number $message_number\n"; my $email = Email::MIME->new( join '', @{$server->get( $message_nu +mber )} ); my $stripper = Email::MIME::Attachment::Stripper->new($email); my @attachments = $stripper->attachments; foreach my $attachment ( @attachments ) { print $attachment->{filename}, " ", $attachment->{content_type +}, "\n"; } }
    In my brief experience I haven't had problems using similar code to access an Exchange server in the past (although the code above is untested as I don't have access to that code right now) other than dealing with ms-tnef attachments from Outlook users sending RTF messages..

    3. Suggestions on handling this depend more on your requirements. You can always append the date/time of the message you are processing to the attachment name or perhaps see if an attachment by the name you have already exists and append a number to the end etc..

    Hope that helps!

      Getting the emails is easy if you can get access to the mail account... getting access to all of the mail accounts is the hard part...

      Team Sybase member

      No one has seen what you have seen, and until that happens, we're all going to think that you're nuts. - Jack O'Neil, Stargate SG-1

        Aww it's not that hard, just ask each user for their username and password and log in! :)

        I realize that's the hard part and it's a good thing it is hard, I just thought I'd give some pointers on the parts I know a little bit about.

Re: Exchange Server and IMAP
by jfroebe (Parson) on Nov 18, 2004 at 16:47 UTC

    Hi,

    Simply, IMAP was never intended for what you are trying to do. You need to use the OLE hooks that Exchange provides (perl would access them through Win32::OLE) ... please note that you will likely need the Microsoft Office XP Developer on your development box.

    There are plenty of vb script examples that you will be able to convert to perl with a little bit of work... BUT I think you should save yourself alot of work and just write your script in VB Script.

    Note, that you can use Win32::Exchange but it doesn't appear to be well suited for the task you want

    Jason L. Froebe

    Team Sybase member

    No one has seen what you have seen, and until that happens, we're all going to think that you're nuts. - Jack O'Neil, Stargate SG-1

      IMAP is perfectly capable of doing this task. Exchange may not be (I am not familiar enough with its implementation of the protocol to say). It is absolutely possible to grant a user read-only access to other people's mailboxes (see, for example, IMAP::Admin, Mail::IMAPTalk). The Mail::IMAPTalk module will allow downloading attachments, providing unique ids and changing folders (there's an example in the POD of looking at another user's mailbox):

      $imap = Mail::IMAPTalk->new( Server => 'foo.com', Port => 143, Username => 'joebloggs', Password => 'mypassword', Separator => '.', RootFolder => 'inbox', CaseInsensitive => 1) || die "Connection to foo.com failed. Reason: $@"; $imap->select('user.john'); # Selects 'user.john' my $Res = $imap->fetch('1:*', 'all');

      Updated: Here's the example for changing folder access:

      # Get full access for user 'joe' on his own folder $imap->setacl('user.joe','joe','lrswipcda') || die "IMAP error: $@"; # Remove write, insert, post, create, delete access for user 'andrew' $imap->setacl('user.joe','andrew','-wipcd') || die "IMAP error: $@"; # Add lookup, read, keep unseen information for user 'paul' $imap->setacl('user.joe','paul','+lrs') || die "IMAP error: $@";

      The intelligent reader will judge for himself. Without examining the facts fully and fairly, there is no way of knowing whether vox populi is really vox dei, or merely vox asinorum. -- Cyrus H. Gordon

        Hi

        IMAP for Exchange 5.5 and 2000 has to be enabled for it to work. As this produces extra overhead (performance, maintenance, security and administrative) for the Exchange server, it generally is undesirable. The only proper way (according Microsoft) to interface with the Exchange server from a script or application is to use CDO.

        I've written enough Exchange apps in VB6, VB.NET and vbscript to know that Perl is, unfortunately, ill suited for any real Exchange development. Atleast until someone writes a set of modules that is able to interface with Exchange with CDO on more than superficial terms.

        Jason L. Froebe

        Team Sybase member

        No one has seen what you have seen, and until that happens, we're all going to think that you're nuts. - Jack O'Neil, Stargate SG-1

      Thanks much, but that won't work. It need to be able to run it from a machine that doesn't have Exchange installed on it. I forgot to add that.

      I have pretty much surmised that IMAP won't do the trick alone, but I feel there are other modules that would assist in the task.

      I also really want to do it in Perl . . . I have no desire to do anything in VB.

        Hi

        It need to be able to run it from a machine that doesn't have Exchange installed on it.

        Then you will definitely need the MS Office Developer version installed on your client box. Interfacing with Exchange can be tricky from another machine.

        Since this appears to be your first attempt at Exchange code writing, I would suggest taking a good look at Microsoft's examples... write a test script in vbscript to make sure you do understand and to verify that it works... then do a port to perl. VBScript is just a scripting language.

        Start off with an introduction to Collaboration Data Objects then with Collaboration Data Objects for Exchange.

        hope this gives you a start

        Jason L. Froebe

        Team Sybase member

        No one has seen what you have seen, and until that happens, we're all going to think that you're nuts. - Jack O'Neil, Stargate SG-1