http://qs321.pair.com?node_id=136382
Category: E-Mail Programs
Author/Contact Info Kyle Krom (buckaduck)
Description: This Win32 program extracts all email messages from your Lotus Notes account, and saves the text and all of the attachments to your hard drive.

Some of this code was based on the excellent program getnotes.pl

# This program extracts email messages from a
# Lotus Notes account. 
#
# Email messages will be saved in directories
# named for the mail folder they're stored in.  
# All of these directories will be stored
# under a new top-level directory named
# "C:\temp\mail" by default, but this can be
# overridden with the -d flag.
#
# For each email message, a subdirectory will 
# be created, containing the text and attachments 
# for that message. These subdirectories are 
# currently named by sequential numbers instead of 
# by their subject titles. That's on my TODO list
# to fix; it shouldn't be too hard.
#
# Some folders in the Notes mail database are not
# really mail folders, so I try to skip them.
# Currently I skip all folders whose names are in
# parentheses (except for Inbox), and the folders 
# in the array @badlist. You can customize @badlist
# as necessary.
# 
# By default, Lotus Notes will open the email
# database for the PC's default user. To access
# the email for a different user: open Notes
# and switch to another userid first; then run
# this program while Notes is still open.

use strict;
use English;
use warnings;
use vars qw($opt_d $opt_v);
use Getopt::Std;
use Win32::OLE;

# Command-line options:
# -d dirname    Save everything under the directory "dirname"
# -v            Verbose reporting of progress 
getopt("d");

# Define a directory to store the results
my $dir = $opt_d || 'C:/temp/mail';
mkdir ($dir, 0755) or die "Can't make $dir: $!";

# Define a list of "Normal" folders to skip
my @badlist = ('_Archiving', 'Archiving\\Age of Documents', 
               'Discussion Threads', 'Events');
                
# Auto-print carriage returns
$OUTPUT_RECORD_SEPARATOR = "\n";

# Open the email database in Lotus Notes
# (To use another person's email database, switch to
#  their userid in Notes before running this program)
my $notes = Win32::OLE->new('Notes.NotesSession')
             or die "Can't open Lotus Notes";
my $database = $notes->GetDatabase("","");
$database->OpenMail;

# Verify the server connection
print "Connected to ", $database->{Title}, 
      " on ", $database->{Server} if $opt_v;

# Loop over all of the folders
foreach my $viewname (GetViews($database)) {

  # Get the object for this View
  print "Checking folder $viewname...";
  my $view = $database->GetView($viewname);

  # Create a subdirectory to store the messages in
  $viewname =~ tr/()$//d;
  $viewname =~ s(\\)(.)g;
  my $path = "$dir/$viewname";
  mkdir ($path, 0755) 
      or die "Can't make directory $path: $!";
  chdir ($path);

  # Get the first document in the folder
  my $num = 1;
  my $doc = $view->GetFirstDocument;
  next unless $doc;
  GetInfo($num, $path, $doc);

  # Get the remaining documents in the folder
  while ($doc = $view->GetNextDocument($doc)) {
    $num++;
    GetInfo($num, $path, $doc);
  }
}

sub GetInfo {
  my ($num, $path, $doc) = @_;

  print "Processing message $num" if $opt_v;

  # Create a new subdirectory based on the message number
  my $subdir = sprintf("%02d",$num);
  mkdir ($subdir, 0755)
     or die "Can't make $subdir subdirectory: $!";

  # Write the contents of the message to a file
  open (TEXTFILE, ">$subdir/message.txt")
     or die "Can't create $subdir message file: $!";
  print TEXTFILE "From: ", $doc->{From}->[0];
  print TEXTFILE "Subject: ", $doc->{Subject}->[0];
  print TEXTFILE $doc->{Body};
  close TEXTFILE;

  # Save attachments as files, if any
  my $array_ref = $doc->{'$FILE'};
  foreach my $attachment (@$array_ref) {
    if ($attachment) {
      ExtractAttachment($doc, "$path/$subdir", $attachment);     
    }
  }
}

sub ExtractAttachment {
  my ($doc, $path, $filename) = @_;

  print "Extracting attachment $filename" if $opt_v;

  # Get a Windows-friendly pathname for the file
  $path = "$path/$filename";
  $path =~ tr/\//\\/;

  # Save the attachment to a file
  my $attachment = $doc->GetAttachment($filename);
  $attachment->ExtractFile($path);
}  

sub GetViews {
  my ($database) = @_;
  my @views = ();

  # Loop through all of the views in this database
  my $array_ref = $database->{Views};
  foreach my $view (@$array_ref) {
    my $name = $view->{Name};
    
    # We only want folders if it's the Inbox
    # or a normal folder name with no parentheses
    if (($name eq '($Inbox)') or ($name !~ /\(.+\)/)) {

      # Add the folder name to the @views list
      # if it's not in the @badlist
      push(@views, $name) unless (grep { $name eq $_ } @badlist);
    }
  }

  return @views;
}
Replies are listed 'Best First'.
Re: Store Lotus Notes Email
by NateTut (Deacon) on Dec 10, 2004 at 00:53 UTC
    Thanks to buckaduck for this lifesaver of a script. Our Notes setup here automagically deletes messages over 90 days weekly. Now I can save them off in a usuable & portable format.

    I have made some modest changes to the script.

    UPDATE: The script now saves messages with the same or related (FW & RE) to the same directory.

    Here is my version:
    # This program extracts email messages from a # Lotus Notes account. # # Email messages will be saved in directories # named for the mail folder they're stored in. # All of these directories will be stored # under a new top-level directory named # "C:\temp\mail" by default, but this can be # overridden with the -d flag. # # For each email message, a subdirectory will # be created, containing the text and attachments # for that message. These subdirectories are # currently named by sequential numbers instead of # by their subject titles. That's on my TODO list # to fix; it shouldn't be too hard. # # Some folders in the Notes mail database are not # really mail folders, so I try to skip them. # Currently I skip all folders whose names are in # parentheses (except for Inbox), and the folders # in the array @badlist. You can customize @badlist # as necessary. # # By default, Lotus Notes will open the email # database for the PC's default user. To access # the email for a different user: open Notes # and switch to another userid first; then run # this program while Notes is still open. # # Original by Kyle Krom (buckaduck) # # Tweaked by Doug Marsh (NateTut) # # Added Default Directory of "My Documents\Notes2Files" # Added 'All by Purge Date', 'Stationery' to the @badlist # Added an Exception for (Sent) # Remove extraneous LFs from message.txt # Message Directories are now named for $Subject # Multiple Messages with the same or Related Subjects (i.e. FW & RE) a +re # now stored to the same folder. # Tweaked some prints # use strict; use English; use warnings; use vars qw($opt_d $opt_v); use charnames ':full'; use Getopt::Std; use Win32::OLE; use Win32; # Command-line options: # -d dirname Save everything under the directory "dirname" # -v Verbose reporting of progress getopt("d"); # Define a directory to store the results my $dir = $opt_d || Win32::GetFolderPath(Win32::CSIDL_PERSONAL) . '\\N +otes2Files'; if(-d $dir) { print("Directory: $dir already exists.\nPlease choose another direc +tory or remove $dir.\n"); exit(1); } mkdir ($dir, 0755) or die "Can't make $dir: $!"; print("Saving Lotus Notes Mail in: $dir\\\n"); # Define a list of "Normal" folders to skip my @badlist = ('_Archiving', 'Archiving\\Age of Documents', 'Discussion Threads', 'Events', 'All by Purge Date', 'S +tationery'); # Auto-print carriage returns $OUTPUT_RECORD_SEPARATOR = "\n"; # Open the email database in Lotus Notes # (To use another person's email database, switch to # their userid in Notes before running this program) my $notes = Win32::OLE->new('Notes.NotesSession') or die "Can't open Lotus Notes"; my $database = $notes->GetDatabase("",""); $database->OpenMail; # Verify the server connection print "Connected to ", $database->{Title}, " on ", $database->{Server} if $opt_v; # Loop over all of the folders foreach my $viewname (GetViews($database)) { # Get the object for this View print "Saving Messages in folder $viewname..."; my $view = $database->GetView($viewname); # Create a subdirectory to store the messages in $viewname =~ tr/()$//d; $viewname =~ s(\\)(.)g; my $path = "$dir/$viewname"; mkdir ($path, 0755) or die "Can't make directory $path: $!"; chdir ($path); # Get the first document in the folder my $num = 1; my $doc = $view->GetFirstDocument; next unless $doc; GetInfo($num, $path, $doc); # Get the remaining documents in the folder while ($doc = $view->GetNextDocument($doc)) { $num++; GetInfo($num, $path, $doc); } } sub GetInfo { my ($num, $path, $doc) = @_; print "Processing message $num" if $opt_v; # Create a new subdirectory based on the message number my $Cleaned_Subject = $doc->{Subject}->[0]; while($Cleaned_Subject =~ s/[^A-z0-9\$%'`\-\@{}~!#()&_^ ]/\-/g) { ; } $Cleaned_Subject =~ s/^\s*//; $Cleaned_Subject =~ s/\s*$//; $Cleaned_Subject =~ s/\\//; $Cleaned_Subject =~ s/\s+/\-/g; my $subdir = $Cleaned_Subject; $subdir =~ s/^RE\-//i; $subdir =~ s/^FW\-//i; $subdir =~ s/^\-//i; if($subdir eq '') { $subdir = 'No_Subject'; } if(! -d $subdir) { mkdir ($subdir, 0755) or warn "Can't make \[$subdir\] subdirector +y: $!"; } # Write the contents of the message to a file my $FileName = sprintf("%04d_Message.txt", $num); open (TEXTFILE, ">$subdir/$FileName") or warn "Can't create \[$subdi +r/$FileName\] file: $!"; print TEXTFILE "From: ", $doc->{From}->[0]; print TEXTFILE "Subject: ", $doc->{Subject}->[0]; my $NewBody = $doc->{Body}; $NewBody =~ s/\x0D\n/\n/g; print TEXTFILE $NewBody; close TEXTFILE; # Save attachments as files, if any my $array_ref = $doc->{'$FILE'}; foreach my $attachment (@$array_ref) { if ($attachment) { ExtractAttachment($doc, "$path/$subdir", $attachment); } } } sub ExtractAttachment { my ($doc, $path, $filename) = @_; print "Extracting attachment $filename" if $opt_v; # Get a Windows-friendly pathname for the file $path = "$path/$filename"; $path =~ tr/\//\\/; # Save the attachment to a file my $attachment = $doc->GetAttachment($filename); eval { $attachment->ExtractFile($path) }; if($?) { print("Error Saving Attachment:$filename:$?:$!:$@:$^E\n"); } } sub GetViews { my ($database) = @_; my @views = (); # Loop through all of the views in this database my $array_ref = $database->{Views}; foreach my $view (@$array_ref) { my $name = $view->{Name}; # We only want folders if it's the Inbox or Sent # or a normal folder name with no parentheses if (($name eq '($Inbox)') or ($name eq '($Sent)') or ($name !~ /\( +.+\)/)) { # Add the folder name to the @views list # if it's not in the @badlist push(@views, $name) unless (grep { $name eq $_ } @badlist); } } return @views; }


    Doug
      These are some awesome improvements! I'm glad we could help each other.

      buckaduck

        The Attachments seemed not to be saving off... I get no message warnings using the newer code... but when I print that ExtractFile message anyways it says something about: No such file or directory. I tried hard coding the path and it still doesn't save off the attachments. Any ideas?
Re: Store Lotus Notes Email
by Anonymous Monk on Sep 25, 2003 at 16:28 UTC
    Source Code? What do i do with it?! I need to store or convert all of my Lotus Notes (R5) email so I can read it in Outlook or otherwise text. If this will do it -- what do I do with this code? Please help!
      To use this program as written you need a PC with Perl and Lotus Notes installed, and it should already be configured so that you are able to login to Lotus Notes and read your mail.

      You don't need to compile the source code, or anything like that. Just save this code to a file (e.g. "get_mail.pl") and run it from a Windows command prompt: perl get_mail.pl . Some command line options are described in the source code comments.

      If Lotus Notes isn't already running, it will launch automatically.

      buckaduck

        Can I store emails in html version?
        Hello to all of you, I'm trying to extract my notes messages to txt files before migrating to outlook. However,Perl is not installed on my machine. I would like to know if there's a solution for people like me who only have Lotus on their desktop.
      Export the email and save it as a *.eml - that should save it into a format that can be opened in Outlook.
      Does this work on LN .nsf files?