Smart questions
Smart answers
Smart people
INTELLIGENT WORK FORUMS
FOR COMPUTER PROFESSIONALS

Member Login




Remember Me
Forgot Password?
Join Us!

Come Join Us!

Are you a
Computer / IT professional?
Join Tek-Tips now!
  • Talk With Other Members
  • Be Notified Of Responses
    To Your Posts
  • Keyword Search
  • One-Click Access To Your
    Favorite Forums
  • Automated Signatures
    On Your Posts
  • Best Of All, It's Free!

Join Tek-Tips
*Tek-Tips's functionality depends on members receiving e-mail. By joining you are opting in to receive e-mail.

Posting Guidelines

Promoting, selling, recruiting, coursework and thesis posting is forbidden.
Jobs from Indeed

Link To This Forum!

Partner Button
Add Stickiness To Your Site By Linking To This Professionally Managed Technical Forum.
Just copy and paste the
code below into your site.

Any easy way to export many attachments/emails?

sylvite (Programmer) (OP)
25 Jan 09 13:44
Eaach day I receive several emails each of which has a MS Wrod attachment containing important information that I need to archive. I have a few thousand of such emails now that I direct to pre-designated folders when I get them. I could use the Notes archival function to store all of these, yes, but I'd prefer to archive the attachments separately from the Notes system entirely, such as on a hard drive or flash drive.

I haven't come across any easy way to do this, however. I could manually export the attachments but that would take days of effort. Is there any way of exporting/archiving multiple emails or attachments like this at once. By reading Lotus' help content, there appears to none.
pmonett (Programmer)
30 Jan 09 17:49
The Sandbox has several items that can help.

One of them is the Detach Remove and Link agent. Check it out.

Pascal.


I've got nothing to hide, and I'd very much like to keep that away from prying eyes.

sylvite (Programmer) (OP)
13 Feb 09 15:40
Thanks for the suggestion. I downloaded the Detach Remove and Link agent but now, proving that I am not smarter than a Fifth-Grader, I have to ask:  how do I use it ?
pmonett (Programmer)
18 Feb 09 3:17
smile

Given that it is an agent, you need to copy/paste the agent into your mailbox design (with the Designer client), and right-click it to run it.

This agent cannot be scheduled because it requires your input for the destination folder. That means that the agent includes calls to the NotesUIWorkspace, and agents containing such calls cannot be scheduled.

Pascal.


I've got nothing to hide, and I'd very much like to keep that away from prying eyes.

pdupreez (TechnicalUser)
24 Jul 09 7:38
I have also been trying to extract all mail attachments from my Lotus Notes mailbox. I found the code below on perlmonk, and it works fantastically, other than for one small problem.

It only saves the first attachment from the mail, and seemingly ignores the rest. I have looked everywhere to try and find a potential reason for this, and my perl skills are rudimentary.

Somewhere around here the attachments are read into an array?? and then saved one by one by looping through the array. Either the array is not populated properly or it is not properly looping, but I cannot find out which is which

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

Any ideas would be well appreciated.

Thanks (and thanks to the original contributors  Kyle Krom (buckaduck)and Doug Marsh (NateTut) from perlmonk.com


# 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) are
# 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) . '\\Notes2Files';
if(-d $dir)
   {
   print("Directory: $dir already exists.\nPlease choose another directory 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', 'Stationery');

# 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\] subdirectory: $!";
     }

  # 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 \[$subdir/$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'};
  #$attachments = @$array_ref;
  print scalar($array_ref)."<br />";
    foreach my $attachment (@$array_ref) {
    print "Attachment in Message $num: $attachment";
    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;
}  
pmonett (Programmer)
28 Jul 09 9:41
I believe the problem is that the code was not written using the NotesEmbeddedObject property.
The corresponding section of code would have to be rewritten to correct the error.
Maybe there is an update to this code that provides a fix ?

Otherwise, somebody will have to rewrite it.

Pascal.

I've got nothing to hide, and I'd very much like to keep that away from prying eyes.

pdupreez (TechnicalUser)
5 Aug 09 11:29
I have struggled with this and searched all over the net without a solution, but at the end I found a number of scripts and combined to give me a fairly bulletproof perl script that will export each email as a text file, with its attachments into its own folder with a cleaned up subject field as the foldername and text file name.

A tree structure looks then as such:

Default Directory\[View Name In Lotus Notes]\[Cleaned Subject Field]\Cleaned Subject.txt

with also all attachments as originally named within the Lotus mail.

This will handle multiple attachments per email and I have extracted a 5GB mailbox with this containing 16000 mails without a problem. This does not work on selected mails, and only export wholesale from the main mailbox. This is set to save it in the d:\archives directory (which must not exist before you start) and you will have to modify it to suit your purposes. The core of the script comes from www.perlmonk.org, so please visit them if you wish to get the original script. I cannot remember where some of the other pieces come from unfortunately.

# 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\Archived-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) are
# 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 = 'D:\Archives';

# Define a list of "Normal" folders to skip
my @badlist = ('_Archiving', 'Archiving\\Age of Documents',
               'Discussion Threads', 'Events', 'Mail By Sender', 'All by Purge Date', 'Unread\\unread', 'Stationery');

# Auto-print carriage returns
$OUTPUT_RECORD_SEPARATOR = "\n";

# Open the email database in Lotus Notes
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};

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

 my $path = 'D:\Archives';
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 ( $doc->HasEmbedded ) {
  
  # Create a new subdirectory based on the message subject
  my $Cleaned_Subject = $doc->{Subject}->[0];
  
  $Cleaned_Subject =~s/Re\://gi;
  $Cleaned_Subject =~s/Tr\://gi;
  
  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/^Fw\-//i;
  $subdir =~ s/^Tr\-//i;
  $subdir =~ s/^Re\-//i;
  $subdir =~ s/^\-//i;
  $subdir =~ s/\-\-/\-/g;
  $subdir =~ s/\-\-/\-/g;
  $subdir =~ s/\-\-/\-/g;
  $subdir =~ s/^\-//;    
  
  $subdir = substr($subdir, 0, 50);
  
  $Cleaned_Subject = $subdir;
    
  if($subdir eq ')
     {
     $subdir = 'No_Subject';
     }
  
  if(! -d $subdir)
     {
     print "Making subdirectory $subdir";  
     mkdir ($subdir, 0755) or warn "Can't make $path\$subdir directory: $!";
     }
     
      my $DocumentBody = $doc->GetFirstItem('Body');

      foreach my $embeddedDoc ( $DocumentBody->{EmbeddedObjects} ) {
         foreach my $arryele ( @{$embeddedDoc } ) {
           my @array = $arryele->{Source};
           ExtractAttachment($doc, "$path/$subdir", @array);
         }
       }
    }
    
}
  
sub ExtractAttachment {
 my ($doc, $path, $filename) = @_;

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

 #Save the attachment to a file
  my $attachment = $doc->GetAttachment($filename);
  
  if (-e "$path/$attachment") {
  print "File exists!";
  }
  else {
#  print "File does not exist.";

 print "Extracting attachment $path";
 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 '($All)') # or ($name eq '($Sent)')  or ($name !~ /\(.+\)/))
      {
      push(@views, $name); # unless (grep { $name eq $_ } @badlist);
      }
  }

  return @views;
}

# END OF SCRIPT

#############################################################################

I have also modified the code slightly to allow me to export all attachments to a single directory by adding a sequential counter to the filename, therefore preventing overwriting of files with the same name.

It would probably be better to add the counter as a suffix rather than a prefix as it will allow for better sorting and filtering of similarly named files, but that would require parsing and concatenating of the filename before saving, and I am still struggling to understand regular expressions.

Somebody else can perhaps help out with that?
#############################################################################

# START OF FLAT EXPORT SCRIPT
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 = 'D:\Archives';
my $Counter = 1;

# Define a list of "Normal" folders to skip
my @badlist = ('_Archiving', 'Archiving\\Age of Documents',
               'Discussion Threads', 'Events', 'Mail By Sender', 'All by Purge Date', 'Unread\\unread', 'Stationery');

# Auto-print carriage returns
$OUTPUT_RECORD_SEPARATOR = "\n";

# Open the email database in Lotus Notes
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};

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

 my $path = 'D:\Archives';
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 ( $doc->HasEmbedded ) {
  
      my $DocumentBody = $doc->GetFirstItem('Body');

      foreach my $embeddedDoc ( $DocumentBody->{EmbeddedObjects} ) {
         foreach my $arryele ( @{$embeddedDoc } ) {
           my @array = $arryele->{Source};
           ExtractAttachment($doc, "$path", @array);
         }
       }
    }
    
}
  
sub ExtractAttachment {
 my ($doc, $path, $filename) = @_;
 
 $Counter = $Counter + 1;
 
 #Get a Windows-friendly pathname for the file
  $path = "$path/$Counter-$filename";
  $path =~ tr/\//\\/;
  
print "Extracting attachment $path";

#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 '($All)') # or ($name eq '($Sent)')  or ($name !~ /\(.+\)/))
      {
      push(@views, $name); # unless (grep { $name eq $_ } @badlist);
      }
  }

  return @views;
}

Reply To This Thread

Posting in the Tek-Tips forums is a member-only feature.

Click Here to join Tek-Tips and talk with other members!

Back To Forum

Close Box

Join Tek-Tips® Today!

Join your peers on the Internet's largest technical computer professional community.
It's easy to join and it's free.

Here's Why Members Love Tek-Tips Forums:

Register now while it's still free!

Already a member? Close this window and log in.

Join Us             Close