| 14 | 
           rodolico | 
           1 | 
           #! /usr/bin/perl -w
  | 
        
        
            | 
            | 
           2 | 
              | 
        
        
            | 
            | 
           3 | 
           #    archiveIMAP: moves old messages from one IMAP account to another
  | 
        
        
            | 
            | 
           4 | 
           #    maintaining hierarchy.
  | 
        
        
            | 
            | 
           5 | 
           #    see http://wiki.linuxservertech.com for additional information
  | 
        
        
            | 
            | 
           6 | 
           #    Copyright (C) 2014  R. W. Rodolico
  | 
        
        
            | 
            | 
           7 | 
           #
  | 
        
        
            | 
            | 
           8 | 
           #    version 1.0, 20140818
  | 
        
        
            | 
            | 
           9 | 
           #       Initial Release
  | 
        
        
            | 
            | 
           10 | 
           #
  | 
        
        
            | 
            | 
           11 | 
           #    version 1.0.1 20140819
  | 
        
        
            | 
            | 
           12 | 
           #        Removed dependancy on Email::Simple
  | 
        
        
            | 
            | 
           13 | 
           #        Allowed 'separator' as an element in either source or target
  | 
        
        
            | 
            | 
           14 | 
           #
  | 
        
        
            | 
            | 
           15 | 
           #    This program is free software: you can redistribute it and/or modify
  | 
        
        
            | 
            | 
           16 | 
           #    it under the terms of the GNU General Public License as published by
  | 
        
        
            | 
            | 
           17 | 
           #    the Free Software Foundation, either version 3 of the License, or
  | 
        
        
            | 
            | 
           18 | 
           #    (at your option) any later version.
  | 
        
        
            | 
            | 
           19 | 
           #
  | 
        
        
            | 
            | 
           20 | 
           #    This program is distributed in the hope that it will be useful,
  | 
        
        
            | 
            | 
           21 | 
           #    but WITHOUT ANY WARRANTY; without even the implied warranty of
  | 
        
        
            | 
            | 
           22 | 
           #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  | 
        
        
            | 
            | 
           23 | 
           #    GNU General Public License for more details.
  | 
        
        
            | 
            | 
           24 | 
           #
  | 
        
        
            | 
            | 
           25 | 
           #    You should have received a copy of the GNU General Public License
  | 
        
        
            | 
            | 
           26 | 
           #    along with this program.  If not, see <http://www.gnu.org/licenses/>.
  | 
        
        
            | 
            | 
           27 | 
              | 
        
        
            | 
            | 
           28 | 
           use strict;
  | 
        
        
            | 
            | 
           29 | 
           use warnings;
  | 
        
        
            | 
            | 
           30 | 
           use Net::IMAP::Simple; # libnet-imap-simple-ssl-perl
  | 
        
        
            | 
            | 
           31 | 
           use POSIX; # to get floor and ceil
  | 
        
        
            | 
            | 
           32 | 
           #use Data::Dumper;
  | 
        
        
            | 
            | 
           33 | 
              | 
        
        
            | 
            | 
           34 | 
           # globals
  | 
        
        
            | 
            | 
           35 | 
           my $CONFIG_FILE_NAME = 'archiveIMAP.cfg';
  | 
        
        
            | 
            | 
           36 | 
           my $server = 'localhost'; # used if not specified in definition
  | 
        
        
            | 
            | 
           37 | 
           # Following are added to ignore in definition in account (%accounts)
  | 
        
        
            | 
            | 
           38 | 
           my @ignore = ( 'Deleted Messages','Drafts','Junk E-mail','Junk','Trash' );
  | 
        
        
            | 
            | 
           39 | 
           # these are folders we may want to copy, but we never want to delete
  | 
        
        
            | 
            | 
           40 | 
           my @systemFolders = ('Outbox','Sent Items','INBOX','Inbox');
  | 
        
        
            | 
            | 
           41 | 
           my $deleteEmptyFolders = 1;
  | 
        
        
            | 
            | 
           42 | 
           my $deleteOnSuccess = 1;
  | 
        
        
            | 
            | 
           43 | 
           my %accounts;  # this must be configured in archiveIMAP.cfg. See sample.
  | 
        
        
            | 
            | 
           44 | 
              | 
        
        
            | 
            | 
           45 | 
           #
  | 
        
        
            | 
            | 
           46 | 
           # find where the script is actually located as cfg should be there
  | 
        
        
            | 
            | 
           47 | 
           #
  | 
        
        
            | 
            | 
           48 | 
           sub getScriptLocation {
  | 
        
        
            | 
            | 
           49 | 
              use strict;
  | 
        
        
            | 
            | 
           50 | 
              use File::Spec::Functions qw(rel2abs);
  | 
        
        
            | 
            | 
           51 | 
              use File::Basename;
  | 
        
        
            | 
            | 
           52 | 
              return dirname(rel2abs($0));
  | 
        
        
            | 
            | 
           53 | 
           }
  | 
        
        
            | 
            | 
           54 | 
              | 
        
        
            | 
            | 
           55 | 
           #
  | 
        
        
            | 
            | 
           56 | 
           # Read the configuration file from current location 
  | 
        
        
            | 
            | 
           57 | 
           # and return it as a string
  | 
        
        
            | 
            | 
           58 | 
           #
  | 
        
        
            | 
            | 
           59 | 
           sub readConfig {
  | 
        
        
            | 
            | 
           60 | 
              my $scriptLocation = &getScriptLocation();
  | 
        
        
            | 
            | 
           61 | 
              my $return = '';
  | 
        
        
            | 
            | 
           62 | 
              if ( -e "$scriptLocation/$CONFIG_FILE_NAME" ) {
  | 
        
        
            | 
            | 
           63 | 
                 open CFG,"<$scriptLocation/$CONFIG_FILE_NAME" or die "Could not read $scriptLocation/$CONFIG_FILE_NAME: $!\n";
  | 
        
        
            | 
            | 
           64 | 
                 $return = join ( '', <CFG> );
  | 
        
        
            | 
            | 
           65 | 
                 close CFG;
  | 
        
        
            | 
            | 
           66 | 
              }
  | 
        
        
            | 
            | 
           67 | 
              return $return;
  | 
        
        
            | 
            | 
           68 | 
           }
  | 
        
        
            | 
            | 
           69 | 
              | 
        
        
            | 
            | 
           70 | 
           #
  | 
        
        
            | 
            | 
           71 | 
           # Open an IMAP connection
  | 
        
        
            | 
            | 
           72 | 
           #
  | 
        
        
            | 
            | 
           73 | 
           sub openIMAPConnection {
  | 
        
        
            | 
            | 
           74 | 
              my ( $server, $username, $password ) = @_;
  | 
        
        
            | 
            | 
           75 | 
              my $imap = Net::IMAP::Simple->new( $server ) ||
  | 
        
        
            | 
            | 
           76 | 
               die "Unable to connect to IMAP: $Net::IMAP::Simple::errstr\n";
  | 
        
        
            | 
            | 
           77 | 
              # Log on
  | 
        
        
            | 
            | 
           78 | 
              if(!$imap->login( $username, $password )){
  | 
        
        
            | 
            | 
           79 | 
                die "Login failed: " . $imap->errstr . "\n";
  | 
        
        
            | 
            | 
           80 | 
              }
  | 
        
        
            | 
            | 
           81 | 
              return $imap;
  | 
        
        
            | 
            | 
           82 | 
           }
  | 
        
        
            | 
            | 
           83 | 
              | 
        
        
            | 
            | 
           84 | 
           #
  | 
        
        
            | 
            | 
           85 | 
           # returns a string in proper format for RFC which is $age days ago
  | 
        
        
            | 
            | 
           86 | 
           #
  | 
        
        
            | 
            | 
           87 | 
           sub getDate {
  | 
        
        
            | 
            | 
           88 | 
              my $age = shift;
  | 
        
        
            | 
            | 
           89 | 
              my @months = ('Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec');
  | 
        
        
            | 
            | 
           90 | 
              my @now = localtime(time - 24 * 60 * 60 * $age);
  | 
        
        
            | 
            | 
           91 | 
              $now[4] = @months[$now[4]];
  | 
        
        
            | 
            | 
           92 | 
              $now[5] += 1900;
  | 
        
        
            | 
            | 
           93 | 
              my $date = sprintf( "%d-%s-%d", $now[3],$now[4],$now[5] ) ; # '1-Jan-2014';
  | 
        
        
            | 
            | 
           94 | 
              return $date;
  | 
        
        
            | 
            | 
           95 | 
           }
  | 
        
        
            | 
            | 
           96 | 
              | 
        
        
            | 
            | 
           97 | 
           #
  | 
        
        
            | 
            | 
           98 | 
           # Get a list of all folders to be processed
  | 
        
        
            | 
            | 
           99 | 
           # currently, it just weeds out items in the ignore list
  | 
        
        
            | 
            | 
           100 | 
           #
  | 
        
        
            | 
            | 
           101 | 
           sub getFolders {
  | 
        
        
            | 
            | 
           102 | 
              my ($imap, $ignore, $separator) = @_;
  | 
        
        
            | 
            | 
           103 | 
              $separator = '\\' . $separator;
  | 
        
        
            | 
            | 
           104 | 
              # build a regex that will be used to filter the input
  | 
        
        
            | 
            | 
           105 | 
              # assuming Trash, Drafts and Junk are in the ignore list
  | 
        
        
            | 
            | 
           106 | 
              # and a period is the separator, the generated regex is
  | 
        
        
            | 
            | 
           107 | 
              # (^|(\.))((Trash)|(Drafts)|(Junk))((\.)|$)
  | 
        
        
            | 
            | 
           108 | 
              # which basically says ignore those folders, but not substrings of them
  | 
        
        
            | 
            | 
           109 | 
              # ie, Junk02 would not be filtered but Junk would
  | 
        
        
            | 
            | 
           110 | 
              my $ignoreRegex = "(^|($separator))((" . join( ")\|(", @$ignore ) . "))(($separator)|\$)";
  | 
        
        
            | 
            | 
           111 | 
              # read all mailboxes and filter them with above regex into @boxes
  | 
        
        
            | 
            | 
           112 | 
              my @boxes = grep{ ! /$ignoreRegex/ } $imap->mailboxes;
  | 
        
        
            | 
            | 
           113 | 
              return \@boxes;
  | 
        
        
            | 
            | 
           114 | 
           }
  | 
        
        
            | 
            | 
           115 | 
              | 
        
        
            | 
            | 
           116 | 
           #
  | 
        
        
            | 
            | 
           117 | 
           # make a folder on the IMAP account. The folder is assumed to be the
  | 
        
        
            | 
            | 
           118 | 
           # fully qualified path with the correct delimiters
  | 
        
        
            | 
            | 
           119 | 
           #
  | 
        
        
            | 
            | 
           120 | 
           sub makeFolder {
  | 
        
        
            | 
            | 
           121 | 
              my ($imap, $folder, $delimiter) = @_;
  | 
        
        
            | 
            | 
           122 | 
              | 
        
        
            | 
            | 
           123 | 
              print "\n\t\tCreating folder $folder";
  | 
        
        
            | 
            | 
           124 | 
              # you must create the parent folder before creating the children
  | 
        
        
            | 
            | 
           125 | 
              my $escapedDelimiter = '\\' . $delimiter;
  | 
        
        
            | 
            | 
           126 | 
              my @folders = split( $escapedDelimiter, $folder );
  | 
        
        
            | 
            | 
           127 | 
              $folder = '';
  | 
        
        
            | 
            | 
           128 | 
              # take them from the left and, if they don't exist, create it
  | 
        
        
            | 
            | 
           129 | 
              while ( my $subdir = shift @folders ) {
  | 
        
        
            | 
            | 
           130 | 
                 $folder .= $delimiter if $folder;
  | 
        
        
            | 
            | 
           131 | 
                 $folder .= $subdir;
  | 
        
        
            | 
            | 
           132 | 
                 next if $imap->select( $folder ); # already created, so look deeper in hierachy
  | 
        
        
            | 
            | 
           133 | 
                 print "\n\t\t\tCreating subfolder $folder";
  | 
        
        
            | 
            | 
           134 | 
                 $imap->create_mailbox( $folder ) || warn $imap->errstr();
  | 
        
        
            | 
            | 
           135 | 
                 $imap->folder_subscribe( $folder ) || die $imap->errstr();
  | 
        
        
            | 
            | 
           136 | 
                 unless ( $imap->select( $folder ) ) { # verify it was created
  | 
        
        
            | 
            | 
           137 | 
                    warn "Unable to create $folder on target account\n";
  | 
        
        
            | 
            | 
           138 | 
                    return 0;
  | 
        
        
            | 
            | 
           139 | 
                 } # unless
  | 
        
        
            | 
            | 
           140 | 
              } # while
  | 
        
        
            | 
            | 
           141 | 
              return $folder;
  | 
        
        
            | 
            | 
           142 | 
           }
  | 
        
        
            | 
            | 
           143 | 
              | 
        
        
            | 
            | 
           144 | 
           #
  | 
        
        
            | 
            | 
           145 | 
           # Delete an IMAP folder
  | 
        
        
            | 
            | 
           146 | 
           #
  | 
        
        
            | 
            | 
           147 | 
           sub deleteAFolder {
  | 
        
        
            | 
            | 
           148 | 
              my ($sourceAccount, $folder, $separator, $systemFolders) = @_;
  | 
        
        
            | 
            | 
           149 | 
              return 1 if $folder eq 'INBOX'; # do NOT mess with INBOX
  | 
        
        
            | 
            | 
           150 | 
              return 2 if $sourceAccount->select($folder) > 0; # do not mess with it if it still has messages in it
  | 
        
        
            | 
            | 
           151 | 
              return 3 if $sourceAccount->mailboxes( $folder . $separator . '*' ); # do not mess with it if it has subfolders
  | 
        
        
            | 
            | 
           152 | 
              return 4 if ( ref ( $systemFolders ) eq 'ARRAY' ) && ( grep{$_ eq $folder} @$systemFolders );
  | 
        
        
            | 
            | 
           153 | 
              print "\n\t\tDeleting empty folder $folder";
  | 
        
        
            | 
            | 
           154 | 
              $sourceAccount->folder_unsubscribe($folder);
  | 
        
        
            | 
            | 
           155 | 
              $sourceAccount->delete_mailbox( $folder );
  | 
        
        
            | 
            | 
           156 | 
           }
  | 
        
        
            | 
            | 
           157 | 
              | 
        
        
            | 
            | 
           158 | 
           #
  | 
        
        
            | 
            | 
           159 | 
           # If folder has messages that match the criteria, move them to target
  | 
        
        
            | 
            | 
           160 | 
           # creates the target folder if necessary
  | 
        
        
            | 
            | 
           161 | 
           #
  | 
        
        
            | 
            | 
           162 | 
           sub processFolder {
  | 
        
        
            | 
            | 
           163 | 
              my ( $sourceAccount, $targetAccount, $folder, $dateBefore, $sourceDelimiter, $targetDelimiter, $deleteOnSuccess ) = @_;
  | 
        
        
            | 
            | 
           164 | 
              my $numMessages = 0;
  | 
        
        
            | 
            | 
           165 | 
              $sourceAccount->expunge_mailbox( $folder ); # clean it up so we don't copy deleted messages
  | 
        
        
            | 
            | 
           166 | 
              $sourceAccount->select( $folder ) or die "Could not connect to folder $folder\n"; # move into the correct folder for the source
  | 
        
        
            | 
            | 
           167 | 
              my @ids = $sourceAccount->search_sent_before( $dateBefore ); # use sent_before to get the sent date from message
  | 
        
        
            | 
            | 
           168 | 
           #   print join( "\n\t\t\t", @ids ) . "\n";
  | 
        
        
            | 
            | 
           169 | 
              return 0 unless @ids; # we have nothing to copy, so exit
  | 
        
        
            | 
            | 
           170 | 
              if ( $sourceDelimiter ne $targetDelimiter ) { # different delimiters, so we have to change them in the folder def
  | 
        
        
            | 
            | 
           171 | 
                 # they may contain meta chars, so escape them. We can use \Q \E in the pattern to match, but the 
  | 
        
        
            | 
            | 
           172 | 
                 # second part of the s/// will substitute literal EXCEPT for the delimiter and the dollar sign
  | 
        
        
            | 
            | 
           173 | 
                 # I'm escaping the double quote (what I'm using for the delimiter) "just in case" but I'm not doing
  | 
        
        
            | 
            | 
           174 | 
                 # the dollar sign, so this will fail, fail, fail if there is an issue there.
  | 
        
        
            | 
            | 
           175 | 
                 my $escapedTargetDelimiter = $targetDelimiter eq '"' ? '\\' .  $targetDelimiter : $targetDelimiter;
  | 
        
        
            | 
            | 
           176 | 
                 $folder =~ s"\Q$sourceDelimiter\E"$escapedTargetDelimiter"g;
  | 
        
        
            | 
            | 
           177 | 
              }
  | 
        
        
            | 
            | 
           178 | 
              if ( $targetAccount->select( $folder ) || &makeFolder( $targetAccount, $folder, $targetDelimiter ) ) {
  | 
        
        
            | 
            | 
           179 | 
                 foreach my $id ( @ids ) {
  | 
        
        
            | 
            | 
           180 | 
                    my @flags = $sourceAccount->msg_flags( $id );
  | 
        
        
            | 
            | 
           181 | 
                    my $message = $sourceAccount->get( $id ) or die $sourceAccount->errstr;
  | 
        
        
            | 
            | 
           182 | 
                    if ( $targetAccount->put( $folder, $message, @flags ) ) {
  | 
        
        
            | 
            | 
           183 | 
                       $sourceAccount->delete( $id ) if ( $deleteOnSuccess ) ;
  | 
        
        
            | 
            | 
           184 | 
                       $numMessages++;
  | 
        
        
            | 
            | 
           185 | 
                    } else {
  | 
        
        
            | 
            | 
           186 | 
                       die "Could not write to target, aborting\n$targetAccount->errstr\n";
  | 
        
        
            | 
            | 
           187 | 
                    }
  | 
        
        
            | 
            | 
           188 | 
                 }
  | 
        
        
            | 
            | 
           189 | 
              } else {
  | 
        
        
            | 
            | 
           190 | 
                 warn "\t\t$folder not found in target and could not create it\n";
  | 
        
        
            | 
            | 
           191 | 
              }
  | 
        
        
            | 
            | 
           192 | 
              return $numMessages;
  | 
        
        
            | 
            | 
           193 | 
           }
  | 
        
        
            | 
            | 
           194 | 
              | 
        
        
            | 
            | 
           195 | 
           #
  | 
        
        
            | 
            | 
           196 | 
           # main processing loop to handle one account
  | 
        
        
            | 
            | 
           197 | 
           #
  | 
        
        
            | 
            | 
           198 | 
           sub processAccount {
  | 
        
        
            | 
            | 
           199 | 
              my ( $source, $target, $age, $ignore, $deleteOnSuccess, $deleteEmptyFolders ) = @_;
  | 
        
        
            | 
            | 
           200 | 
              | 
        
        
            | 
            | 
           201 | 
              my $date = getDate( $age );
  | 
        
        
            | 
            | 
           202 | 
              print "\t" . ( $deleteOnSuccess ? 'Moving' : 'Copying' ) . " all messages before $date\n";
  | 
        
        
            | 
            | 
           203 | 
              | 
        
        
            | 
            | 
           204 | 
              # open and log into both source and target, and get the separator used
  | 
        
        
            | 
            | 
           205 | 
              my $sourceAccount = &openIMAPConnection( $$source{'server'}, $$source{'username'}, $$source{'password'} );
  | 
        
        
            | 
            | 
           206 | 
              my $targetAccount = &openIMAPConnection( $$target{'server'}, $$target{'username'}, $$target{'password'} );
  | 
        
        
            | 
            | 
           207 | 
              $$source{'separator'} = $sourceAccount->separator unless $$source{'separator'};
  | 
        
        
            | 
            | 
           208 | 
              $$target{'separator'} = $targetAccount->separator unless $$target{'separator'};
  | 
        
        
            | 
            | 
           209 | 
              | 
        
        
            | 
            | 
           210 | 
              # get a list of all folders to be processed on the source
  | 
        
        
            | 
            | 
           211 | 
              $$source{'folders'} = &getFolders( $sourceAccount, $ignore, $$source{'separator'} );
  | 
        
        
            | 
            | 
           212 | 
              #print Dumper( $targetAccount );
  | 
        
        
            | 
            | 
           213 | 
              #die;
  | 
        
        
            | 
            | 
           214 | 
              my $folderList = $$source{'folders'};
  | 
        
        
            | 
            | 
           215 | 
              my $count = 0; # count the number of messages processed
  | 
        
        
            | 
            | 
           216 | 
              my $processedCount = 0; # count the number of folders processed
  | 
        
        
            | 
            | 
           217 | 
              foreach my $folder ( @$folderList ) {
  | 
        
        
            | 
            | 
           218 | 
                 print "\t$folder";
  | 
        
        
            | 
            | 
           219 | 
                 my $messages = &processFolder( $sourceAccount, $targetAccount, $folder, $date, $$source{'separator'}, $$target{'separator'}, $deleteOnSuccess );
  | 
        
        
            | 
            | 
           220 | 
                 $sourceAccount->expunge_mailbox( $folder );
  | 
        
        
            | 
            | 
           221 | 
                 # delete folder if empty and client has requested it.
  | 
        
        
            | 
            | 
           222 | 
                 &deleteAFolder( $sourceAccount, $folder, $$source{'separator'}, $$source{'systemfolder'} ) if ( $deleteEmptyFolders );
  | 
        
        
            | 
            | 
           223 | 
                 print "\n\t\t$messages processed\n";
  | 
        
        
            | 
            | 
           224 | 
                 $count += $messages;
  | 
        
        
            | 
            | 
           225 | 
                 $processedCount++;
  | 
        
        
            | 
            | 
           226 | 
                 # next line used only for testing. Dies after 5 folders on first account
  | 
        
        
            | 
            | 
           227 | 
                 # last if $processedCount > 5;
  | 
        
        
            | 
            | 
           228 | 
              }
  | 
        
        
            | 
            | 
           229 | 
              $sourceAccount->quit;
  | 
        
        
            | 
            | 
           230 | 
              $targetAccount->quit;
  | 
        
        
            | 
            | 
           231 | 
              return $count;
  | 
        
        
            | 
            | 
           232 | 
           }
  | 
        
        
            | 
            | 
           233 | 
              | 
        
        
            | 
            | 
           234 | 
           #######################################################################
  | 
        
        
            | 
            | 
           235 | 
           #                   Main                                              #
  | 
        
        
            | 
            | 
           236 | 
           #######################################################################
  | 
        
        
            | 
            | 
           237 | 
              | 
        
        
            | 
            | 
           238 | 
           # read and evaluate configuration file
  | 
        
        
            | 
            | 
           239 | 
           if ( my $config = readConfig() ) {
  | 
        
        
            | 
            | 
           240 | 
              eval $config; 
  | 
        
        
            | 
            | 
           241 | 
              die "Error in configuraration file $CONFIG_FILE_NAME\n$@" if $@;
  | 
        
        
            | 
            | 
           242 | 
           } else {
  | 
        
        
            | 
            | 
           243 | 
              die "Configurastion file $CONFIG_FILE_NAME must be located in script directory\n";
  | 
        
        
            | 
            | 
           244 | 
           }
  | 
        
        
            | 
            | 
           245 | 
              | 
        
        
            | 
            | 
           246 | 
              | 
        
        
            | 
            | 
           247 | 
           my %processed;
  | 
        
        
            | 
            | 
           248 | 
           $processed{'Accounts'} = 0;
  | 
        
        
            | 
            | 
           249 | 
           $processed{'Messages'} = 0;
  | 
        
        
            | 
            | 
           250 | 
              | 
        
        
            | 
            | 
           251 | 
           foreach my $account ( keys %accounts ) {
  | 
        
        
            | 
            | 
           252 | 
              # talk to user
  | 
        
        
            | 
            | 
           253 | 
              print "Processing account $account\n";
  | 
        
        
            | 
            | 
           254 | 
              # Set some defaults from globals if they were not defined
  | 
        
        
            | 
            | 
           255 | 
              $accounts{$account}{'source'}{'server'} = $server unless exists( $accounts{$account}{'source'}{'server'} );
  | 
        
        
            | 
            | 
           256 | 
              $accounts{$account}{'target'}{'server'} = $server unless exists( $accounts{$account}{'target'}{'server'} );
  | 
        
        
            | 
            | 
           257 | 
              $accounts{$account}{'deleteOnSuccess'} = $deleteOnSuccess unless exists $accounts{$account}{'deleteOnSuccess'};
  | 
        
        
            | 
            | 
           258 | 
              $accounts{$account}{'deleteEmptyFolders'} = $deleteEmptyFolders unless exists $accounts{$account}{'deleteEmptyFolders'};
  | 
        
        
            | 
            | 
           259 | 
              if ( exists $accounts{$account}{'ignore'} ) {
  | 
        
        
            | 
            | 
           260 | 
                 foreach my $element ( @ignore ) {
  | 
        
        
            | 
            | 
           261 | 
                    push $accounts{$account}{'ignore'}, $element;
  | 
        
        
            | 
            | 
           262 | 
                 }
  | 
        
        
            | 
            | 
           263 | 
              } else {
  | 
        
        
            | 
            | 
           264 | 
                 $accounts{$account}{'ignore'} = \@ignore;
  | 
        
        
            | 
            | 
           265 | 
              }
  | 
        
        
            | 
            | 
           266 | 
              | 
        
        
            | 
            | 
           267 | 
              if ( exists $accounts{$account}{'source'}{'systemFolders'} ) {
  | 
        
        
            | 
            | 
           268 | 
                 foreach my $element ( @systemFolders ) {
  | 
        
        
            | 
            | 
           269 | 
                    push $accounts{$account}{'source'}{'systemFolders'}, $element;
  | 
        
        
            | 
            | 
           270 | 
                 }
  | 
        
        
            | 
            | 
           271 | 
              } else {
  | 
        
        
            | 
            | 
           272 | 
                 $accounts{$account}{'source'}{'systemFolders'} = \@systemFolders;
  | 
        
        
            | 
            | 
           273 | 
              }
  | 
        
        
            | 
            | 
           274 | 
              | 
        
        
            | 
            | 
           275 | 
              # do the account
  | 
        
        
            | 
            | 
           276 | 
              $accounts{$account}{'processed'} =
  | 
        
        
            | 
            | 
           277 | 
                       &processAccount( 
  | 
        
        
            | 
            | 
           278 | 
                                $accounts{$account}{'source'},
  | 
        
        
            | 
            | 
           279 | 
                                $accounts{$account}{'target'},
  | 
        
        
            | 
            | 
           280 | 
                                $accounts{$account}{'age'},   
  | 
        
        
            | 
            | 
           281 | 
                                $accounts{$account}{'ignore'},
  | 
        
        
            | 
            | 
           282 | 
                                $accounts{$account}{'deleteOnSuccess'},
  | 
        
        
            | 
            | 
           283 | 
                                $accounts{$account}{'deleteEmptyFolders'}
  | 
        
        
            | 
            | 
           284 | 
                                );
  | 
        
        
            | 
            | 
           285 | 
              print "Done, $accounts{$account}{'processed'} messages copied\n";
  | 
        
        
            | 
            | 
           286 | 
              $processed{'Accounts'}++;
  | 
        
        
            | 
            | 
           287 | 
              $processed{'Messages'} += $accounts{$account}{'processed'};
  | 
        
        
            | 
            | 
           288 | 
              | 
        
        
            | 
            | 
           289 | 
           } # foreach loop
  | 
        
        
            | 
            | 
           290 | 
              | 
        
        
            | 
            | 
           291 | 
           print "$processed{'Accounts'} accounts processed, $processed{'Messages'} messages\n";
  | 
        
        
            | 
            | 
           292 | 
              | 
        
        
            | 
            | 
           293 | 
           1;
  | 
        
        
            | 
            | 
           294 | 
              |