perl to move outlook emails to another folder - perl

Hi I have a script that reads thru an email folder and if the subject line starts with 'test' it extracts the mail body to a txt file. I would like it to then move all 6 emails to another folder. but while the script extracts from all 6 emails in the folder, when i add the line ( $message->Move($tofolder); ) i can only get it to move 3 emails at once, not all of them!
I get warning: Use of uninitialized value in pattern match (m//) on ~ /^test /) ..... line
#!/usr/bin/perl
use strict;
use warnings;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft Outlook';
my $filename = 'c:\\net.txt' ;
open(FH,"> $filename")
or die ("cannot open $filename");
my $outlook = Win32::OLE->new('Outlook.Application')
or die "Failed Opening Outlook.";
my $namespace = $outlook->GetNamespace("MAPI");
my $folder = $namespace->Folders("test")->Folders("test1");#->Folders; ("Junk Mail")->Folders("Bad");
my $tofolder = $namespace->Folders("test")->Folders("test1");#->Folders; ("Junk Mail")->Folders("Bad");
my $items = $folder->Items;
for my $itemIndex (1..$items->Count)
{
my $message = $items->item($itemIndex);
if ($message->{Subject} =~ /^test/){
print $message->{Subject}."\n";
print FH $message->{Body};
$message->Move($tofolder);
}
}
close(FH);

I'm afraid I'm not quite sure what's up - from the comments, an error on line 24 suggests that the thing you're accessing as a message doesn't have a 'Subject' field.
So it might actually not be a message at all.
I've tried something a bit like this (paraphrased a little) which seems to work:
#!/usr/bin/perl
use strict;
use warnings;
use Win32::OLE;
use Win32::OLE::Const 'Microsoft Outlook';
my $filename = 'c:\\net.txt';
open( my $output_fh, ">", $filename ) or die $!;
my $outlook = Win32::OLE->new('Outlook.Application')
or die "Failed Opening Outlook.";
my $namespace = $outlook->GetNamespace("MAPI");
my $archive = $namespace->GetDefaultFolder(6)->Folders('Archive');
my $deletedItems = $namespace->GetDefaultFolder(3);
my $items = $archive->Items;
foreach my $msg ( $items->in ) {
if ( $msg->{Subject} =~ m/^test/ ) {
print $msg ->{Subject}, "\n";
print {$output_fh} $msg->{Body};
$msg->Move($deletedItems);
}
}
close($output_fh);
This moves things from 'Archive' subfolder of 'Inbox' to Deleted Items. And extracts to a file as we go. Note that it just splurges 'body' to the output file, without any separators, so you probably want to do something more complicated. (I've taken to using $msg -> SaveAs so I can preserve the whole message object).

Related

Extracting files with Japanese characters from a zip archive

Everything inside the zip file has a Japanese name (e.g. the directories inside, pdfs inside etc.). When I tried using
Archive::Zip
or
Archive::Extract,
it fails at a single point (Input/Output error) while trying to create a directory with a apanese name.
Is there any way to deal with this without having to write my unzipping module?
use warnings;
use POSIX;
use File::Basename;
use File::Copy;
use Sys::Hostname;
use Archive::Extract;
use File::Path;
my $filename = '42108e01b86ed61ed18c29066254b5b9.zip';
my $dest_dir = "test_site/pk";
use Archive::Zip;
my $zip = Archive::Zip->new();
unless ( $zip->read( $filename ) == AZ_OK ) {
die "Error Reading Zip File !";
}
foreach my $m ( $zip->members() ) {
print "Member $m:\n ";
my $err = $zip->extractMemberWithoutPaths( $m, "$dest_dir/" . $m->fileName );
print "Error: $err" if $err;
print $/;
}
Error is:
Input/output error at Archive/Zip/Member.pm line 485.

Zipping file in perl

I have been trying to zip files on remote windows server but not getting success by whatever i tried. Below is the small peice of code. Please tell me where m going wrong. This code is not producing any error but just not generating the zip file.
use strict;
use warnings;
# before running check perl module is installed in your PC.
use Archive::Zip;
use File::Basename 'basename';
my #files = ('D:\Scripts\Testing\abc.txt');
# if it is more than one file add it by using comma as separator
my $zip = Archive::Zip->new;
foreach my $file (#files) {
my $member = basename $file;
printf qq{Adding file "%s" as archive member "%s"\n}, $file, $member;
$zip->addFile( $file, $member );
printf "Member added\n";
}
printf "Writing to zip\n";
$zip->writeToFileNamed('zippedFolders.zip');
#zip file name change it as u want
Could you please:
use Cwd;
use strict;
use warnings;
# before running check perl module is installed in your PC.
use Archive::Zip;
use File::Basename;
my (#files,$dirname,$bsename) = "";
my $inFile = "D:\\Scripts\\Testing\\abc.txt"; # if it is more than one file add it by using comma as separator
my $curdir = getcwd();
#Need to open file here and to be read the file
open(IN, $inFile) || die "Cant \n";
while(<IN>) {
my $sngfile = $_;
chomp($sngfile);
push(#files, $sngfile);
}
my $zip = Archive::Zip->new();
foreach my $file (#files)
{
$dirname = dirname($file);
$bsename = basename($file);
#Check file exist here your code
if($dirname!~m/\.$/) {
print "$dirname\t$bsename\n";
#printf qq{Adding file "%s" as archive member "%s"\n}, $dirname, $bsename;
$zip->addFile("$dirname/$bsename"); }
}
printf "$curdir\\Writing to zip\n";
$zip->writeToFileNamed("$curdir/zippedFolders.zip"); #zip file name change it as u want

Reg: Sending automated mail in perl using Windows

I have a certain script , which will segregate the log file and put the result.txt which is comming as expected. But i want to sent mail after this segregate log file attach it in the text file and sent. There is no error in this script but i need to enhance it. Please help me on how i can use it
#use Win32;
if (#ARGV != 2) {
print "Please pass atleast one paramer\n";
print "Usage:\n\t $0 <file_name><Pattern>\n";
exit;
}
$File_name = $ARGV[0];
$res_File_name = $File_name . "\.result\.txt";
$Pattern = $ARGV[1];
chomp($Pattern);
open(FD,"$File_name") or die ("File '$File_name' could not be open \n");
open(WFD,">$res_File_name") or die("File $res_File_name could not be opened\n");
print "Enter begin match pattern: ";
$bgn = <stdin>;
chomp($bgn);
print $bgn;
print "Enter end match pattern: ";
$en = <stdin>;
chomp($en);
while ($line = <FD>) {
chomp($line);
if ($line =~ /^$bgn/) { #seaching a patter at begining of the string.
print WFD "Begin pattern '$bgn' matched with the line '$line'\n";
}
if ($line =~ /$en$/) { #seaching a patter at end of the string.
print WFD "End pattern '$en' matched with the line '$line'\n";
#exit;
}
print WFD $_ if(/$Pattern/);
# main();
# use constant Service_Name =>'MyServ'
# use constant Service_Desc =>'MyServDesc'
# sub main()
# {
# $opt=shift(# ARGV)||""
# if ($opt =~ /^(-i|--install)$/i)
# {
install _service( Service_Name, Service_Desc)
# }
# elsif ($opt =~ /^(-r|--remove)$/i)
# {
# remove_service(Service_Name);
# }
# elsif ($opt =~ /^(run)$/i)
#}
# here we create a log file wth STDOUT and STDERR
# The log file will be created with extension .log
$log = $cwd . $bn . ".log";
# open(STDOUT, ">> $log") or die "Couldn't open $log for appending: $!\n";
# open(STDERR, ">&STDOUT") or die "Could";
close(FD);
close(WFD);
The standard way to create and send email using Perl is to use the many modules in the Email::* namespace.
For creating simple email, you should use Email::Simple.
use Email::Simple;
my $email = Email::Simple->create(
header => [
From => 'casey#geeknest.com',
To => 'drain#example.com',
Subject => 'Message in a bottle',
],
body => '...',
);
$email->header_set( 'X-Content-Container' => 'bottle/glass' );
For more complex email (i.e. ones with multiple parts, like file attachments or HTML versions) use Email::MIME.
To send an email, use Email::Sender (actually, in most cases, you can probably get away with Email::Sender::Simple)
use Email::Sender::Simple qw(sendmail);
sendmail($email); # The $email we created in the previous example.
Your first "enhancement" should be to add use strict and use warnings to the top of your program, and declare all your variables using my. That should be your first thought when writing any Perl program.
As for sending an email, you don't say what it is you want to send, but I suggest you use the MIME::Lite module.

Perl split a text file into chunks

I have a large txt file made of thousand of articles and I am trying to split it into individual files - one for each of the articles that I'd like to save as article_1, article_2 etc.. Each articles begins by a line containing the word /DOCUMENTS/.
I am totally new to perl and any insight would be so great ! (even advice on good doc websites). Thanks a lot.
So far what I have tried look like:
#!/usr/bin/perl
use warnings;
use strict;
my $id = 0;
my $source = "2010_FTOL_GRbis.txt";
my $destination = "file$id.txt";
open IN, $source or die "can t read $source: $!\n";
while (<IN>)
{
{
open OUT, ">$destination" or die "can t write $destination: $!\n";
if (/DOCUMENTS/)
{
close OUT ;
$id++;
}
}
}
close IN;
Let's say that /DOCUMENTS/ appears by itself on a line. Thus you can make that the record separator.
use English qw<$RS>;
use File::Slurp qw<write_file>;
my $id = 0;
my $source = "2010_FTOL_GRbis.txt";
{ local $RS = "\n/DOCUMENTS/\n";
open my $in, $source or die "can t read $source: $!\n";
while ( <$in> ) {
chomp; # removes the line "\n/DOCUMENTS/\n"
write_file( 'file' . ( ++$id ) . '.txt', $_ );
}
# being scoped by the surrounding brackets (my "local block"),
close $in; # an explicit close is not necessary
}
NOTES:
use English declares the global variable $RS. The "messy name" for it is $/. See perldoc perlvar
A line separator is the default record separator. That is, the standard unit of file reading is a record. Which is only, by default, a "line".
As you will find in the linked documentation, $RS only takes literal strings. So, using the idea that the division between articles was '/DOCUMENTS/' all by itself on a line, I specified newline + '/DOCUMENTS/' + newline. If this is part of a path that occurs somewhere on the line, then that particular value will not work for the record separator.
Did you read Programming Perl? It is the best book for beginning!
I don't understand what you are trying to do. I assume you have text that has articles and want to get all articles in separate files.
use warnings;
use strict;
use autodie qw(:all);
my $id = 0;
my $source = "2010_FTOL_GRbis.txt";
my $destination = "file$id.txt";
open my $IN, '<', $source;
#open first file
open my $OUT, '>', $destination;
while (<$IN>) {
chomp; # kill \n at the end
if ($_ eq '/DOCUMENTS/') { # not sure, am i right here or what you looking for
close OUT;
$id++;
$destination = "file$id.txt";
open my $OUT, '>', $destination;
} else {
print {$OUT} $_, "\n"; # print into file with $id name (as you open above)
}
}
close $IN;

Why does this program fail to copy files?

this morning, my friend and I discussed and wrote the below code. The idea behind this Perl script is to create the directory structure and copy the files to the corresponding directory.
#!/usr/bin/perl
use File::Path;
use File::Copy;
use Path::Class;
use File::Basename qw/dirname/;
my $src = "/Vijay/new.txt";
unless (open(MYFILE, "file1")) {
die ("cannot open input file file1\n");
}
$line = <MYFILE>;
while ($line ne "") {
print ($line);
mkdir_and_copy($src,$line);
$line = <MYFILE>;
}
sub mkdir_and_copy {
my ($from, $to) = #_;
my($directory, $filename) = $to =~ m/(.*\/)(.*)$/;
print("creating dir $directory");
system "mkdir -p $directory";
print("copying file $from to $to");
system "cp -f $from $to";
return;
}
The above piece of code creates the directory structure, but fails to copy the files to the corresponding directory. Could you please let us know, where exactly we are wrong?
Contents of file1:
test/test1/test2/test.txt
Contents of new.txt:
Shell/Test/test1/test1.txt
Shell/Test/test2/test2.txt
Shell/Test/test3/test3.txt
Output:
> ./mypgm.pl
test/test1/test2/test.txt
creating dir test/test1/test2/copying file /Vijay/new.txt to test/test1/test2/test.txt
cp: cannot access /Vijay/new.txt: No such file or directory
>
The directory Vijay has the file new.txt with the above mentioned content.
Thanks in advance,
Vijay
Hello everyone,
I just modified my code. Please refer the below section of code.
#!/usr/bin/perl
use File::Path;
use File::Copy;
use File::Basename qw/dirname/;
my $src = "./Vijay/new.txt";
unless (open(MYFILE, "file1"))
{
die ("cannot open input file file1\n");
}
$line = ;
while ($line ne "")
{
print ($line); print("\n");
mkdir_and_copy($src,$line);
$line = ""; }
sub mkdir_and_copy
{
my ($from, $to) = #_;
my($directory, $filename) = $to =~ m/(.\/)(.)$/;
$temp = $directory.$filename;
print("Creating dirrectory $directory \n");
if(! -d $directory)
{
mkpath($directory) #or die "Failed to create path";
}
printf("From: $from \n");
printf("To: $temp \n");
copy($from,$temp) or die "Failed to Copy";
return;
}
Now, it creates the exact directory structure and copies the file to the corresponding directory. Could you please tell me that, whether the above code is a proper one?
Your goal is not clear to me, but perhaps this will help you solve the problem:
# Perl scripts should always include this.
# Your original script was generating some useful warnings.
use strict;
use warnings;
my $src = "/Vijay/new.txt";
my $f1 = 'file1';
# This is the recommended way to open a file --
# that is, using a lexical file handle.
open(my $file_handle, '<', $f1) or die "open() failed : $f1 : $!";
# This is the typical way of iterating over the lines in a file.
while (my $line = <$file_handle>){
# You probably want to remove the newline
# before passing the line to mkdir_and_copy()
chomp $line;
mkdir_and_copy($src, $line);
}
sub mkdir_and_copy {
my ($from, $to) = #_;
my ($directory, $filename) = $to =~ m/(.*\/)(.*)$/;
# When writing a script that makes system() calls,
# start by simply printing them. After everything
# looks good, convert the print commands to system() calls.
print "system(): mkdir -p $directory", "\n";
print "system(): cp -f $from $to", "\n";
# The return is not needed.
}
When I run the script with the inputs you provided, here's the output:
system(): mkdir -p test/test1/test2/
system(): cp -f /Vijay/new.txt test/test1/test2/test.txt
This can't be your intent. In particular, why are you iterating over file1 when it contains only one line? Perhaps you meant to iterate over new.txt?
The first thing to do if something "does't work" is to catch errors and to look at them. Then to investigate content of variables. In your case the variable $to just contains the file name, so the script copies it into the current working directory, I'd imagine, not into the newly created directory.
HOWEVER, the methods you're using to get your job done are not exactly the best. It would be better to actually use File::Path and File::Copy, and in particular your way of splitting a path into directory and filename at the first slash is anything but general. This sort of thing should be done in libraries, of which Perl has many.
I'll bet your $line variable still has a newline appended to it. The input returned from the filehandle input operator (<MYFILE>) includes the record separator (usually the newline character(s) for your OS). Try this:
$line = <MYFILE>;
chomp($line);