From 09dfa9982d6f058f4b4179d2db0cb32359eb0912 Mon Sep 17 00:00:00 2001 From: Nick Bebout Date: Sun, 24 Apr 2011 16:19:36 -0500 Subject: [PATCH] 1.411 --- CREDITS | 26 +- ChangeLog | 40 +- FAQ | 64 +- .../Changes | 15 + .../MANIFEST | 0 .../META.yml | 2 +- .../Makefile.PL | 0 .../README | 0 .../examples/build_dist.pl | 0 .../examples/build_ldif.pl | 0 .../examples/cleanTest.pl | 0 .../examples/copy_folder.pl | 0 .../examples/cyrus_expire.pl | 0 .../examples/cyrus_expunge.pl | 0 .../examples/find_dup_msgs.pl | 0 .../examples/idle.pl | 0 .../examples/imap_to_mbox.pl | 0 .../examples/imtestExample.pl | 0 .../examples/migrate_mail2.pl | 0 .../examples/migrate_mbox.pl | 0 .../examples/populate_mailbox.pl | 0 .../examples/sharedFolder.pl | 0 .../lib/Mail/IMAPClient.pm | 52 +- .../lib/Mail/IMAPClient.pod | 27 +- .../lib/Mail/IMAPClient/BodyStructure.pm | 0 .../IMAPClient/BodyStructure/Parse.grammar | 0 .../Mail/IMAPClient/BodyStructure/Parse.pm | 0 .../Mail/IMAPClient/BodyStructure/Parse.pod | 0 .../lib/Mail/IMAPClient/MessageSet.pm | 0 .../lib/Mail/IMAPClient/Thread.grammar | 0 .../lib/Mail/IMAPClient/Thread.pm | 0 .../lib/Mail/IMAPClient/Thread.pod | 0 .../prepare_dist | 0 .../t/basic.t | 0 .../t/body_string.t | 0 .../t/bodystructure.t | 0 .../t/fetch_hash.t | 47 +- .../t/messageset.t | 0 .../t/pod.t | 0 .../t/simple.t | 0 .../t/thread.t | 0 .../test_template.txt | 0 Makefile | 51 +- README | 21 +- TIME | 8 + TODO | 19 +- VERSION | 2 +- VERSION_EXE | 2 +- adwords | 6 + i2 | 5 +- i3 | 5 +- imapsync | 88 +- imapsync-1.366 | 4310 +++++++++++++++ imapsync-1.404 | 4830 +++++++++++++++++ imapsync.exe | Bin 5868421 -> 5820177 bytes index.shtml | 130 +- memo | 10 +- paypal_reply/memo | 147 + paypal_reply/paypal_bilan | 800 ++- paypal_reply/paypal_bilan_1.22 | 756 +++ paypal_reply/paypal_build_invoices | 83 + paypal_reply/paypal_build_reply | 57 +- paypal_reply/paypal_functions | 56 +- paypal_reply/paypal_imapget | 9 +- .../{paypal_run_test => paypal_run_dev} | 6 +- paypal_reply/paypal_run_laposte | 4 +- paypal_reply/paypal_run_petite | 4 +- paypal_reply/paypal_send_invoices | 43 + paypal_return.shtml | 113 + paypal_return_support.shtml | 109 + test2.bat | 9 +- tests.sh | 160 +- 72 files changed, 11829 insertions(+), 287 deletions(-) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/Changes (99%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/MANIFEST (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/META.yml (97%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/Makefile.PL (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/README (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/build_dist.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/build_ldif.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/cleanTest.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/copy_folder.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/cyrus_expire.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/cyrus_expunge.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/find_dup_msgs.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/idle.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/imap_to_mbox.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/imtestExample.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/migrate_mail2.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/migrate_mbox.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/populate_mailbox.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/examples/sharedFolder.pl (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/lib/Mail/IMAPClient.pm (98%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/lib/Mail/IMAPClient.pod (99%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/lib/Mail/IMAPClient/BodyStructure.pm (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/lib/Mail/IMAPClient/BodyStructure/Parse.grammar (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/lib/Mail/IMAPClient/BodyStructure/Parse.pm (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/lib/Mail/IMAPClient/BodyStructure/Parse.pod (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/lib/Mail/IMAPClient/MessageSet.pm (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/lib/Mail/IMAPClient/Thread.grammar (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/lib/Mail/IMAPClient/Thread.pm (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/lib/Mail/IMAPClient/Thread.pod (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/prepare_dist (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/t/basic.t (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/t/body_string.t (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/t/bodystructure.t (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/t/fetch_hash.t (81%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/t/messageset.t (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/t/pod.t (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/t/simple.t (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/t/thread.t (100%) rename {Mail-IMAPClient-3.27 => Mail-IMAPClient-3.28}/test_template.txt (100%) create mode 100644 adwords create mode 100755 imapsync-1.366 create mode 100755 imapsync-1.404 create mode 100644 paypal_reply/memo create mode 100755 paypal_reply/paypal_bilan_1.22 create mode 100644 paypal_reply/paypal_build_invoices rename paypal_reply/{paypal_run_test => paypal_run_dev} (71%) create mode 100644 paypal_reply/paypal_send_invoices create mode 100644 paypal_return.shtml create mode 100644 paypal_return_support.shtml diff --git a/CREDITS b/CREDITS index 3275cb3..bb21e8b 100644 --- a/CREDITS +++ b/CREDITS @@ -1,5 +1,5 @@ #!/bin/cat -# $Id: CREDITS,v 1.155 2011/01/23 23:39:54 gilles Exp gilles $ +# $Id: CREDITS,v 1.156 2011/03/15 00:51:57 gilles Exp gilles $ If you want to make a donation to the author, Gilles LAMIRAL, use any of the following ways: @@ -30,6 +30,21 @@ I thank very much all of these people. I thank also very much all people who bought imapsync from the homepage but I don't cite them here. +Khalid Shakir +Contributed by giving the book +75.00 "Selected Papers on Fun and Games [Hardcover]" + +Alexander J. Stein +Contributed by giving the book +22.00 "Weinberg on Writing: The Fieldstone Method" + +Doug Ferguson +Contributed by giving the books +35.16 "Test Driven Development: By Example" +13.86 "Gödel, Escher, Bach: An Eternal Golden Braid" +14.49 "The Mind's I: Fantasies and Reflections on Self & Soul" +46.42 "Memory" + Timothy Jay Chambers Contributed by giving the book 27.32 "Mathematics and Plausible Reasoning: Volume II Patterns of Plausible Inference" @@ -981,6 +996,13 @@ Eric Yung Total amount of book prices : c \ +75.00+\ +\ +35.16+\ +13.86+\ +14.49+\ +46.42+\ +\ 27.32+\ 40.90+\ \ @@ -1102,4 +1124,4 @@ c \ 31.20+\ 40.00 = -2779.03 +2963.96 diff --git a/ChangeLog b/ChangeLog index 3021928..24f3c03 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,17 +1,49 @@ RCS file: RCS/imapsync,v Working file: imapsync -head: 1.404 +head: 1.411 branch: locks: strict - gilles: 1.404 + gilles: 1.411 access list: symbolic names: keyword substitution: kv -total revisions: 404; selected revisions: 404 +total revisions: 411; selected revisions: 411 description: ---------------------------- -revision 1.404 locked by: gilles; +revision 1.411 locked by: gilles; +date: 2011/04/19 23:34:30; author: gilles; state: Exp; lines: +19 -11 +Bugfix for "Folders in host2 not in host1" list when folders are given by --folder option or equivalent. +The old list listed too many folders with --folder INBOX for example. +---------------------------- +revision 1.410 +date: 2011/04/19 23:11:42; author: gilles; state: Exp; lines: +9 -8 +Updated success list. +---------------------------- +revision 1.409 +date: 2011/04/16 20:15:05; author: gilles; state: Exp; lines: +7 -6 +Added --takebody option. +---------------------------- +revision 1.408 +date: 2011/04/11 01:37:34; author: gilles; state: Exp; lines: +9 -8 +Added Gimap (Gmail imap) success. +Added IMail 11.03 [host1] success +---------------------------- +revision 1.407 +date: 2011/04/02 23:07:09; author: gilles; state: Exp; lines: +21 -12 +Made --delete2 works with --uselib or --usecache +---------------------------- +revision 1.406 +date: 2011/03/10 01:35:57; author: gilles; state: Exp; lines: +15 -13 +No longer --useuid with --fast +Debug output with permanentflags. +---------------------------- +revision 1.405 +date: 2011/03/07 13:41:54; author: gilles; state: Exp; lines: +13 -11 +Added isync url. +Sleep 2 seconds after foldersizes calls. +---------------------------- +revision 1.404 date: 2011/02/21 03:35:39; author: gilles; state: Exp; lines: +7 -7 typo ---------------------------- diff --git a/FAQ b/FAQ index 8914cc1..10ffef0 100644 --- a/FAQ +++ b/FAQ @@ -1,5 +1,5 @@ #!/bin/cat -# $Id: FAQ,v 1.83 2011/01/28 05:14:12 gilles Exp gilles $ +# $Id: FAQ,v 1.85 2011/02/28 16:02:17 gilles Exp gilles $ +------------------+ | FAQ for imapsync | @@ -24,7 +24,7 @@ R. http://www.linux-france.org/prj/imapsync/FAQ Q. How can I have commercial support? R. Ask the imapsync author and expert: Gilles LAMIRAL -Rates per hour (2010) : 81 euros (111 USD) +Rates per hour (2011) : 84 euros (111 USD) ======================================================================= Q. How can I have gratis support? @@ -81,7 +81,7 @@ http://www.faqs.org/rfcs/rfc4549.html ======================================================================= Q. Where I can find old imapsync releases? -R. ftp://www.linux-france.org/pub/prj/imapsync/ +R. Search the internet. ======================================================================= Q. How can I try imapsync with the new Mail::IMAPClient 3.xx perl library? @@ -103,8 +103,7 @@ R. - Download latest Mail::IMAPClient 3.xx at perl -I./Mail-IMAPClient-3.23/lib /path/imapsync ... ======================================================================= -Q. imapsync does not work with Mail::IMAPClient 3.xx - How can I downgrade to 2.2.9 release? +Q. How can I use imapsync with Mail::IMAPClient 2.2.9 perl module? R. - Download Mail::IMAPClient 2.2.9 at http://search.cpan.org/~djkernen/Mail-IMAPClient-2.2.9/ @@ -119,12 +118,18 @@ R. - Download Mail::IMAPClient 2.2.9 at perl -I./Mail-IMAPClient-2.2.9 /path/imapsync [...] ======================================================================= -Q. Can I use imapsync to migrate emails from pop server to imap server? +Q. Can I use imapsync to migrate emails from pop3 server to imap server? -R. No. +R1. No. You can migrate emails from pop server to imap server with pop2imap: http://www.linux-france.org/prj/pop2imap/ +R2. Yes +Many pop3 servers runs in parallel with an imap server on the +exactly the same mailboxes. They serve the same INBOX +(imap serves INBOX and several other folders, pop3 serves only INBOX) +So have a try with imapsync on the same host1. + ======================================================================= Q. I am interested in creating a local clone of the IMAP on a LAN server for faster synchronisations, email will always be delivered @@ -178,18 +183,35 @@ d) Use the --syncinternaldates option and keep using Eudora. Q. imapsync calculates 479 messages in a folder but only transfers 400 messages. What's happen? -R. imapsync considers the header part of a message (as a whole or +R1. imapsync considers the header part of a message (as a whole or only specific lines depending on --useheader --skipheader) to identify a message on both sides. -Two consequences: +Consequences: - 1) Messages with no header are not transferred. - 2) Duplicate messages (identical header) are not transferred + 1) Duplicate messages (identical header) are not transferred several times. The result is that you can have more messages on host1 than on host2. +R2. With option --useuid imapsync doesn't use headers to identify +messages on both sides but it uses their imap uid. In than case +duplicates are transfered and --delete2 won't work. + +======================================================================= +Q. I run multiple imapsync applications at the same time then get a + warning "imapsync.pid already exists, overwriting it". + Is this a potential problem when trying to sync multiple + IMAP account in parallel? + +R1. No issue with the file imapsync.pid if you don't use its content. +This file can help you to manage multiple runs by sending +signals to the processes (sigterm or sigkill) using their PID, +each run can have its own pid file with --pidfile option. +The file imapsync.pid contains the PID of the imapsync process. +This file is removed at the end of a normal run. +You can saafely ignore the warning if you don't use imapsync.pid. + ======================================================================= Q. Couldn't create [INBOX.Ops/foo/bar]: NO Invalid mailbox name: INBOX.Ops/foo/bar @@ -208,7 +230,7 @@ Sometimes the sep1 character is not valid on host2 (character "/" usualy) R. Try : - --regextrans2 's,/,X,g' + --regextrans2 "s,/,X,g" It'll convert / character to X Choose X as you wish: _ or SEP or @@ -267,7 +289,7 @@ R. For some servers, flags have to begin with a \ character. The flag "NonJunk" may be a invalid flag for your server so use for example: -imapsync ... --regexflag 's/NonJunk//g' +imapsync ... --regexflag "s/NonJunk//g" Remark (thanks to Arnt Gulbrandsen): IMAP system flags have to begin with \ character. @@ -1157,19 +1179,3 @@ Q: How can I write an .rpm with imapsync R: I don't know but Neil Brown wrote one rpm package and you'll find his .spec file here : http://www.linux-france.org/prj/imapsync/learn/rpm/ - -====================================================================== -Q: Problems on win32, Timezone and Date::Manip -R: Comment the code like the following - - if ($syncinternaldates) { - $d = $f_idate; - $debug and print "internal date from 1: [$d]\n"; - #require Date::Manip; - #Date::Manip->import(qw(ParseDate Date_Cmp UnixDate)); - #$d = UnixDate(ParseDate($d), "%d %b %Y %H:%M:%S %z"); - #$d = "\"$d\""; - #$debug and print "internal date from 1: [$d] (fixed)\n"; - } - - diff --git a/Mail-IMAPClient-3.27/Changes b/Mail-IMAPClient-3.28/Changes similarity index 99% rename from Mail-IMAPClient-3.27/Changes rename to Mail-IMAPClient-3.28/Changes index 267d807..137a4c7 100644 --- a/Mail-IMAPClient-3.27/Changes +++ b/Mail-IMAPClient-3.28/Changes @@ -5,6 +5,21 @@ Changes from 2.99_01 to 3.16 made by Mark Overmeer Changes from 0.09 to 2.99_01 made by David Kernen - Potential compatibility issues from 3.17+ highlighted with '*' +version 3.28_04: Fri Mar 4 00:17:38 EST 2011 + - rt.cpan.org#66004: internaldate() return undef if no internaldate in reply + [Jason Long] + - rt.cpan.org#66367: fetch_hash uses Escaped_results() in 3.26/3.27 + (redo) rt.cpan.org#63524: fetch_hash() parse errors + [Mathias Reitinger] + + fetch_hash: only Escape() data in parenthesized list + + update fetch_hash test and add a new test + - do not touch CRLF in Escape()/Unescape() + - added Escape() method + - rt.cpan.org#66287: flags results truncated due to Maxcommandlength + [Erik Colson] + - rt.cpan.org#65694: SASL PLAIN: bad order of login data + [Willi Mann] + version 3.27: Sun Feb 13 14:37:27 EST 2011 - rt.cpan.org#65694: migrate fails [Erik Colson] diff --git a/Mail-IMAPClient-3.27/MANIFEST b/Mail-IMAPClient-3.28/MANIFEST similarity index 100% rename from Mail-IMAPClient-3.27/MANIFEST rename to Mail-IMAPClient-3.28/MANIFEST diff --git a/Mail-IMAPClient-3.27/META.yml b/Mail-IMAPClient-3.28/META.yml similarity index 97% rename from Mail-IMAPClient-3.27/META.yml rename to Mail-IMAPClient-3.28/META.yml index 39692f1..e10d446 100644 --- a/Mail-IMAPClient-3.27/META.yml +++ b/Mail-IMAPClient-3.28/META.yml @@ -1,6 +1,6 @@ --- #YAML:1.0 name: Mail-IMAPClient -version: 3.27 +version: 3.28 abstract: IMAP4 client library author: - Phil Pearl (Lobbes) diff --git a/Mail-IMAPClient-3.27/Makefile.PL b/Mail-IMAPClient-3.28/Makefile.PL similarity index 100% rename from Mail-IMAPClient-3.27/Makefile.PL rename to Mail-IMAPClient-3.28/Makefile.PL diff --git a/Mail-IMAPClient-3.27/README b/Mail-IMAPClient-3.28/README similarity index 100% rename from Mail-IMAPClient-3.27/README rename to Mail-IMAPClient-3.28/README diff --git a/Mail-IMAPClient-3.27/examples/build_dist.pl b/Mail-IMAPClient-3.28/examples/build_dist.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/build_dist.pl rename to Mail-IMAPClient-3.28/examples/build_dist.pl diff --git a/Mail-IMAPClient-3.27/examples/build_ldif.pl b/Mail-IMAPClient-3.28/examples/build_ldif.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/build_ldif.pl rename to Mail-IMAPClient-3.28/examples/build_ldif.pl diff --git a/Mail-IMAPClient-3.27/examples/cleanTest.pl b/Mail-IMAPClient-3.28/examples/cleanTest.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/cleanTest.pl rename to Mail-IMAPClient-3.28/examples/cleanTest.pl diff --git a/Mail-IMAPClient-3.27/examples/copy_folder.pl b/Mail-IMAPClient-3.28/examples/copy_folder.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/copy_folder.pl rename to Mail-IMAPClient-3.28/examples/copy_folder.pl diff --git a/Mail-IMAPClient-3.27/examples/cyrus_expire.pl b/Mail-IMAPClient-3.28/examples/cyrus_expire.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/cyrus_expire.pl rename to Mail-IMAPClient-3.28/examples/cyrus_expire.pl diff --git a/Mail-IMAPClient-3.27/examples/cyrus_expunge.pl b/Mail-IMAPClient-3.28/examples/cyrus_expunge.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/cyrus_expunge.pl rename to Mail-IMAPClient-3.28/examples/cyrus_expunge.pl diff --git a/Mail-IMAPClient-3.27/examples/find_dup_msgs.pl b/Mail-IMAPClient-3.28/examples/find_dup_msgs.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/find_dup_msgs.pl rename to Mail-IMAPClient-3.28/examples/find_dup_msgs.pl diff --git a/Mail-IMAPClient-3.27/examples/idle.pl b/Mail-IMAPClient-3.28/examples/idle.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/idle.pl rename to Mail-IMAPClient-3.28/examples/idle.pl diff --git a/Mail-IMAPClient-3.27/examples/imap_to_mbox.pl b/Mail-IMAPClient-3.28/examples/imap_to_mbox.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/imap_to_mbox.pl rename to Mail-IMAPClient-3.28/examples/imap_to_mbox.pl diff --git a/Mail-IMAPClient-3.27/examples/imtestExample.pl b/Mail-IMAPClient-3.28/examples/imtestExample.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/imtestExample.pl rename to Mail-IMAPClient-3.28/examples/imtestExample.pl diff --git a/Mail-IMAPClient-3.27/examples/migrate_mail2.pl b/Mail-IMAPClient-3.28/examples/migrate_mail2.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/migrate_mail2.pl rename to Mail-IMAPClient-3.28/examples/migrate_mail2.pl diff --git a/Mail-IMAPClient-3.27/examples/migrate_mbox.pl b/Mail-IMAPClient-3.28/examples/migrate_mbox.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/migrate_mbox.pl rename to Mail-IMAPClient-3.28/examples/migrate_mbox.pl diff --git a/Mail-IMAPClient-3.27/examples/populate_mailbox.pl b/Mail-IMAPClient-3.28/examples/populate_mailbox.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/populate_mailbox.pl rename to Mail-IMAPClient-3.28/examples/populate_mailbox.pl diff --git a/Mail-IMAPClient-3.27/examples/sharedFolder.pl b/Mail-IMAPClient-3.28/examples/sharedFolder.pl similarity index 100% rename from Mail-IMAPClient-3.27/examples/sharedFolder.pl rename to Mail-IMAPClient-3.28/examples/sharedFolder.pl diff --git a/Mail-IMAPClient-3.27/lib/Mail/IMAPClient.pm b/Mail-IMAPClient-3.28/lib/Mail/IMAPClient.pm similarity index 98% rename from Mail-IMAPClient-3.27/lib/Mail/IMAPClient.pm rename to Mail-IMAPClient-3.28/lib/Mail/IMAPClient.pm index b465dbe..cebb696 100644 --- a/Mail-IMAPClient-3.27/lib/Mail/IMAPClient.pm +++ b/Mail-IMAPClient-3.28/lib/Mail/IMAPClient.pm @@ -7,7 +7,7 @@ use strict; use warnings; package Mail::IMAPClient; -our $VERSION = '3.27'; +our $VERSION = '3.28'; use Mail::IMAPClient::MessageSet; @@ -1708,7 +1708,7 @@ sub Escaped_results { # literal is appended to previous data if ( $self->_is_literal($line) ) { - $data =~ s/([\\\(\)"$CRLF])/\\$1/og; + $data = $self->Escape($data); $a[-1] .= qq( "$data"); $prevwasliteral = 1; } @@ -1726,10 +1726,16 @@ sub Escaped_results { return wantarray ? @a : \@a; } +sub Escape { + my $data = $_[1]; + $data =~ s/([\\\"])/\\$1/og; + return $data; +} + sub Unescape { - my $whatever = $_[1]; - $whatever =~ s/\\([\\\(\)"$CRLF])/$1/og; - $whatever; + my $data = $_[1]; + $data =~ s/\\([\\\"])/$1/og; + return $data; } sub logout { @@ -2001,7 +2007,7 @@ s/([\( ])FULL([\) ])/${1}FLAGS INTERNALDATE RFC822\.SIZE ENVELOPE BODY$2/i; } my %words = map { uc($_) => 1 } @words; - my $output = $self->fetch( { escaped => 1 }, $msgs, "($what)" ) + my $output = $self->fetch( $msgs, "($what)" ) or return undef; while ( my $l = shift @$output ) { @@ -2025,7 +2031,7 @@ s/([\( ])FULL([\) ])/${1}FLAGS INTERNALDATE RFC822\.SIZE ENVELOPE BODY$2/i; $l = shift @$output; next ATTR; } - elsif ( $l =~ m/\G(?:"([^"]+)"|([^()\s]+))\s*/gc ) { + elsif ( $l =~ m/\G(?:"(.*?)(?:(?{$key} = $value; next ATTR; @@ -2050,6 +2056,13 @@ s/([\( ])FULL([\) ])/${1}FLAGS INTERNALDATE RFC822\.SIZE ENVELOPE BODY$2/i; else { $value .= $stuff; } + + # consume literal data if any + if ( $l =~ m/\G\s*$/gc and scalar(@$output) ) { + my $elit = $self->Escape( shift @$output ); + $l = shift @$output; + $value .= ( length($value) ? " " : "" ) . qq{"$elit"}; + } } $l =~ m/\G\s*/gc; } @@ -2207,13 +2220,13 @@ sub flags { $msg->cat(@_) if @_; # Send command - $self->fetch( $msg, "FLAGS" ) or return undef; + my $ref = $self->fetch( $msg, "FLAGS" ) or return undef; my $u_f = $self->Uid; my $flagset = {}; # Parse results, setting entry in result hash for each line - foreach my $line ( $self->Results ) { + foreach my $line (@$ref) { $self->_debug("flags: line = '$line'"); if ( $line =~ /\* \s+ (\d+) \s+ FETCH \s+ # * nnn FETCH @@ -2661,10 +2674,8 @@ sub internaldate { my ( $self, $msg ) = @_; $self->_imap_uid_command( FETCH => $msg, 'INTERNALDATE' ) or return undef; - my $internalDate = join '', $self->History; - $internalDate =~ s/^.*INTERNALDATE "//si; - $internalDate =~ s/\".*$//s; - $internalDate; + my $hist = join '', $self->History; + return $hist =~ /\bINTERNALDATE "([^"]*)"/i ? $1 : undef; } sub is_parent { @@ -2973,13 +2984,14 @@ sub authenticate { elsif ( $scheme eq 'PLAIN' ) { # PLAIN SASL $response ||= sub { my ( $code, $client ) = @_; - encode_base64( - $client->User - . chr(0) - . $client->Proxy - . chr(0) - . $client->Password, - '' + encode_base64( # [authname] user password + join( + chr(0), + defined $client->Proxy + ? ( $client->User, $client->Proxy ) + : ( "", $client->User ), + defined $client->Password ? $client->Password : "", + ), ); }; } diff --git a/Mail-IMAPClient-3.27/lib/Mail/IMAPClient.pod b/Mail-IMAPClient-3.28/lib/Mail/IMAPClient.pod similarity index 99% rename from Mail-IMAPClient-3.27/lib/Mail/IMAPClient.pod rename to Mail-IMAPClient-3.28/lib/Mail/IMAPClient.pod index f03cc89..6a4b12c 100644 --- a/Mail-IMAPClient-3.27/lib/Mail/IMAPClient.pod +++ b/Mail-IMAPClient-3.28/lib/Mail/IMAPClient.pod @@ -94,7 +94,13 @@ CRAM-MD5 requires the L module. =item PLAIN (SASL) -PLAIN (SASL) authentication requires the use of the L parameter. +PLAIN (SASL) authentication allows the optional use of the L +parameter. RFC 4616 documents this syntax for SASL PLAIN: + + message = [authzid] UTF8NUL authcid UTF8NUL passwd + +When L is defined, L is used as 'authzid' and L +is used as 'authcid'. Otherwise, L is used as 'authcid'. =item NTLM @@ -1056,16 +1062,14 @@ This would result in L output similar to the following: } }; -By itself this method may be useful for, say, speeding up programs that -want the size of every message in a folder. It issues one command and -receives one (possibly long!) response from the server. However, it's -true power lies in the as-yet-unwritten methods that will rely on this -method to deliver even more powerful result hashes. Look for more new -function in later releases. +By itself this method may be useful for tasks like obtaining the size +of every message in a folder. It issues one command and receives one +(possibly long!) response from the server. -This method is new with version 2.2.3 and is thus still experimental. -If you decide to try this method and run into problems, please see the -section on L. +If the fetch request causes the server to return data in a +parenthesized list, the data within the parenthesized list may be +escaped via the Escape() method. Use the Unescape() method to get the +raw values back in this case. =head2 flags @@ -1308,7 +1312,8 @@ Example: or die "Could not internaldate: $@\n"; B accepts one argument, a message id (or UID if the -L parameter is true), and returns that message's internal date. +L parameter is true), and returns that message's internal date +or undef if the call fails or internal date is not returned. =head2 get_bodystructure diff --git a/Mail-IMAPClient-3.27/lib/Mail/IMAPClient/BodyStructure.pm b/Mail-IMAPClient-3.28/lib/Mail/IMAPClient/BodyStructure.pm similarity index 100% rename from Mail-IMAPClient-3.27/lib/Mail/IMAPClient/BodyStructure.pm rename to Mail-IMAPClient-3.28/lib/Mail/IMAPClient/BodyStructure.pm diff --git a/Mail-IMAPClient-3.27/lib/Mail/IMAPClient/BodyStructure/Parse.grammar b/Mail-IMAPClient-3.28/lib/Mail/IMAPClient/BodyStructure/Parse.grammar similarity index 100% rename from Mail-IMAPClient-3.27/lib/Mail/IMAPClient/BodyStructure/Parse.grammar rename to Mail-IMAPClient-3.28/lib/Mail/IMAPClient/BodyStructure/Parse.grammar diff --git a/Mail-IMAPClient-3.27/lib/Mail/IMAPClient/BodyStructure/Parse.pm b/Mail-IMAPClient-3.28/lib/Mail/IMAPClient/BodyStructure/Parse.pm similarity index 100% rename from Mail-IMAPClient-3.27/lib/Mail/IMAPClient/BodyStructure/Parse.pm rename to Mail-IMAPClient-3.28/lib/Mail/IMAPClient/BodyStructure/Parse.pm diff --git a/Mail-IMAPClient-3.27/lib/Mail/IMAPClient/BodyStructure/Parse.pod b/Mail-IMAPClient-3.28/lib/Mail/IMAPClient/BodyStructure/Parse.pod similarity index 100% rename from Mail-IMAPClient-3.27/lib/Mail/IMAPClient/BodyStructure/Parse.pod rename to Mail-IMAPClient-3.28/lib/Mail/IMAPClient/BodyStructure/Parse.pod diff --git a/Mail-IMAPClient-3.27/lib/Mail/IMAPClient/MessageSet.pm b/Mail-IMAPClient-3.28/lib/Mail/IMAPClient/MessageSet.pm similarity index 100% rename from Mail-IMAPClient-3.27/lib/Mail/IMAPClient/MessageSet.pm rename to Mail-IMAPClient-3.28/lib/Mail/IMAPClient/MessageSet.pm diff --git a/Mail-IMAPClient-3.27/lib/Mail/IMAPClient/Thread.grammar b/Mail-IMAPClient-3.28/lib/Mail/IMAPClient/Thread.grammar similarity index 100% rename from Mail-IMAPClient-3.27/lib/Mail/IMAPClient/Thread.grammar rename to Mail-IMAPClient-3.28/lib/Mail/IMAPClient/Thread.grammar diff --git a/Mail-IMAPClient-3.27/lib/Mail/IMAPClient/Thread.pm b/Mail-IMAPClient-3.28/lib/Mail/IMAPClient/Thread.pm similarity index 100% rename from Mail-IMAPClient-3.27/lib/Mail/IMAPClient/Thread.pm rename to Mail-IMAPClient-3.28/lib/Mail/IMAPClient/Thread.pm diff --git a/Mail-IMAPClient-3.27/lib/Mail/IMAPClient/Thread.pod b/Mail-IMAPClient-3.28/lib/Mail/IMAPClient/Thread.pod similarity index 100% rename from Mail-IMAPClient-3.27/lib/Mail/IMAPClient/Thread.pod rename to Mail-IMAPClient-3.28/lib/Mail/IMAPClient/Thread.pod diff --git a/Mail-IMAPClient-3.27/prepare_dist b/Mail-IMAPClient-3.28/prepare_dist similarity index 100% rename from Mail-IMAPClient-3.27/prepare_dist rename to Mail-IMAPClient-3.28/prepare_dist diff --git a/Mail-IMAPClient-3.27/t/basic.t b/Mail-IMAPClient-3.28/t/basic.t similarity index 100% rename from Mail-IMAPClient-3.27/t/basic.t rename to Mail-IMAPClient-3.28/t/basic.t diff --git a/Mail-IMAPClient-3.27/t/body_string.t b/Mail-IMAPClient-3.28/t/body_string.t similarity index 100% rename from Mail-IMAPClient-3.27/t/body_string.t rename to Mail-IMAPClient-3.28/t/body_string.t diff --git a/Mail-IMAPClient-3.27/t/bodystructure.t b/Mail-IMAPClient-3.28/t/bodystructure.t similarity index 100% rename from Mail-IMAPClient-3.27/t/bodystructure.t rename to Mail-IMAPClient-3.28/t/bodystructure.t diff --git a/Mail-IMAPClient-3.27/t/fetch_hash.t b/Mail-IMAPClient-3.28/t/fetch_hash.t similarity index 81% rename from Mail-IMAPClient-3.27/t/fetch_hash.t rename to Mail-IMAPClient-3.28/t/fetch_hash.t index 5ce15a0..c998887 100644 --- a/Mail-IMAPClient-3.27/t/fetch_hash.t +++ b/Mail-IMAPClient-3.28/t/fetch_hash.t @@ -9,7 +9,7 @@ use strict; use warnings; -use Test::More tests => 19; +use Test::More tests => 20; BEGIN { use_ok('Mail::IMAPClient') or exit; } @@ -100,26 +100,56 @@ my @tests = ( ], [ "BODY.PEEK[] requests match BODY[] responses", - [ q{* 1 FETCH (BODY[] foo)} ], + [q{* 1 FETCH (BODY[] foo)}], [ [1], qw(BODY.PEEK[]) ], { "1" => { "BODY[]" => q{foo}, }, }, ], [ "BODY.PEEK[] requests match BODY.PEEK[] responses also", - [ q{* 1 FETCH (BODY.PEEK[] foo)} ], + [q{* 1 FETCH (BODY.PEEK[] foo)}], [ [1], qw(BODY.PEEK[]) ], { "1" => { "BODY.PEEK[]" => q{foo}, }, }, ], [ - "escaped subject", - [ q{* 1 FETCH (UID 1 X-SAVEDATE "28-Jan-2011 16:52:31 -0500" FLAGS (\Seen) ENVELOPE ("Fri, 28 Jan 2011 00:03:30 -0500" "foo \\"bar\\" baz\'s" (("Phil Pearl" NIL "phil" "dom.loc")) (("Phil Pearl" NIL "phil" "dom.loc")) (("Phil Pearl" NIL "phil" "dom.loc")) ((NIL NIL "phil" "dom.loc")) NIL NIL NIL "")) } ], + "escaped ENVELOPE subject", + [ +q{* 1 FETCH (UID 1 X-SAVEDATE "28-Jan-2011 16:52:31 -0500" FLAGS (\Seen) ENVELOPE ("Fri, 28 Jan 2011 00:03:30 -0500"}, + q{foo "bar\\" (baz\\)}, +q{ (("Phil Pearl" NIL "phil" "dom.loc")) (("Phil Pearl" NIL "phil" "dom.loc")) (("Phil Pearl" NIL "phil" "dom.loc")) ((NIL NIL "phil" "dom.loc")) NIL NIL NIL "")) } + ], [ [1], qw(UID X-SAVEDATE FLAGS ENVELOPE) ], { "1" => { 'X-SAVEDATE' => '28-Jan-2011 16:52:31 -0500', - 'UID' => '1', - 'FLAGS' => '\\Seen', - 'ENVELOPE' => q{"Fri, 28 Jan 2011 00:03:30 -0500" "foo \\"bar\\" baz\'s" (("Phil Pearl" NIL "phil" "dom.loc")) (("Phil Pearl" NIL "phil" "dom.loc")) (("Phil Pearl" NIL "phil" "dom.loc")) ((NIL NIL "phil" "dom.loc")) NIL NIL NIL ""} + 'UID' => '1', + 'FLAGS' => '\\Seen', + 'ENVELOPE' => +q{"Fri, 28 Jan 2011 00:03:30 -0500" "foo \\"bar\\\\\\" (baz\\\\)" (("Phil Pearl" NIL "phil" "dom.loc")) (("Phil Pearl" NIL "phil" "dom.loc")) (("Phil Pearl" NIL "phil" "dom.loc")) ((NIL NIL "phil" "dom.loc")) NIL NIL NIL ""} + }, + }, + ], + [ + "non-escaped BODY[HEADER.FIELDS (...)]", + [ +q{* 1 FETCH (UID 1 FLAGS () BODY[HEADER.FIELDS (TO FROM SUBJECT DATE)]}, + 'From: Phil Pearl (Lobbes) +To: phil+to@perkpartners.com +Subject: foo "bar\" (baz\) +Date: Sat, 22 Jan 2011 20:43:58 -0500 + +' + ], + [ [1], ( qw(FLAGS), 'BODY[HEADER.FIELDS (TO FROM SUBJECT DATE)]' ) ], + { + '1' => { + 'BODY[HEADER.FIELDS (TO FROM SUBJECT DATE)]' => + 'From: Phil Pearl (Lobbes) +To: phil+to@perkpartners.com +Subject: foo "bar\" (baz\) +Date: Sat, 22 Jan 2011 20:43:58 -0500 + +', + 'FLAGS' => '', }, }, ], @@ -225,6 +255,7 @@ sub fetch { my ( $self, @args ) = @_; return $self->{_next_fetch_response} || []; } + sub Escaped_results { my ( $self, @args ) = @_; return $self->{_next_fetch_response} || []; diff --git a/Mail-IMAPClient-3.27/t/messageset.t b/Mail-IMAPClient-3.28/t/messageset.t similarity index 100% rename from Mail-IMAPClient-3.27/t/messageset.t rename to Mail-IMAPClient-3.28/t/messageset.t diff --git a/Mail-IMAPClient-3.27/t/pod.t b/Mail-IMAPClient-3.28/t/pod.t similarity index 100% rename from Mail-IMAPClient-3.27/t/pod.t rename to Mail-IMAPClient-3.28/t/pod.t diff --git a/Mail-IMAPClient-3.27/t/simple.t b/Mail-IMAPClient-3.28/t/simple.t similarity index 100% rename from Mail-IMAPClient-3.27/t/simple.t rename to Mail-IMAPClient-3.28/t/simple.t diff --git a/Mail-IMAPClient-3.27/t/thread.t b/Mail-IMAPClient-3.28/t/thread.t similarity index 100% rename from Mail-IMAPClient-3.27/t/thread.t rename to Mail-IMAPClient-3.28/t/thread.t diff --git a/Mail-IMAPClient-3.27/test_template.txt b/Mail-IMAPClient-3.28/test_template.txt similarity index 100% rename from Mail-IMAPClient-3.27/test_template.txt rename to Mail-IMAPClient-3.28/test_template.txt diff --git a/Makefile b/Makefile index 494c6c5..61c8a80 100644 --- a/Makefile +++ b/Makefile @@ -1,5 +1,5 @@ -# $Id: Makefile,v 1.60 2011/02/21 02:20:38 gilles Exp gilles $ +# $Id: Makefile,v 1.67 2011/04/20 01:20:06 gilles Exp gilles $ .PHONY: help usage all @@ -90,7 +90,7 @@ test_quick_229: imapsync tests.sh CMD_PERL='perl -I./Mail-IMAPClient-2.2.9' /usr/bin/time sh tests.sh locallocal 1>/dev/null test_quick_3xx: imapsync tests.sh - CMD_PERL='perl -I./Mail-IMAPClient-3.27/lib' /usr/bin/time sh tests.sh locallocal 1>/dev/null + CMD_PERL='perl -I./Mail-IMAPClient-3.28/lib' /usr/bin/time sh tests.sh locallocal 1>/dev/null testv: nice -40 sh -x tests.sh @@ -108,19 +108,13 @@ test229: .test_229 touch .test_229 .test_3xx: imapsync tests.sh - CMD_PERL='perl -I./Mail-IMAPClient-3.27/lib' /usr/bin/time sh tests.sh 1>/dev/null + CMD_PERL='perl -I./Mail-IMAPClient-3.28/lib' /usr/bin/time sh tests.sh 1>/dev/null touch .test_3xx testf: clean_test test .PHONY: lfo upload_lfo niouze_lfo niouze_fm public imapsync_cidone -upload_index: index.shtml - rcsdiff index.shtml - rsync -avH index.shtml \ - ../../public_html/www.linux-france.org/html/prj/imapsync/ - sh $(HOME)/memo/lfo-rsync - .dosify_bat: build_exe.bat test_exe.bat test.bat test2.bat unix2dos build_exe.bat test.bat test_exe.bat test2.bat touch .dosify_bat @@ -164,14 +158,14 @@ imapsync.exe: imapsync build_exe.bat test_exe.bat .dosify_bat imapsync_elf_x86.bin: imapsync rcsdiff imapsync { test 'vadrouille' = "`hostname`" && \ - pp -o imapsync_elf_x86.bin -I Mail-IMAPClient-3.27/lib \ + pp -o imapsync_elf_x86.bin -I Mail-IMAPClient-3.28/lib \ -M Mail::IMAPClient -M IO::Socket -M IO::Socket::SSL \ -M Digest::MD5 -M Digest::HMAC_MD5 -M Term::ReadKey \ -M Authen::NTLM \ imapsync ; \ } || : { test 'petite' = "`hostname`" && \ - pp -o imapsync_elf_x86.bin -I Mail-IMAPClient-3.27/lib \ + pp -o imapsync_elf_x86.bin -I Mail-IMAPClient-3.28/lib \ -M Mail::IMAPClient -M IO::Socket -M IO::Socket::SSL \ -M Digest::MD5 -M Digest::HMAC_MD5 -M Term::ReadKey \ -M Authen::NTLM \ @@ -180,7 +174,7 @@ imapsync_elf_x86.bin: imapsync imapsync ; \ } || : { test 'ks200821.kimsufi.com' = "`hostname`" && \ - pp -o imapsync_elf_x86.bin -I Mail-IMAPClient-3.27/lib \ + pp -o imapsync_elf_x86.bin -I Mail-IMAPClient-3.28/lib \ -M Mail::IMAPClient -M IO::Socket -M IO::Socket::SSL \ -M Digest::MD5 -M Digest::HMAC_MD5 -M Term::ReadKey \ -M Authen::NTLM \ @@ -195,7 +189,7 @@ lfo: cidone niouze_lfo upload_lfo dist: cidone test clean all INSTALL tarball -tarball: cidone all imapsync_elf_x86.bin imapsync.exe +tarball: cidone all imapsync.exe echo making tarball $(DIST_FILE) mkdir -p dist mkdir -p ../prepa_dist/$(DIST_NAME) @@ -208,24 +202,43 @@ tarball: cidone all imapsync_elf_x86.bin imapsync.exe ls -l ../prepa_dist/$(DIST_FILE) ks: - rsync -av . imapsync@ks.lamiral.info:public_html/imapsync + rsync -avz . imapsync@ks.lamiral.info:public_html/imapsync { cd /g/var/paypal_reply/ &&\ rsync -av url_exe url_release url_source imapsync@ks.lamiral.info:/g/var/paypal_reply/ \ ; } + +PUBLIC_FILES = ./ChangeLog ./COPYING ./CREDITS ./FAQ \ +./index.shtml ./INSTALL ./TIME \ +./logo_imapsync.png ./logo_imapsync_s.png \ +./paypal.shtml ./paypal_return.shtml ./paypal_return_support.shtml \ +./README ./style.css ./TODO ./VERSION ./VERSION_EXE + +upload_ks: + rsync -lptvHz $(PUBLIC_FILES) \ + root@ks.lamiral.info:/var/www/imapsync/ + rsync -lptvHz ./dist/index.shtml \ + root@ks.lamiral.info:/var/www/imapsync/dist/ + upload_lfo: #rm -rf /home/gilles/public_html/www.linux-france.org/html/prj/imapsync/ #rm -rf /home/gilles/public_html/www.linux-france.org/ftp/prj/imapsync/ - rsync -avH ./ChangeLog ./COPYING ./CREDITS ./FAQ \ - ./index.shtml ./INSTALL ./TIME \ - ./logo_imapsync.png ./logo_imapsync_s.png \ - ./paypal.shtml ./README ./style.css ./TODO ./VERSION ./VERSION_EXE \ + rsync -avH $(PUBLIC_FILES) \ /home/gilles/public_html/www.linux-france.org/html/prj/imapsync/ rsync -avH ./dist/index.shtml \ /home/gilles/public_html/www.linux-france.org/html/prj/imapsync/dist/ sh ~/memo/lfo-rsync -niouze_lfo : VERSION +upload_index: index.shtml + validate --verbose index.shtml + rcsdiff index.shtml + rsync -avH index.shtml \ + ../../public_html/www.linux-france.org/html/prj/imapsync/ + sh $(HOME)/memo/lfo-rsync + + + +niouze_lfo : echo "CORRECT ME: . ./memo && lfo_announce" niouze_fm: VERSION diff --git a/README b/README index 1242f65..e24a4e1 100644 --- a/README +++ b/README @@ -3,7 +3,7 @@ NAME Synchronise mailboxes between two imap servers. Good at IMAP migration. More than 36 different IMAP server softwares supported with success. - $Revision: 1.404 $ + $Revision: 1.411 $ SYNOPSIS To synchronise imap account "foo" on "imap.truc.org" to imap account @@ -270,13 +270,15 @@ BUG REPORT GUIDELINES - IMAPClient.pm version. + - the run context. Do you run imapsync.exe, a unix binary or the perl script imapsync. + - operating system running imapsync. + - virtual software context (vmware, xen etc.) + - operating systems on both sides and the third side in case you run imapsync on a foreign host from the both. - - virtual software context (vmware, xen etc.) - Most of those values can be found as a copy/paste at the begining of the output. @@ -287,12 +289,12 @@ BUG REPORT GUIDELINES IMAP SERVERS Failure stories reported with the following 3 imap servers: - - MailEnable 1.54 (Proprietary) http://www.mailenable.com/ - - DBMail 0.9, 2.0.7 (GPL). But DBMail 1.2.1 works. + - MailEnable 1.54 (Proprietary) but MailEnable 4.23 is supported. + - DBMail 0.9, 2.0.7 (GPL). But DBMail 1.2.1 is supported. Patient and confident testers are welcome. - Imail 7.04 (maybe). - Success stories reported with the following 40 imap servers (software + Success stories reported with the following 41 imap servers (software names are in alphabetic order): - 1und1 H mimap1 84498 [host1] @@ -323,11 +325,13 @@ IMAP SERVERS - Dovecot 0.99.10.4, 0.99.14, 0.99.14-8.fc4, 1.0-0.beta2.7, 1.0.0 [dest/source] (LGPL) (http://www.dovecot.org/) - Eudora WorldMail v2 + - Gimap (Gmail imap) - GMX IMAP4 StreamProxy. - Groupwise IMAP (Novell) 6.x and 7.0. Buggy so see the FAQ. - hMailServer 5.3.3 [host2], 4.4.1 [host1] (see FAQ) - iPlanet Messaging server 4.15, 5.1, 5.2 - - IMail 7.15 (Ipswitch/Win2003), 8.12 + - IMail 7.15 (Ipswitch/Win2003), 8.12, 11.03 [host1] + - MailEnable 4.23 [host1] [host2] - MDaemon 7.0.1, 8.0.2, 8.1, 9.5.4 (Windows server 2003 R2 platform) - Mercury 4.1 (Windows server 2000 platform) - Microsoft Exchange Server 5.5, 6.0.6249.0[host1], 6.0.6487.0[host1], @@ -413,9 +417,10 @@ SIMILAR SOFTWARES imapmigrate : http://sourceforge.net/projects/cyrus-utils/ wonko_imapsync: http://wonko.com/article/554 see also tools/wonko_ruby_imapsync + isync : http://isync.sourceforge.net/ pop2imap : http://www.linux-france.org/prj/pop2imap/ Feedback (good or bad) will often be welcome. - $Id: imapsync,v 1.404 2011/02/21 03:35:39 gilles Exp gilles $ + $Id: imapsync,v 1.411 2011/04/19 23:34:30 gilles Exp gilles $ diff --git a/TIME b/TIME index 72c75d7..833c036 100644 --- a/TIME +++ b/TIME @@ -1,3 +1,11 @@ + 40 Groupwize and authuser. Does not work. +540 Invoices build. + 35 Bug bug_zero_byte() tests.sh No bug found here. email. +200 Prepared change site to ks (apache2 logrotate etc.). + 63 "\Forwarded" flag bug in courier. DJ dj@blu... + 30 Debug "BAD Command Argument Error. 12" on imapsync mailing-list. +120 Building invoices. + 60 Added imapsync on adwords for 75 euros, 1 euro per day max. Free promotional offer from Google Adwords. 200 Added --useuid. 110 Started to allow copy by uid. Added --notakebody 60 Fixed cache, dealing with filenames containing \ characters. diff --git a/TODO b/TODO index 834d856..e1bf2ba 100644 --- a/TODO +++ b/TODO @@ -1,5 +1,5 @@ #!/bin/cat -# $Id: TODO,v 1.92 2011/01/18 02:38:48 gilles Exp gilles $ +# $Id: TODO,v 1.95 2011/04/16 20:16:47 gilles Exp gilles $ TODO file for imapsync ---------------------- @@ -25,6 +25,16 @@ Evaluate http://www.rackspace.com/apps/email_hosting/migrations http://www.yippiemove.com/ +Make --delete2 works with --useuid + +Fix "\Forwarded" flag bug in courier. +Does \lalala can be forbidden (courier does a +"16 NO Error in IMAP command received by server" +with +* OK [PERMANENTFLAGS (\* \Draft \Answered \Flagged \Deleted \Seen)] Limited + + + Suggestion: it's very difficult to track down messages which are behaving funny during the sync. It would be great - and presumably easy to code - to have an option to have imapsync display e.g. the subject of an @@ -148,6 +158,13 @@ http://asg.web.cmu.edu/cyrus/download/imapd/altnamespace.html =========================================================================== +DONE. Read http://bugs.gentoo.org/show_bug.cgi?id=354831 + Nice conversation. + +DONE. Look https://fedorahosted.org/released/imapsync/ + +DONE. Take a look at https://bitbucket.org/imapsync/imapsync + DONE. Explain expunge behavior in help message. DONE. Add --authmd51 --authmd52 to permit authmd5 by host. diff --git a/VERSION b/VERSION index c0d870c..f812671 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.404 +1.411 diff --git a/VERSION_EXE b/VERSION_EXE index 4449725..fa83683 100644 --- a/VERSION_EXE +++ b/VERSION_EXE @@ -1 +1 @@ -1.404 +1.411 diff --git a/adwords b/adwords new file mode 100644 index 0000000..b4503f3 --- /dev/null +++ b/adwords @@ -0,0 +1,6 @@ +IMAP migration tool +Buy imapsync.exe + source for 30 € +30 days money-back guarantee +linux-france.org/prj/imapsync/ +www.linux-france.org/prj/imapsync/ + diff --git a/i2 b/i2 index b78ed27..39074b5 100755 --- a/i2 +++ b/i2 @@ -1,4 +1,7 @@ #!/bin/sh -perl -IMail-IMAPClient-2.2.9 ./imapsync "$@" +# $Id: i2,v 1.2 2011/03/15 01:14:15 gilles Exp gilles $ + +BASE=`dirname $0` +perl -I${BASE}/Mail-IMAPClient-2.2.9 ${BASE}/imapsync "$@" diff --git a/i3 b/i3 index d60b776..1a9d84c 100755 --- a/i3 +++ b/i3 @@ -1,4 +1,7 @@ #!/bin/sh -perl -IMail-IMAPClient-3.27/lib ./imapsync "$@" +# $Id: i3,v 1.7 2011/03/15 01:15:48 gilles Exp gilles $ + +BASE=`dirname $0` +perl -I${BASE}/Mail-IMAPClient-3.28/lib ${BASE}/imapsync "$@" diff --git a/imapsync b/imapsync index 00682b8..c97dadb 100755 --- a/imapsync +++ b/imapsync @@ -15,12 +15,12 @@ =head1 NAME -imapsync - IMAP synchronisation, sync, copy or migration -tool. Synchronise mailboxes between two imap servers. Good -at IMAP migration. More than 36 different IMAP server softwares +imapsync - IMAP synchronisation, sync, copy or migration tool. +Synchronise mailboxes between two imap servers. +Good at IMAP migration. More than 36 different IMAP server softwares supported with success. -$Revision: 1.404 $ +$Revision: 1.411 $ =head1 SYNOPSIS @@ -317,13 +317,15 @@ Help us to help you: in your report, please include: - IMAPClient.pm version. + - the run context. Do you run imapsync.exe, a unix binary or the perl script imapsync. + - operating system running imapsync. + - virtual software context (vmware, xen etc.) + - operating systems on both sides and the third side in case you run imapsync on a foreign host from the both. - - virtual software context (vmware, xen etc.) - Most of those values can be found as a copy/paste at the begining of the output. One time in your life, read the paper @@ -335,12 +337,12 @@ and then forget it. Failure stories reported with the following 3 imap servers: - - MailEnable 1.54 (Proprietary) http://www.mailenable.com/ - - DBMail 0.9, 2.0.7 (GPL). But DBMail 1.2.1 works. + - MailEnable 1.54 (Proprietary) but MailEnable 4.23 is supported. + - DBMail 0.9, 2.0.7 (GPL). But DBMail 1.2.1 is supported. Patient and confident testers are welcome. - Imail 7.04 (maybe). -Success stories reported with the following 40 imap servers +Success stories reported with the following 41 imap servers (software names are in alphabetic order): - 1und1 H mimap1 84498 [host1] @@ -371,11 +373,13 @@ Success stories reported with the following 40 imap servers - Dovecot 0.99.10.4, 0.99.14, 0.99.14-8.fc4, 1.0-0.beta2.7, 1.0.0 [dest/source] (LGPL) (http://www.dovecot.org/) - Eudora WorldMail v2 + - Gimap (Gmail imap) - GMX IMAP4 StreamProxy. - Groupwise IMAP (Novell) 6.x and 7.0. Buggy so see the FAQ. - hMailServer 5.3.3 [host2], 4.4.1 [host1] (see FAQ) - iPlanet Messaging server 4.15, 5.1, 5.2 - - IMail 7.15 (Ipswitch/Win2003), 8.12 + - IMail 7.15 (Ipswitch/Win2003), 8.12, 11.03 [host1] + - MailEnable 4.23 [host1] [host2] - MDaemon 7.0.1, 8.0.2, 8.1, 9.5.4 (Windows server 2003 R2 platform) - Mercury 4.1 (Windows server 2000 platform) - Microsoft Exchange Server 5.5, 6.0.6249.0[host1], 6.0.6487.0[host1], @@ -486,12 +490,13 @@ Entries for imapsync: imapmigrate : http://sourceforge.net/projects/cyrus-utils/ wonko_imapsync: http://wonko.com/article/554 see also tools/wonko_ruby_imapsync + isync : http://isync.sourceforge.net/ pop2imap : http://www.linux-france.org/prj/pop2imap/ Feedback (good or bad) will often be welcome. -$Id: imapsync,v 1.404 2011/02/21 03:35:39 gilles Exp gilles $ +$Id: imapsync,v 1.411 2011/04/19 23:34:30 gilles Exp gilles $ =cut @@ -599,7 +604,7 @@ my( # global variables initialisation -$rcs = '$Id: imapsync,v 1.404 2011/02/21 03:35:39 gilles Exp gilles $ '; +$rcs = '$Id: imapsync,v 1.411 2011/04/19 23:34:30 gilles Exp gilles $ '; $total_bytes_transferred = 0; $total_bytes_skipped = 0; @@ -644,7 +649,7 @@ $allow3xx = defined($allow3xx) ? $allow3xx : 1; $takebody = defined($takebody) ? $takebody : 1; if ( $fast ) { - $useuid = 1 ; + # $useuid = 1 ; $foldersizes = 0 ; } @@ -833,7 +838,8 @@ $split2 and $imap2->Split($split2); my ( @h1_folders_all, %h1_folders_all, @h1_folders_wanted, %requested_folder, %subscribed_folder, -@h2_folders_all, %h2_folders_all, @h2_folders_from_1, %h2_folders_from_1, +@h2_folders_all, %h2_folders_all, @h2_folders_from_1_wanted, %h2_folders_from_1_wanted, +@h2_folders_from_1_all, %h2_folders_from_1_all, ); @@ -929,14 +935,22 @@ print "Host2 separator and prefix: [$h2_sep][$h2_prefix]\n"; foreach my $h1_fold (@h1_folders_wanted) { my $h2_fold; $h2_fold = imap2_folder_name($h1_fold); - $h2_folders_from_1{$h2_fold}++; + $h2_folders_from_1_wanted{$h2_fold}++; } +@h2_folders_from_1_wanted = sort keys(%h2_folders_from_1_wanted); + +foreach my $h1_fold (@h1_folders_all) { + my $h2_fold; + $h2_fold = imap2_folder_name($h1_fold); + $h2_folders_from_1_all{$h2_fold}++; +} +#@h2_folders_from_1_all = sort keys(%h2_folders_from_1_all); -@h2_folders_from_1 = sort keys(%h2_folders_from_1); if ($foldersizes) { - foldersizes("Host1", $imap1, @h1_folders_wanted); - foldersizes("Host2", $imap2, @h2_folders_from_1); + foldersizes( "Host1", $imap1, @h1_folders_wanted ) ; + foldersizes( "Host2", $imap2, @h2_folders_from_1_wanted ) ; + sleep( 2 ) ; } @@ -983,7 +997,7 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) { #print "%%% @select_results\n"; my $permanentflags2 = permanentflags(@select_results); - + $debug and print "permanentflags: $permanentflags2\n" ; if ($expunge){ print "Expunging host1 $h1_fold\n"; unless($dry) { $imap1->expunge() }; @@ -1018,9 +1032,6 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) { print "CACHE h1 h2: ", scalar( keys %$cache_1_2_ref ), " files\n" ; $debug and print '[', map ( { "$_->$cache_1_2_ref->{$_} " } keys %$cache_1_2_ref ), " ]\n"; - #print "CACHE h2 h1: ", scalar( keys %$cache_2_1_ref ), " files\n" ; - #$debug and print '[', - # map ( { "$_->$cache_2_1_ref->{$_} " } keys %$cache_2_1_ref ), " ]\n"; } #sleep 4 ; @@ -1043,11 +1054,16 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) { my @h1_msgs_no_cache = keys %h1_msgs_no_cache ; my @h2_msgs_no_cache = keys %h2_msgs_no_cache ; + my @h2_msgs_delete2_no_cache = () ; if ( $useuid ) { + # use uid so we have to avoid getting header @h1_msgs_copy_by_uid{ @h1_msgs_no_cache } = ( ) ; + @h2_msgs_delete2_no_cache = @h2_msgs_no_cache if $usecache ; @h1_msgs_no_cache = ( ) ; @h2_msgs_no_cache = ( ) ; + + #print "delete2: @h2_msgs_delete2_no_cache\n"; } $debug and print "Host1 folder [$h1_fold] parsing headers\n"; @@ -1136,7 +1152,7 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) { my $h2_msg = $h2_hash{$m_id}{'m'}; my $h2_flags = $h2_hash{$m_id}{'F'} || ""; my $isdel = $h2_flags =~ /\B\\Deleted\b/ ? 1 : 0; - print "msg $h2_fold/$h2_msg deleted on host2 [$m_id]\n" + print "msg $h2_fold/$h2_msg marked \\Deleted on host2 [$m_id]\n" if ! $isdel; push(@h2_expunge, $h2_msg) if $uidexpunge2; unless ($dry or $isdel) { @@ -1146,14 +1162,20 @@ FOLDER: foreach my $h1_fold (@h1_folders_wanted) { } } foreach my $h2_msg (@h2_msgs_duplicate) { - print "msg $h2_fold/$h2_msg deleted [duplicate] on host2\n"; + print "msg $h2_fold/$h2_msg marked \\Deleted [duplicate] on host2\n"; push(@h2_expunge, $h2_msg) if $uidexpunge2; unless ($dry) { $imap2->delete_message($h2_msg); $h2_nb_msg_deleted += 1; } } - + foreach my $h2_msg ( @h2_msgs_delete2_no_cache ) { + print "msg $h2_fold/$h2_msg marked \\Deleted [not in cache] on host2\n"; + unless ($dry) { + $imap2->delete_message($h2_msg); + $h2_nb_msg_deleted += 1; + } + } my $cnt = scalar @h2_expunge; if(@h2_expunge and !$imap2->can("uidexpunge")) { warn "uidexpunge not supported (< IMAPClient 3.17)\n"; @@ -1273,7 +1295,7 @@ sub sync_flags { # we need most of the time. if ( ! $dry and $diff and ! $imap2->store( $h2_msg, "FLAGS.SILENT (@h1_flags)" ) ) { - warn "- msg $h2_fold/$h2_msg could not add flags @h1_flags", + warn "- msg $h2_fold/$h2_msg could not add flags [@h1_flags]: ", $imap2->LastError, "\n"; #$nb_errors++; } @@ -1632,8 +1654,8 @@ sub banner_imapsync { my @argv_copy = @_; my $banner_imapsync = join("", '$RCSfile: imapsync,v $ ', - '$Revision: 1.404 $ ', - '$Date: 2011/02/21 03:35:39 $ ', + '$Revision: 1.411 $ ', + '$Date: 2011/04/19 23:34:30 $ ', "\n",localhost_info(), "\n", "Command line used:\n", "$0 ", command_line_nopassword(@argv_copy), "\n", @@ -2227,7 +2249,7 @@ sub permanentflags { foreach my $line (@lines) { if ($line =~ m{\[PERMANENTFLAGS \(([^)]+?)\)\]}) { - #print "%%%$1%%%\n"; + $debug and print "permanentflags: $line"; my $permanentflags = $1; if ($permanentflags =~ m{\\\*}) { $permanentflags = ''; @@ -2534,6 +2556,7 @@ sub get_cache { return ( $cache_1_2_ref, $cache_2_1_ref ) ; } + sub tests_get_cache { ok( ! get_cache('/cache_no_exist'), 'get_cache: /cache_no_exist' ); @@ -2989,6 +3012,7 @@ sub get_options { "timeout=i" => \$timeout, "skipheader=s" => \$skipheader, "useheader=s" => \@useheader, + "takebody!" => \$takebody, "skipsize!" => \$skipsize, "allowsizemismatch!" => \$allowsizemismatch, "fastio1!" => \$fastio1, @@ -3198,7 +3222,7 @@ sub check_last_release { } sub imapsync_version { - my $rcs = '$Id: imapsync,v 1.404 2011/02/21 03:35:39 gilles Exp gilles $ '; + my $rcs = '$Id: imapsync,v 1.411 2011/04/19 23:34:30 gilles Exp gilles $ '; $rcs =~ m/,v (\d+\.\d+)/; my $VERSION = ($1) ? $1: "UNKNOWN"; return($VERSION); @@ -3455,7 +3479,7 @@ Several options are mandatory. --justlogin : just login to both host1 and host2 with users credentials, then exit. --justfolders : just do things about folders (ignore messages). ---fast : be faster, equivalent to --useuid --nofoldersizes +--fast : be faster, equivalent to --nofoldersizes --reconnectretry1 : reconnect to host1 if connection is lost up to times per imap command (default is 3) --reconnectretry2 : same as --reconnectretry1 but for host2 @@ -3674,7 +3698,7 @@ sub list_folders_in_2_not_in_1 { my (@h2_folders_not_in_1, %h2_folders_not_in_1); @h2_folders_not_in_1 = list_keys_in_2_not_in_1( \%h1_folders_all, \%h2_folders_all); map { $h2_folders_not_in_1{$_} = 1} @h2_folders_not_in_1; - @h2_folders_not_in_1 = list_keys_in_2_not_in_1( \%h2_folders_from_1, \%h2_folders_not_in_1); + @h2_folders_not_in_1 = list_keys_in_2_not_in_1( \%h2_folders_from_1_all, \%h2_folders_not_in_1); return( reverse @h2_folders_not_in_1 ); } diff --git a/imapsync-1.366 b/imapsync-1.366 new file mode 100755 index 0000000..7ae5354 --- /dev/null +++ b/imapsync-1.366 @@ -0,0 +1,4310 @@ +#!/usr/bin/perl + +# structure +# pod documentation +# pragmas +# main program +# global variables initialisation +# default values +# folder loop +# subroutines +# IMAPClient 2.2.9 overrides +# IMAPClient 2.2.9 3.xx ads + +=pod + +=head1 NAME + +imapsync - IMAP synchronisation, sync, copy or migration +tool. Synchronise mailboxes between two imap servers. Good +at IMAP migration. More than 36 different IMAP server softwares +supported with success. + +$Revision: 1.366 $ + +=head1 SYNOPSIS + +To synchronise imap account "foo" on "imap.truc.org" + to imap account "bar" on "imap.trac.org" + with foo password "secret1" + and bar password "secret2": + + imapsync \ + --host1 imap.truc.org --user1 foo --password1 secret1 \ + --host2 imap.trac.org --user2 bar --password2 secret2 + +=head1 INSTALL + + imapsync works fine under any Unix OS with perl. + imapsync works fine under Windows (2000, XP) + with Strawberry Perl 5.10 or 5.12 + or as a standalone binary software imapsync.exe + +imapsync is already available directly on the following distributions +(at least): +FreeBSD, Debian, Ubuntu, Gentoo, Fedora, +NetBSD, Darwin, Mandriva and OpenBSD (yeah!). + + Get imapsync at + http://www.linux-france.org/prj/imapsync/ + + You'll find a compressed tarball called imapsync-x.xx.tgz + where x.xx is the version number. Untar the tarball where + you want (on Unix): + + tar xzvf imapsync-x.xx.tgz + + Go into the directory imapsync-x.xx and read the INSTALL file. + The INSTALL file is also at + http://www.linux-france.org/prj/imapsync/INSTALL + + The freshmeat record is at http://freshmeat.net/projects/imapsync/ + +=head1 USAGE + + imapsync [options] + +To get a description of each option just run imapsync like this: + + imapsync --help + imapsync + +The option list: + + imapsync [--host1 server1] [--port1 ] + [--user1 ] [--passfile1 ] + [--host2 server2] [--port2 ] + [--user2 ] [--passfile2 ] + [--ssl1] [--ssl2] + [--tls1] [--tls2] + [--authmech1 ] [--authmech2 ] + [--noauthmd5] + [--folder --folder ...] + [--folderrec --folderrec ...] + [--include ] [--exclude ] + [--prefix2 ] [--prefix1 ] + [--regextrans2 --regextrans2 ...] + [--sep1 ] + [--sep2 ] + [--justfolders] [--justfoldersizes] [--justconnect] [--justbanner] + [--syncinternaldates] + [--idatefromheader] + [--buffersize ] + [--syncacls] + [--regexmess ] [--regexmess ] + [--maxsize ] + [--minsize ] + [--maxage ] + [--minage ] + [--skipheader ] + [--useheader ] [--useheader ] + [--skipsize] [--allowsizemismatch] + [--delete] [--delete2] + [--expunge] [--expunge1] [--expunge2] [--uidexpunge2] + [--subscribed] [--subscribe] [--subscribe_all] + [--nofoldersizes] + [--dry] + [--debug] [--debugimap][--debugimap1][--debugimap2] + [--timeout ] [--fast] + [--split1] [--split2] + [--reconnectretry1 ] [--reconnectretry2 ] + [--pidfile ] + [--tmpdir ] + [--version] [--help] + +=cut +# comment + +=pod + +=head1 DESCRIPTION + +The command imapsync is a tool allowing incremental and +recursive imap transfer from one mailbox to another. + +By default all folders are transferred, recursively. + +We sometimes need to transfer mailboxes from one imap server to +another. This is called migration. + +imapsync is a good tool because it reduces the amount +of data transferred by not transferring a given message if it +is already on both sides. Same headers +and the transfer is done only once. All flags are +preserved, unread will stay unread, read will stay read, +deleted will stay deleted. You can stop the transfer at any +time and restart it later, imapsync works well with bad +connections. imapsync is CPU hungry so nice and renice +commands can be a good help. imapsync can be memory hungry too, +especially with large messages. + +You can decide to delete the messages from the source mailbox +after a successful transfer (it is a good feature when migrating). +In that case, use the --delete --expunge1 options. + +You can also just synchronize a mailbox A from another mailbox B +in case you just want to keep a "live" copy of B in A (--delete2 +may help) + +=head1 OPTIONS + +To get a description of each option just invoke: + +imapsync --help + +=head1 HISTORY + +I wrote imapsync because an enterprise (basystemes) paid me to install +a new imap server without losing huge old mailboxes located on a far +away remote imap server accessible by a low bandwidth link. The tool +imapcp (written in python) could not help me because I had to verify +every mailbox was well transferred and delete it after a good +transfer. imapsync started life as a copy_folder.pl patch. +The tool copy_folder.pl comes from the Mail-IMAPClient-2.1.3 perl +module tarball source (in the examples/ directory of the tarball). + +=head1 EXAMPLE + +While working on imapsync parameters please run imapsync in +dry mode (no modification induced) with the --dry +option. Nothing bad can be done this way. + +To synchronize the imap account "buddy" (with password "secret1") +on host "imap.src.fr" to the imap account "max" (with password "secret2") +on host "imap.dest.fr": + + imapsync --host1 imap.src.fr --user1 buddy --password1 secret1 \ + --host2 imap.dest.fr --user2 max --password2 secret2 + +Then you will have max's mailbox updated from buddy's +mailbox. + +=head1 SECURITY + +You can use --passfile1 instead of --password1 to give the +password since it is safer. With --password1 option any user +on your host can see the password by using the 'ps auxwwww' +command. Using a variable (like $PASSWORD1) is also +dangerous because of the 'ps auxwwwwe' command. So, saving +the password in a well protected file (600 or rw-------) is +the best solution. + +imasync is not totally protected against sniffers on the +network since passwords may be transferred in plain text +if CRAM-MD5 is not supported by your imap servers. Use +--ssl1 (or --tls1) and --ssl2 (or --tls2) to enable +encryption on host1 and host2. + +You may authenticate as one user (typically an admin user), +but be authorized as someone else, which means you don't +need to know every user's personal password. Specify +--authuser1 "adminuser" to enable this on host1. In this +case, --authmech1 PLAIN will be used by default since it +is the only way to go for now. So don't use --authmech1 SOMETHING +with --authuser1 "adminuser", it will not work. +Same behavior with the --authuser2 option. + + +=head1 EXIT STATUS + +imapsync will exit with a 0 status (return code) if everything went good. +Otherwise, it exits with a non-zero status. + +So if you have an unreliable internet connection, you can use this loop +in a Bourne shell: + + while ! imapsync ...; do + echo imapsync not complete + done + +=head1 LICENSE + +imapsync is free, gratis and open source software cover by +the Do What The Fuck You Want To Public License (WTFPL). +See COPYING file included in the distribution or the web site +http://sam.zoy.org/wtfpl/COPYING + +=head1 MAILING-LIST + +The public mailing-list may be the best way to get support. + +To write on the mailing-list, the address is: + + +To subscribe, send any message (even empty) to: + +then just reply to the confirmation message. + +To unsubscribe, send a message to: + + +To contact the person in charge for the list: + + +The list archives may be available at: +http://www.linux-france.org/prj/imapsync_list/ +So consider that the list is public, anyone +can see your post. Use a pseudonym or do not +post to this list if you want to stay private. + +Thank you for your participation. + +=head1 AUTHOR + +Gilles LAMIRAL + +Feedback good or bad is always welcome. + +The newsgroup comp.mail.imap may be a good place to talk about +imapsync. I read it when imapsync is concerned. +A better place is the public imapsync mailing-list +(see below). + +Gilles LAMIRAL earns his living writing, installing, +configuring and teaching free, open and gratis +softwares. Do not hesitate to pay him for that services. + +=head1 BUG REPORT GUIDELINES + +Help us to help you: follow the following guidelines. + +Report any bugs or feature requests to the public mailing-list +or to the author. + +Before reporting bugs, read the FAQ, the README and the +TODO files. http://www.linux-france.org/prj/imapsync/ + +Upgrade to last imapsync release, maybe the bug +is already fixed. + +Upgrade to last Mail-IMAPClient Perl module. +http://search.cpan.org/dist/Mail-IMAPClient/ +maybe the bug is already fixed. + +Make a good title with word "imapsync" in it (my spam filter won't filter it), +Don't write an email title with just "imapsync" or "problem", +a good title is made of keywords summary, not too long (one visible line). + +Don't write imapsync in uppercase in the email title, we'll +know you run windows(tm) and you haven't read the README yet. + +Help us to help you: in your report, please include: + + - imapsync version. + + - output given with --debug --debugimap near the failure point. + Isolate a message or two in a folder 'BUG' and use + + imapsync ... --folder 'BUG' --debug --debugimap + + - imap server software on both side and their version number. + + - imapsync with all the options you use, the full command line + you use (except the passwords of course). + + - IMAPClient.pm version. + + - operating system running imapsync. + + - operating systems on both sides and the third side in case + you run imapsync on a foreign host from the both. + + - virtual software context (vmware, xen etc.) + +Most of those values can be found as a copy/paste at the begining of the output. + +One time in your life, read the paper +"How To Ask Questions The Smart Way" +http://www.catb.org/~esr/faqs/smart-questions.html +and then forget it. + +=head1 IMAP SERVERS + +Failure stories reported with the following 4 imap servers: + + - MailEnable 1.54 (Proprietary) http://www.mailenable.com/ + - DBMail 0.9, 2.0.7 (GPL). But DBMail 1.2.1 works. + Patient and confident testers are welcome. + - dkimap4 2.39 + - Imail 7.04 (maybe). + +Success stories reported with the following 36 imap servers +(software names are in alphabetic order): + + - 1und1 H mimap1 84498 [host1] + - Archiveopteryx 2.03, 2.04, 2.09, 2.10 [host2], 3.0.0 [host2] + (OSL 3.0) http://www.archiveopteryx.org/ + - BincImap 1.2.3 (GPL) (http://www.bincimap.org/) + - CommuniGatePro server (Redhat 8.0) (Solaris), CommuniGate Pro 5.2.17[host2] (CentOS 5.4) + - Courier IMAP 1.5.1, 2.2.0, 2.1.1, 2.2.1, 3.0.8, 3.0.3, 4.1.1 (GPL) + (http://www.courier-mta.org/) + - Critical Path (7.0.020) + - Cyrus IMAP 1.5, 1.6, 2.1, 2.1.15, 2.1.16, 2.1.18 + 2.2.1, 2.2.2-BETA, 2.2.10, 2.2.12, + v2.2.3-Invoca-RPM-2.2.3-8, + 2.3-alpha (OSI Approved), + v2.2.12-Invoca-RPM-2.2.12-3.RHEL4.1, + 2.2.13, + v2.3.1-Invoca-RPM-2.3.1-2.7.fc5, + v2.3.7, + (http://asg.web.cmu.edu/cyrus/) + - David Tobit V8 (proprietary Message system). + - DBMail 1.2.1, 2.0.4, 2.0.9, 2.2rc1 (GPL) (http://www.dbmail.org/). + 2.0.7 seems buggy. + - Deerfield VisNetic MailServer 5.8.6 [host1] + - Domino (Notes) 4.61[host1], 6.5, 5.0.6, 5.0.7, 7.0.2, 6.0.2CF1, 7.0.1[host1], 8.0.1[host1] + - Dovecot 0.99.10.4, 0.99.14, 0.99.14-8.fc4, 1.0-0.beta2.7, + 1.0.0 [dest/source] (LGPL) (http://www.dovecot.org/) + - Eudora WorldMail v2 + - GMX IMAP4 StreamProxy. + - Groupwise IMAP (Novell) 6.x and 7.0. Buggy so see the FAQ. + - iPlanet Messaging server 4.15, 5.1, 5.2 + - IMail 7.15 (Ipswitch/Win2003), 8.12 + - MDaemon 7.0.1, 8.0.2, 8.1, 9.5.4 (Windows server 2003 R2 platform) + - Mercury 4.1 (Windows server 2000 platform) + - Microsoft Exchange Server 5.5, 6.0.6249.0[host1], 6.0.6487.0[host1], + 6.5.7638.1 [host2], Exchange 2007 SP1 (with Update Rollup 2), + Exchange2007-EP-SP2, + Exchange 2010 RTM (Release to Manufacturing) [host2] + - Netscape Mail Server 3.6 (Wintel !) + - Netscape Messaging Server 4.15 Patch 7 + - OpenMail IMAP server B.07.00.k0 (Samsung Contact ?) + - OpenWave + - Qualcomm Worldmail (NT) + - Rockliffe Mailsite 5.3.11, 4.5.6 + - Samsung Contact IMAP server 8.5.0 + - Scalix v10.1, 10.0.1.3, 11.0.0.431 + - SmarterMail, Smarter Mail 5.0 Enterprise. + - SunONE Messaging server 5.2, 6.0 (SUN JES - Java Enterprise System) + - Sun Java(tm) System Messaging Server 6.2-2.05, 6.2-7.05 + - Sun Messaging Server 6.3 + - Surgemail 3.6f5-5 + - UW-imap servers (imap-2000b) rijkkramer IMAP4rev1 2000.287 + (RedHat uses UW like 2003.338rh), v12.264 Solaris 5.7 (OSI Approved) + (http://www.washington.edu/imap/) + - UW - QMail v2.1 + - Imap part of TCP/IP suite of VMS 7.3.2 + - Zimbra-IMAP 3.0.1 GA 160, 3.1.0 Build 279, 4.0.5, 4.5.2, 4.5.6, 5.5, 6.x + +Please report to the author any success or bad story with +imapsync and do not forget to mention the IMAP server +software names and version on both sides. This will help +future users. To help the author maintaining this section +report the two lines at the begining of the output if they +are useful to know the softwares. Example: + + Host1 software:* OK louloutte Cyrus IMAP4 v1.5.19 server ready + Host2 software:* OK Courier-IMAP ready + +You can use option --justconnect to get those lines. +Example: + + imapsync --host1 imap.troc.org --host2 imap.trac.org --justconnect + +Please rate imapsync at http://freshmeat.net/projects/imapsync/ +or better give the author a book, he likes books: +http://www.amazon.com/gp/registry/wishlist/1C9UNDIH3P7R7/ +(or its paypal account gilles.lamiral@laposte.net) + +=head1 HUGE MIGRATION + +Pay special attention to options +--subscribed +--subscribe +--delete +--delete2 +--expunge +--expunge1 +--expunge2 +--uidexpunge2 +--maxage +--minage +--maxsize +--useheader +--fast + +If you have many mailboxes to migrate think about a little +shell program. Write a file called file.csv (for example) +containing users and passwords. +The separator used in this example is ';' + +The file.csv file contains: + +user0001;password0001;user0002;password0002 +user0011;password0011;user0012;password0012 +... + +And the shell program is just: + + { while IFS=';' read u1 p1 u2 p2; do + imapsync --user1 "$u1" --password1 "$p1" --user2 "$u2" --password2 "$p2" ... + done ; } < file.csv + +Welcome in shell programming ! + +=head1 Hacking + +Feel free to hack imapsync as the WTFPL Licence permits it. + +=head1 Links + +Entries for imapsync: + http://www.imap.org/products/showall.php + + +=head1 SIMILAR SOFTWARES + + imap_tools : http://www.athensfbc.com/imap_tools + offlineimap : http://software.complete.org/offlineimap + mailsync : http://mailsync.sourceforge.net/ + imapxfer : http://www.washington.edu/imap/ + part of the imap-utils from UW. + mailutil : replace imapxfer in + part of the imap-utils from UW. + http://www.gsp.com/cgi-bin/man.cgi?topic=mailutil + imaprepl : http://www.bl0rg.net/software/ + http://freshmeat.net/projects/imap-repl/ + imap_migrate : http://freshmeat.net/projects/imapmigration/ + imapcopy : http://home.arcor.de/armin.diehl/imapcopy/imapcopy.html + migrationtool : http://sourceforge.net/projects/migrationtool/ + imapmigrate : http://sourceforge.net/projects/cyrus-utils/ + wonko_imapsync: http://wonko.com/article/554 + see also tools/wonko_ruby_imapsync + pop2imap : http://www.linux-france.org/prj/pop2imap/ + + +Feedback (good or bad) will often be welcome. + +$Id: imapsync,v 1.366 2010/10/25 17:15:52 gilles Exp $ + +=cut + + +# pragmas + +use warnings; +++$|; +use strict; +use Carp; +use Getopt::Long; +use Mail::IMAPClient; +use Digest::MD5 qw(md5_base64); +#use Term::ReadKey; +#use IO::Socket::SSL; +use MIME::Base64; +use English; +use File::Basename; +use POSIX qw(uname SIGALRM); +use Fcntl; +use File::Spec; +use File::Path qw(mkpath rmtree); +use IO::Socket qw(:crlf SOL_SOCKET SO_KEEPALIVE); +use Errno qw(EAGAIN EPIPE ECONNRESET); + +use Test::More 'no_plan'; + +eval { require 'usr/include/sysexits.ph' }; + +use constant { + Unconnected => 0, + Connected => 1, # connected; not logged in + Authenticated => 2, # logged in; no mailbox selected + Selected => 3, # mailbox selected +}; + + +# global variables + +my( + $rcs, $pidfile, + $debug, $debugimap, $debugimap1, $debugimap2, $nb_errors, + $host1, $host2, $port1, $port2, + $user1, $user2, $password1, $password2, $passfile1, $passfile2, + @folder, @include, @exclude, @folderrec, + $prefix1, $prefix2, + @regextrans2, @regexmess, @regexflag, + $sep1, $sep2, + $syncinternaldates, + $idatefromheader, + $usedatemanip, + $syncacls, + $fastio1, $fastio2, + $maxsize, $minsize, $maxage, $minage, + $skipheader, @useheader, + $skipsize, $allowsizemismatch, $foldersizes, $buffersize, + $delete, $delete2, + $expunge, $expunge1, $expunge2, $uidexpunge2, $dry, + $justfoldersizes, + $authmd5, + $subscribed, $subscribe, $subscribe_all, + $version, $help, + $justconnect, $justfolders, $justbanner, + $fast, + $total_bytes_transferred, + $total_bytes_skipped, + $total_bytes_error, + $nb_msg_transferred, + $nb_msg_skipped, + $nb_msg_skipped_dry_mode, + $h1_nb_msg_duplicate, + $h2_nb_msg_duplicate, + $h1_nb_msg_noheader, + $h2_nb_msg_noheader, + $h1_total_bytes_duplicate, + $h2_total_bytes_duplicate, + $h1_nb_msg_deleted, + $h2_nb_msg_deleted, + $timeout, + $timestart, $timeend, $timediff, + $timesize, $timebefore, + $ssl1, $ssl2, + $tls1, $tls2, + $authuser1, $authuser2, + $authmech1, $authmech2, + $split1, $split2, + $reconnectretry1, $reconnectretry2, + $tests, $test_builder, $tests_debug, + $allow3xx, $justlogin, + $tmpdir, + $releasecheck, + $max_msg_size_in_bytes, + $modules_version, + $delete2folders, +); + +# main program + +# global variables initialisation + +$rcs = '$Id: imapsync,v 1.366 2010/10/25 17:15:52 gilles Exp $ '; + +$total_bytes_transferred = 0; +$total_bytes_skipped = 0; +$total_bytes_error = 0; +$nb_msg_transferred = 0; +$nb_msg_skipped = $nb_msg_skipped_dry_mode = 0; +$h1_nb_msg_deleted = $h2_nb_msg_deleted = 0; +$h1_nb_msg_duplicate = $h2_nb_msg_duplicate = 0; +$h1_nb_msg_noheader = $h2_nb_msg_noheader = 0; +$h1_total_bytes_duplicate = $h2_total_bytes_duplicate = 0; + +$nb_errors = 0; +$max_msg_size_in_bytes = 0; + +unless(defined(&_SYSEXITS_H)) { + # 64 on my linux box. + eval 'sub EX_USAGE () {64;}' unless defined(&EX_USAGE); +} + +# @ARGV will be eat by get_options() +my @argv_copy = @ARGV; + +get_options(); + +$modules_version = defined($modules_version) ? $modules_version : 1; + +$releasecheck = defined($releasecheck) ? $releasecheck : 1; +my $warn_release = ($releasecheck) ? check_last_release() : ''; + +# default values + +$tmpdir ||= File::Spec->tmpdir(); +$pidfile ||= $tmpdir . '/imapsync.pid'; + +# allow Mail::IMAPClient 3.0.xx by default +$allow3xx = defined($allow3xx) ? $allow3xx : 1; + +print banner_imapsync(@argv_copy); + +print "Temp directory is $tmpdir\n"; + +is_valid_directory($tmpdir); +write_pidfile($pidfile) if ($pidfile); + +$modules_version and print "Modules version list:\n", modules_VERSION(), "\n"; + +check_lib_version() or + die "imapsync needs perl lib Mail::IMAPClient release 2.2.9, or 3.0.25 or superior \n"; + +exit_clean(0) if ($justbanner); + +# By default, 1000 at a time, not more. +$split1 ||= 1000; +$split2 ||= 1000; + +$host1 || missing_option("--host1") ; +$port1 ||= (defined $ssl1 and !defined $tls1) ? 993 : 143; + +$host2 || missing_option("--host2") ; +$port2 ||= (defined $ssl2 && !defined $tls2) ? 993 : 143; + +$debugimap1 = $debugimap2 = 1 if ($debugimap); + +# By default, don't take size to compare +$skipsize = (defined $skipsize) ? $skipsize : 1; + + +if ($justconnect) { + justconnect(); + exit_clean(0); +} + +$user1 || missing_option("--user1"); +$user2 || missing_option("--user2"); + +$syncinternaldates = defined($syncinternaldates) ? $syncinternaldates : 1; + +if($idatefromheader) { + print "Turned ON idatefromheader, ", + "will set the internal dates on host2 from the 'Date:' header line.\n"; + $syncinternaldates = 0; + +} +if ($syncinternaldates) { + print "Turned ON syncinternaldates, ", + "will set the internal dates (arrival dates) on host2 same as host1.\n"; +}else{ + print "Turned OFF syncinternaldates\n"; +} + + +if(defined($authmd5) and not($authmd5)) { + $authmech1 ||= 'LOGIN'; + $authmech2 ||= 'LOGIN'; +} +else{ + $authmech1 ||= $authuser1 ? 'PLAIN' : 'CRAM-MD5'; + $authmech2 ||= $authuser2 ? 'PLAIN' : 'CRAM-MD5'; +} + +$authmech1 = uc($authmech1); +$authmech2 = uc($authmech2); + +$authuser1 ||= $user1; +$authuser2 ||= $user2; + +print "Will try to use $authmech1 authentication on host1\n"; +print "Will try to use $authmech2 authentication on host2\n"; + +$syncacls = (defined($syncacls)) ? $syncacls : 0; +$foldersizes = (defined($foldersizes)) ? $foldersizes : 1; + +$fastio1 = (defined($fastio1)) ? $fastio1 : 0; +$fastio2 = (defined($fastio2)) ? $fastio2 : 0; + +$reconnectretry1 = (defined($reconnectretry1)) ? $reconnectretry1 : 3; +$reconnectretry2 = (defined($reconnectretry2)) ? $reconnectretry2 : 3; + +@useheader = ("ALL") unless (@useheader); + +print "Host1: imap server [$host1] port [$port1] user [$user1]\n"; +print "Host2: imap server [$host2] port [$port2] user [$user2]\n"; + +$password1 || $passfile1 || do { + $password1 = ask_for_password($authuser1 || $user1, $host1); +}; + +$password1 = (defined($passfile1)) ? firstline ($passfile1) : $password1; + +$password2 || $passfile2 || do { + $password2 = ask_for_password($authuser2 || $user2, $host2); +}; + +$password2 = (defined($passfile2)) ? firstline ($passfile2) : $password2; + +my $imap1 = (); +my $imap2 = (); + +$timestart = time(); +$timebefore = $timestart; + +$debugimap1 and print "Host1 connection\n"; +$imap1 = login_imap($host1, $port1, $user1, $password1, + $debugimap1, $timeout, $fastio1, $ssl1, $tls1, + $authmech1, $authuser1, $reconnectretry1); + +$debugimap2 and print "Host2 connection\n"; +$imap2 = login_imap($host2, $port2, $user2, $password2, + $debugimap2, $timeout, $fastio2, $ssl2, $tls2, + $authmech2, $authuser2, $reconnectretry2); + +# history + +$debug and print "Host1 Buffer I/O: ", $imap1->Buffer(), "\n"; +$debug and print "Host2 Buffer I/O: ", $imap2->Buffer(), "\n"; + + + +die_clean() unless $imap1->IsAuthenticated(); +print "Host1: state Authenticated\n"; +die_clean() unless $imap2->IsAuthenticated(); +print "Host2: state Authenticated\n"; + +print "Host1 capability: ", join(" ", $imap1->capability_update()), "\n"; +print "Host2 capability: ", join(" ", $imap2->capability_update()), "\n"; + + +exit_clean(0) if ($justlogin); + +$split1 and $imap1->Split($split1); +$split2 and $imap2->Split($split2); + +# +# Folder stuff +# + +my ( +@h1_folders_all, %h1_folders_all, @h1_folders_wanted, %requested_folder, %subscribed_folder, +@h2_folders_all, %h2_folders_all, @h2_folders_from_1, %h2_folders_from_1, +); + + +# Make a hash of subscribed folders in source server. +map { $subscribed_folder{$_} = 1 } $imap1->subscribed(); + +# All folders on host1 and host2 +@h1_folders_all = sort $imap1->folders(); +@h2_folders_all = sort $imap2->folders(); + +map { $h1_folders_all{$_} = 1} @h1_folders_all; +map { $h2_folders_all{$_} = 1} @h2_folders_all; + +if (scalar(@folder) or $subscribed or scalar(@folderrec)) { + # folders given by option --folder + if (scalar(@folder)) { + add_to_requested_folders(@folder); + } + + # option --subscribed + if ($subscribed) { + add_to_requested_folders(keys (%subscribed_folder)); + } + + # option --folderrec + if (scalar(@folderrec)) { + foreach my $folderrec (@folderrec) { + add_to_requested_folders($imap1->folders($folderrec)); + } + } +} +else { + # no include, no folder/subscribed/folderrec options => all folders + if (not scalar(@include)) { + add_to_requested_folders(@h1_folders_all); + } +} + + +# consider (optional) includes and excludes +if (scalar(@include)) { + foreach my $include (@include) { + my @included_folders = grep /$include/, @h1_folders_all; + add_to_requested_folders(@included_folders); + print "Including folders matching pattern '$include': @included_folders\n"; + } +} + +if (scalar(@exclude)) { + foreach my $exclude (@exclude) { + my @requested_folder = sort(keys(%requested_folder)); + my @excluded_folders = grep /$exclude/, @requested_folder; + remove_from_requested_folders(@excluded_folders); + print "Excluding folders matching pattern '$exclude': @excluded_folders\n"; + } +} + +# Remove no selectable folders + +foreach my $folder (keys(%requested_folder)) { + if ( not $imap1->selectable($folder)) { + print "Warning: ignoring folder $folder because it is not selectable\n"; + remove_from_requested_folders($folder); + } +} + + +my @requested_folder = sort(keys(%requested_folder)); + +@h1_folders_wanted = @requested_folder; + +my($h1_sep,$h2_sep); +# what are the private folders separators for each server ? + +$debug and print "Getting separators\n"; +$h1_sep = get_separator($imap1, $sep1, "--sep1"); +$h2_sep = get_separator($imap2, $sep2, "--sep2"); + +#my $h1_namespace = $imap1->namespace(); +#my $h2_namespace = $imap2->namespace(); +#$debug and print "Host1 namespace:\n", Data::Dumper->Dump([$h1_namespace]); +#$debug and print "Host2 namespace:\n", Data::Dumper->Dump([$h2_namespace]); + +my($h1_prefix,$h2_prefix); +$h1_prefix = get_prefix($imap1, $prefix1, "--prefix1"); +$h2_prefix = get_prefix($imap2, $prefix2, "--prefix2"); + + +print "Host1 separator and prefix: [$h1_sep][$h1_prefix]\n"; +print "Host2 separator and prefix: [$h2_sep][$h2_prefix]\n"; + + +foreach my $h1_fold (@h1_folders_wanted) { + my $h2_fold; + $h2_fold = imap2_folder_name($h1_fold); + $h2_folders_from_1{$h2_fold}++; +} + +@h2_folders_from_1 = sort keys(%h2_folders_from_1); + +if ($foldersizes) { + foldersizes("Host1", $imap1, @h1_folders_wanted); + foldersizes("Host2", $imap2, @h2_folders_from_1); +} + + +exit_clean(0) if ($justfoldersizes); + +print + "++++ Listing folders\n", + "Host1 folders list:\n", map("[$_]\n",@h1_folders_all),"\n", + "Host2 folders list:\n", map("[$_]\n",@h2_folders_all),"\n"; + +print + "Host1 subscribed folders list: ", + map("[$_] ", sort keys(%subscribed_folder)), "\n" + if ($subscribed); + +my @h2_folders_not_in_1; +@h2_folders_not_in_1 = list_folders_in_2_not_in_1(); + +print "Folders in host2 not in host1:\n", + map("[$_]\n", @h2_folders_not_in_1),"\n"; + +delete_folders_in_2_not_in_1() if $delete2folders; + +# folder loop +print "++++ Looping on each folder\n"; + +FOLDER: foreach my $h1_fold (@h1_folders_wanted) { + + last FOLDER if $imap1->IsUnconnected(); + last FOLDER if $imap2->IsUnconnected(); + + my $h2_fold = imap2_folder_name($h1_fold); + + printf("%-35s -> %-35s\n", "[$h1_fold]", "[$h2_fold]"); + unless ($imap1->select($h1_fold)) { + warn + "Host1 folder $h1_fold: Could not select: ", + $imap1->LastError, "\n"; + $nb_errors++; + next FOLDER; + } + + if ( ! exists($h2_folders_all{$h2_fold})) { + print "Host2 folder $h2_fold does not exist\n"; + print "Creating folder [$h2_fold]\n"; + unless ($dry){ + unless ($imap2->create($h2_fold)){ + warn "Couldn't create [$h2_fold]: ", + $imap2->LastError,"\n"; + $nb_errors++; + next FOLDER; + } + } + else{ + next FOLDER; + } + } + + acls_sync($h1_fold, $h2_fold); + + unless ($imap2->select($h2_fold)) { + warn + "Host2 folder $h2_fold: Could not select: ", + $imap2->LastError, "\n"; + $nb_errors++; + next FOLDER; + } + my @select_results = $imap2->Results(); + + #print "%%% @select_results\n"; + my $permanentflags2 = permanentflags(@select_results); + + if ($expunge){ + print "Expunging host1 $h1_fold\n"; + unless($dry) { $imap1->expunge() }; + #print "Expunging host2 $h2_fold\n"; + #unless($dry) { $imap2->expunge() }; + } + + if (($subscribe and exists $subscribed_folder{$h1_fold}) or $subscribe_all) { + print "Subscribing to folder $h2_fold on destination server\n"; + unless($dry) { $imap2->subscribe($h2_fold) }; + } + + next FOLDER if ($justfolders); + + last FOLDER if $imap1->IsUnconnected(); + last FOLDER if $imap2->IsUnconnected(); + + my @h1_msgs = select_msgs($imap1); + + $debug and print "LIST Host1: ", scalar(@h1_msgs), " messages [@h1_msgs]\n"; + # internal dates on host2 are after the ones on host1 + # normally... + my @h2_msgs = select_msgs($imap2); + + $debug and print "LIST Host2: ", scalar(@h2_msgs), " messages [@h2_msgs]\n"; + + my %h1_hash = (); + my %h2_hash = (); + + $debug and print "Host1 folder [$h1_fold] parsing headers\n"; + last FOLDER if $imap1->IsUnconnected(); + last FOLDER if $imap2->IsUnconnected(); + + my ($h1_heads_ref, $h1_fir_ref) = ({}, {}); + $h1_heads_ref = $imap1->parse_headers([@h1_msgs], @useheader) if (@h1_msgs); + $debug and print "Time headers: ", timenext(), " s\n"; + last FOLDER if $imap1->IsUnconnected(); + + @$h1_fir_ref{@h1_msgs} = (undef); + $h1_fir_ref = $imap1->fetch_hash_2("FLAGS", "INTERNALDATE", "RFC822.SIZE", $h1_fir_ref) + if (@h1_msgs); + $debug and print "Time fir: ", timenext(), " s\n"; + unless ($h1_fir_ref) { + warn + "Host1 folder $h1_fold: Could not fetch_hash_2 ", + scalar(@h1_msgs), " msgs: ", $imap1->LastError, "\n"; + $nb_errors++; + next FOLDER; + } + last FOLDER if $imap1->IsUnconnected(); + + + my @h1_msgs_duplicate; + foreach my $m (@h1_msgs) { + my $rc = parse_header_msg($imap1, $m, $h1_heads_ref, $h1_fir_ref, "F", \%h1_hash); + if (! defined($rc)) { + my $h1_size = $h1_fir_ref->{$m}->{"RFC822.SIZE"} || 0; + print "+ Skipping msg #$m:$h1_size on host1 folder $h1_fold (no header so we ignore this message)\n"; + $total_bytes_skipped += $h1_size; + $nb_msg_skipped += 1; + $h1_nb_msg_noheader +=1; + } elsif(0 == $rc) { + # duplicate + push(@h1_msgs_duplicate, $m); + # duplicate, same id same size? + my $h1_size = $h1_fir_ref->{$m}->{"RFC822.SIZE"} || 0; + $nb_msg_skipped += 1; + $h1_total_bytes_duplicate += $h1_size; + $h1_nb_msg_duplicate += 1; + } + } + $debug and print "Time parsing headers on host1: ", timenext(), " s\n"; + + $debug and print "Host2 folder [$h2_fold] parsing headers\n"; + + my ($h2_heads_ref, $h2_fir_ref) = ({}, {}); + $h2_heads_ref = $imap2->parse_headers([@h2_msgs], @useheader) if (@h2_msgs); + $debug and print "Time headers: ", timenext(), " s\n"; + last FOLDER if $imap2->IsUnconnected(); + + @$h2_fir_ref{@h2_msgs} = (undef); # fetch_hash_2 can select by uid with last arg as ref + $h2_fir_ref = $imap2->fetch_hash_2("FLAGS", "INTERNALDATE", "RFC822.SIZE", $h2_fir_ref) + if (@h2_msgs); + $debug and print "Time fir: ", timenext(), " s\n"; + last FOLDER if $imap2->IsUnconnected(); + + my @h2_msgs_duplicate; + foreach my $m (@h2_msgs) { + my $rc = parse_header_msg($imap2, $m, $h2_heads_ref, $h2_fir_ref, "T", \%h2_hash); + if (! defined($rc)) { + my $h2_size = $h2_fir_ref->{$m}->{"RFC822.SIZE"} || 0; + print "+ Skipping msg #$m:$h2_size in host2 folder $h2_fold (no header so we ignore this message)\n"; + $h2_nb_msg_noheader += 1 ; + } elsif(0 == $rc) { + # duplicate + my $h2_size = $h2_fir_ref->{$m}->{"RFC822.SIZE"} || 0; + $h2_nb_msg_duplicate += 1; + $h2_total_bytes_duplicate += $h2_size; + push(@h2_msgs_duplicate, $m); + } + } + $debug and print "Time parsing headers on host2: ", timenext(), " s\n"; + + $debug and print "++++ Verifying [$h1_fold] -> [$h2_fold]\n"; + # messages in host1 that are not in host2 + + my @h1_hash_keys_sorted_by_uid + = sort {$h1_hash{$a}{'m'} <=> $h1_hash{$b}{'m'}} keys(%h1_hash); + + #print map { $h1_hash{$_}{'m'} . " "} @h1_hash_keys_sorted_by_uid; + + my @h2_hash_keys_sorted_by_uid + = sort {$h2_hash{$a}{'m'} <=> $h2_hash{$b}{'m'}} keys(%h2_hash); + + + if($delete2) { + my @h2_expunge; + foreach my $m_id (@h2_hash_keys_sorted_by_uid) { + #print "$m_id "; + unless (exists($h1_hash{$m_id})) { + my $h2_msg = $h2_hash{$m_id}{'m'}; + my $h2_flags = $h2_hash{$m_id}{'F'} || ""; + my $isdel = $h2_flags =~ /\B\\Deleted\b/ ? 1 : 0; + print "msg $h2_fold/$h2_msg deleted on host2 [$m_id]\n" + if ! $isdel; + push(@h2_expunge, $h2_msg) if $uidexpunge2; + unless ($dry or $isdel) { + $imap2->delete_message($h2_msg); + $h2_nb_msg_deleted += 1; + } + } + } + foreach my $h2_msg (@h2_msgs_duplicate) { + print "msg $h2_fold/$h2_msg deleted [duplicate] on host2\n"; + push(@h2_expunge, $h2_msg) if $uidexpunge2; + unless ($dry) { + $imap2->delete_message($h2_msg); + $h2_nb_msg_deleted += 1; + } + } + + my $cnt = scalar @h2_expunge; + if(@h2_expunge and !$imap2->can("uidexpunge")) { + warn "uidexpunge not supported (< IMAPClient 3.17)\n"; + } + elsif(@h2_expunge) { + print "uidexpunge $cnt message(s)\n"; + $imap2->uidexpunge(\@h2_expunge) if !$dry; + } + } + + MESS: foreach my $m_id (@h1_hash_keys_sorted_by_uid) { + my $h1_size = $h1_hash{$m_id}{'s'}; + my $h1_msg = $h1_hash{$m_id}{'m'}; + my $h1_idate = $h1_hash{$m_id}{'D'}; + + if (defined $maxsize and $h1_size >= $maxsize) { + print "msg $h1_fold/$h1_msg skipping ($h1_size exceeds maxsize limit $maxsize bytes)\n"; + $total_bytes_skipped += $h1_size; + $nb_msg_skipped += 1; + next MESS; + } + if (defined $minsize and $h1_size <= $minsize) { + print "msg $h1_fold/$h1_msg skipping ($h1_size smaller than minsize $minsize bytes)\n"; + $total_bytes_skipped += $h1_size; + $nb_msg_skipped += 1; + next MESS; + } + + unless (exists($h2_hash{$m_id})) { + # copy + $debug and print "msg $h1_fold/$h1_msg copying to $h2_fold\n"; + last FOLDER if $imap1->IsUnconnected(); + last FOLDER if $imap2->IsUnconnected(); + my $string; + #print "Message_string Beg\n", memory_consumption(); + $string = $imap1->message_string($h1_msg); + #print "Message_string End\n", memory_consumption(); + unless (defined($string)) { + warn + "- msg $h1_fold/$h1_msg could not fetch [$m_id $h1_size]: ", + $imap1->LastError, "\n"; + $nb_errors++; + $total_bytes_error += $h1_size; + next MESS; + } + + #my $message_file = "tmp_imapsync_$$"; + #$imap1->select($h1_fold); + #unlink($message_file); + #$imap1->message_to_file($message_file, $h1_msg) or do { + # warn "Could not put message #$h1_msg to file $message_file", + # $imap1->LastError; + # $nb_errors++; + # $total_bytes_error += $h1_size; + # next MESS; + #}; + #$string = file_to_string($message_file); + #print "AAA1[$string]ZZZ\n"; + #unlink($message_file); + if (@regexmess) { + $string = regexmess($string); + + #string_to_file($string, $message_file); + } + + + $debug and print + "=" x80, "\n", + "F message content begin next line\n", + $string, + "F message content ended on previous line\n", "=" x 80, "\n"; + my $h1_date = ""; + if ($syncinternaldates) { + $h1_date = $h1_idate; + $debug and print "internal date from host1: [$h1_date]\n"; + $h1_date = good_date($h1_date); + $debug and print "internal date from host1: [$h1_date] (fixed)\n"; + } + + if ($idatefromheader) { + + $h1_date = $imap1->get_header($h1_msg,"Date"); + $debug and print "header date from host1: [$h1_date]\n"; + $h1_date = good_date($h1_date); + $debug and print "header date from host1: [$h1_date] (fixed)\n"; + } + + my $h1_flags = $h1_hash{$m_id}{'F'} || ""; + # RFC 2060: This flag can not be altered by any client + $h1_flags =~ s@\\Recent\s?@@gi; + $h1_flags = flags_regex($h1_flags) if @regexflag; + + $h1_flags = flags_filter($h1_flags, $permanentflags2) if ($permanentflags2); + + my $new_id; + $debug and print "msg $h1_fold/$h1_msg date [$h1_date] flags [$h1_flags] size [$h1_size]\n"; + last FOLDER if $imap1->IsUnconnected(); + last FOLDER if $imap2->IsUnconnected(); + $h1_date = undef if ($h1_date eq ""); + + unless ($dry) { + $max_msg_size_in_bytes = max($h1_size, $max_msg_size_in_bytes); + $new_id = $imap2->append_string($h2_fold, $string, $h1_flags, $h1_date); + unless($new_id){ + no warnings 'uninitialized'; + warn "- msg $h1_fold/$h1_msg couldn't append (Subject:[". + $imap1->subject($h1_msg)."]) to folder $h2_fold: ", + $imap2->LastError, "\n"; + $nb_errors++; + $total_bytes_error += $h1_size; + next MESS; + } + else{ + # good + # $new_id is an id if the IMAP server has the + # UIDPLUS capability else just a ref + print "msg $h1_fold/$h1_msg copied to $h2_fold/$new_id\n"; + $total_bytes_transferred += $h1_size; + $nb_msg_transferred += 1; + if($delete) { + print "msg $h1_fold/$h1_msg deleted on host1\n"; + unless($dry) { + $imap1->delete_message($h1_msg); + $h1_nb_msg_deleted += 1; + last FOLDER if $imap1->IsUnconnected(); + $imap1->expunge() if ($expunge); + last FOLDER if $imap1->IsUnconnected(); + } + } + } + } + else{ + $nb_msg_skipped_dry_mode += 1; + } + #unlink($message_file); + next MESS; + } + else{ + #my $h2_size = $h2_hash{$m_id}{'s'}; + my $h2_msg = $h2_hash{$m_id}{'m'}; + #my $h2_idate = $h2_hash{$m_id}{'D'}; + $debug and print "msg $h1_fold/$h1_msg equals $h2_fold/$h2_msg\n"; + $total_bytes_skipped += $h1_size; + $nb_msg_skipped += 1; + } + + $fast and next MESS; + #$debug and print "MESSAGE $m_id\n"; + my $h2_size = $h2_hash{$m_id}{'s'}; + my $h2_msg = $h2_hash{$m_id}{'m'}; + + # used cached flag values for efficiency + my $h1_flags = $h1_hash{$m_id}{'F'} || ""; + my $h2_flags = $h2_hash{$m_id}{'F'} || ""; + + # RFC 2060: This flag can not be altered by any client + $h1_flags =~ s@\\Recent\s?@@gi; + $h1_flags = flags_regex($h1_flags) if @regexflag; + $h1_flags = flags_filter($h1_flags, $permanentflags2) if ($permanentflags2); + + + # compare flags - set flags if there a difference + my @h1_flags = sort split(' ', $h1_flags ); + my @h2_flags = sort split(' ', $h2_flags ); + my $diff = compare_lists(\@h1_flags, \@h2_flags); + + $diff and $debug and print "msg $h2_fold/$h2_msg replacing h2 flags($h2_flags) with h1 flags($h1_flags)\n"; + + # This sets flags so flags can be removed with this + # When you remove a \Seen flag on host1 you want to it + # to be removed on host2. Just add flags is not what + # we need most of the time. + + if (!$dry and $diff and !$imap2->store($h2_msg, "FLAGS.SILENT (@h1_flags)") ) { + warn "- msg $h2_fold/$h2_msg could not add flags @h1_flags", + $imap2->LastError, "\n"; + #$nb_errors++; + } + last FOLDER if $imap2->IsUnconnected(); + + $debug and do { + my @h2_flags = @{ $imap2->flags($h2_msg) || [] }; + last FOLDER if $imap2->IsUnconnected(); + + print "host1 flags: $h1_flags\n", + "host2 flags: @h2_flags\n"; + + print "Looking dates\n"; + #my $h1_idate = $imap1->internaldate($h1_msg); + #my $h2_idate = $imap2->internaldate($h2_msg); + my $h1_idate = $h1_hash{$m_id}{'D'}; + my $h2_idate = $h2_hash{$m_id}{'D'}; + print + "host1 internal date: $h1_idate\n", + "host2 internal date: $h2_idate\n"; + + #unless ($h1_idate eq $h2_idate) { + # print "!!! Dates differs !!!\n"; + #} + }; + unless ($skipsize or ($h1_size == $h2_size)) { + # Bad size + print + "- msg $h1_fold/$h1_msg size diff $h1_size != $h2_size $h2_fold/$h2_msg\n"; + $nb_errors++; + } + else { + # Good + $debug and print + "msg $h1_fold/$h1_msg sizes ok $h1_size <=> $h2_size $h2_fold/$h2_msg\n"; + if($delete) { + print "msg $h1_fold/$h1_msg deleted on host1\n"; + unless($dry) { + $imap1->delete_message($h1_msg); + $h1_nb_msg_deleted += 1; + $imap1->expunge() if ($expunge); + } + } + } + } + if ($expunge1){ + print "Expunging host1 folder $h1_fold\n"; + unless($dry) { $imap1->expunge() }; + } + if ($expunge2){ + print "Expunging host2 folder $h2_fold\n"; + unless($dry) { $imap2->expunge() }; + } + +$debug and print "Time: ", timenext(), " s\n"; +} + +print "++++ End looping on each folder\n"; +#print memory_consumption(); + +my $memory_consumption = memory_consumption(); +my $memory_ratio = ($max_msg_size_in_bytes) ? + sprintf('%.1f', $memory_consumption / $max_msg_size_in_bytes) : "NA"; + + +$imap1->logout(); +$imap2->logout(); + +my $host1_reconnect_count = $imap1->Reconnect_counter() || 0; +my $host2_reconnect_count = $imap2->Reconnect_counter() || 0; + + +$timeend = time(); +$timediff = $timeend - $timestart; + +stats(); +exit_clean(1) if($nb_errors); +exit_clean(0); + +# END of main program + +# subroutines + +sub max { + return(undef) if (0 == scalar(@_)); + my @sorted = sort { $a <=> $b } @_; + return(pop(@sorted)); +} + +sub tests_max { + ok(0 == max(0), "max 0"); + ok(1 == max(1), "max 1"); + ok(-1 == max(-1), "max -1"); + ok(! defined(max()), "max no arg"); + ok(100 == max(1, 100), "max 1 100"); + ok(100 == max(100, 1), "max 100 1"); + ok(100 == max(100, 42, 1), "max 100 42 1"); + ok(100 == max(100, "42", 1), "max 100 42 1"); + ok(100 == max("100", "42", 1), "max 100 42 1"); + #ok(100 == max(100, "haha", 1), "max 100 42 1"); +} + +sub check_lib_version { + $debug and print "IMAPClient $Mail::IMAPClient::VERSION\n"; + if ($Mail::IMAPClient::VERSION eq '2.2.9') { + override_imapclient(); + return(1); + } + else{ + # 3.x.x is no longer buggy with imapsync. + if ($allow3xx) { + return(1); + }else{ + return(0); + } + } +} + +sub modules_VERSION { + + my @list_version; + + foreach my $module (qw( +Mail::IMAPClient +IO::Socket +IO::Socket::SSL +Digest::MD5 +Digest::HMAC_MD5 +Term::ReadKey)) + { + my $v = "?"; + + if (eval "require $module") { + # module is here + $v = eval "\$${module}::VERSION"; + }else{ + # no module + $v = "?"; + } + #print ("$module ", $v, "\n"); + push (@list_version, sprintf("%-20s %s\n", $module, $v)); + } + return(@list_version); +} + +# Construct a command line copy with passwords replaced by MASKED. +sub command_line_nopassword { + my @argv_copy = @_; + my @argv_nopassword; + while (@argv_copy) { + my $arg = shift(@argv_copy); # option name or value + if ($arg =~ m/-password[12]/) { + shift(@argv_copy); # password value + push(@argv_nopassword, $arg, "MASKED"); # option name and fake value + }else{ + push(@argv_nopassword, $arg); # same option or value + } + } + return("@argv_nopassword"); +} + +sub tests_command_line_nopassword { + + ok('' eq command_line_nopassword(), 'command_line_nopassword void'); + ok('--blabla' eq command_line_nopassword('--blabla'), 'command_line_nopassword --blabla'); + #print command_line_nopassword((qw{ --password1 secret1 })), "\n"; + ok('--password1 MASKED' eq command_line_nopassword(qw{ --password1 secret1}), 'command_line_nopassword --password1'); + ok('--blabla --password1 MASKED --blibli' + eq command_line_nopassword(qw{ --blabla --password1 secret1 --blibli }), 'command_line_nopassword --password1 --blibli'); + + +} + +sub ask_for_password { + my ($user, $host) = @_; + print "What's the password for $user\@$host? "; + Term::ReadKey::ReadMode(2); + my $password = <>; + chomp $password; + printf "\n"; + Term::ReadKey::ReadMode(0); + return $password; +} + + +sub myconnect { + my $self = shift; + + $debug and print "Entering myconnect\n"; + %$self = (%$self, @_); + + my $sock = (($self->Ssl) ? IO::Socket::SSL->new : IO::Socket::INET->new); + my $dp = ($self->Ssl ? 'imaps(993)' : 'imap(143)'); + + $debug and print "Calling configure\n"; + my $ret = $sock->configure({ + PeerAddr => $self->Server , + PeerPort => $self->Port||$dp , + Proto => 'tcp' , + Timeout => $self->Timeout||0 , + Debug => $self->Debug , + }); + unless ( defined($ret) ) { + $self->LastError( "$@\n"); + $@ = "$@"; + carp "$@" + unless defined wantarray; + return undef; + } + $sock->autoflush(1); + + my $banner = $sock->getline(); + $debug and print "Read: $banner"; + + $self->Banner($banner); + $self->RawSocket2($sock); + $self->State(Connected); + + if ($self->Tls) { + starttls($self); + } + + $self->Ignoresizeerrors($allowsizemismatch); + + if ($self->User and $self->Password) { + $debug and print "Calling login\n"; + return $self->login ; + } + else { + return $self; + } +} + + + + +sub starttls { + my $self = shift; + my $socket = $self->RawSocket2(); + + $debug and print "Entering starttls\n"; + unless ($self->has_capability("STARTTLS")) { + die_clean( "No STARTTLS capability" ); + } + print $socket, "\n"; + print $socket "z00 STARTTLS\015\012"; + CORE::select( undef, undef, undef, 0.025 ); + my $txt = $socket->getline(); + $debug and print "Read tls: $txt"; + unless($txt =~ /^z00 OK/){ + die_clean( "Invalid response for STARTTLS: $txt\n" ); + } + $debug and print "Calling start_SSL\n"; + unless(IO::Socket::SSL->start_SSL($socket, + { + SSL_version => "TLSV1", + SSL_startHandshake => 1, + SSL_verify_depth => 1, + })) + { + die_clean( "Couldn't start TLS: ".IO::Socket::SSL::errstr()."\n"); + } + if (ref($socket) ne "IO::Socket::SSL") { + die_clean( "Socket has NOT been converted to SSL"); + }else{ + $debug and print "Socket successfuly converted to SSL\n"; + } + $debug and print "Ending starttls\n"; +} + + + +sub connect_imap { + my($host, $port, $debugimap, $ssl, $tls) = @_; + my $imap = Mail::IMAPClient->new(); + $imap->Ssl($ssl) if ($ssl); + $imap->Tls($tls) if ($tls); + $imap->Server($host); + $imap->Port($port); + $imap->Debug($debugimap); + #$imap->connect() + myconnect($imap) + or die_clean("Can not open imap connection on [$host]: $@\n"); +} + +sub justconnect { + my $imap1 = (); + my $imap2 = (); + + $imap1 = connect_imap($host1, $port1, $debugimap1, $ssl1, $tls1); + print "Host1 software: ", server_banner($imap1); + print "Host1 capability: ", join(" ", $imap1->capability()), "\n"; + $imap2 = connect_imap($host2, $port2, $debugimap2, $ssl2, $tls2); + print "Host2 software: ", server_banner($imap2); + print "Host2 capability: ", join(" ", $imap2->capability()), "\n"; + $imap1->logout(); + $imap2->logout(); + +} + + +sub login_imap { + my($host, $port, $user, $password, + $debugimap, $timeout, $fastio, + $ssl, $tls, $authmech, $authuser, $reconnectretry) = @_; + my ($imap); + + $imap = Mail::IMAPClient->new(); + + $imap->Ssl($ssl) if ($ssl); + $imap->Tls($tls) if ($tls); + $imap->Clear(1); + $imap->Server($host); + $imap->Port($port); + $imap->Fast_io($fastio); + $imap->Buffer($buffersize || 4096); + $imap->Uid(1); + $imap->Peek(1); + $imap->Debug($debugimap); + $timeout and $imap->Timeout($timeout); + + $imap->Reconnectretry($reconnectretry) if ($reconnectretry); + + #$imap->connect() + myconnect($imap) + or die_clean("Can not open imap connection on [$host] with user [$user]: $@\n"); + + print "Banner: ", server_banner($imap); + + if ($imap->has_capability("AUTH=$authmech") + or $imap->has_capability($authmech) + ) { + printf("Host %s says it has CAPABILITY for AUTHENTICATE %s\n", + $imap->Server, $authmech); + } + else { + printf("Host %s says it has NO CAPABILITY for AUTHENTICATE %s\n", + $imap->Server, $authmech); + if ($authmech eq 'PLAIN') { + print "Frequently PLAIN is only supported with SSL, ", + "try --ssl1 or --ssl2 option\n"; + } + } + + $imap->Authmechanism($authmech) unless ($authmech eq 'LOGIN'); + $imap->Authcallback(\&plainauth) if $authmech eq "PLAIN"; + + + $imap->User($user); + $imap->Authuser($authuser); + $imap->Password($password); + unless ($imap->login()) { + my $info = "Error login: [$host] with user [$user] auth"; + my $einfo = $imap->LastError || @{$imap->History}[-1]; + chomp($einfo); + my $error = "$info [$authmech]: $einfo\n"; + print $error; # note: duplicating error on stdout/stderr + die_clean($error) if ($authmech eq 'LOGIN' or $imap->IsUnconnected() or $authuser); + print "Trying LOGIN Auth mechanism on [$host] with user [$user]\n"; + $imap->Authmechanism(""); + $imap->login() or + die_clean("$info [LOGIN]: ", $imap->LastError, "\n"); + } + print "Success login on [$host] with user [$user] auth [$authmech]\n"; + return($imap); +} + + +sub plainauth() { + my $code = shift; + my $imap = shift; + + my $string = sprintf("%s\x00%s\x00%s", $imap->User, + $imap->Authuser, $imap->Password); + return encode_base64("$string", ""); +} + + +sub server_banner { + my $imap = shift; + my $banner = $imap->Banner() || "No banner\n"; + return $banner; + } + + +sub banner_imapsync { + + my @argv_copy = @_; + my $banner_imapsync = join("", + '$RCSfile: imapsync,v $ ', + '$Revision: 1.366 $ ', + '$Date: 2010/10/25 17:15:52 $ ', + "\n",localhost_info(), "\n", + "Command line used:\n", + "$0 ", command_line_nopassword(@argv_copy), "\n", + ); +} + +sub is_valid_directory { + my $dir = shift; + return(1) if (-d $dir and -r _ and -w _); + # Trying to create it + mkpath($dir) or die "Error creating tmpdir $tmpdir : $!"; + die "Error with tmpdir $tmpdir : $!" if not (-d $dir and -r _ and -w _); + return(1); +} + + + + +sub write_pidfile { + my $pidfile = shift; + + print "PID file is $pidfile\n"; + if (-e $pidfile) { + warn "$pidfile already exists, overwriting it\n"; + } + open(PIDFILE, ">$pidfile") or do { + warn "Could not open $pidfile for writing"; + return undef; + }; + + print PIDFILE $PROCESS_ID; + close PIDFILE; + return($PROCESS_ID); +} + +sub exit_clean { + my $status = shift; + + unlink($pidfile); + exit($status); +} + +sub die_clean { + + unlink($pidfile); + die @_; +} + +sub missing_option { + my ($option) = @_; + die_clean("$option option must be used, run $0 --help for help\n"); +} + + + +sub tests_folder_routines { + ok( !is_requested_folder('folder_foo') ); + ok( add_to_requested_folders('folder_foo') ); + ok( is_requested_folder('folder_foo') ); + ok( !is_requested_folder('folder_NO_EXIST') ); + ok( !remove_from_requested_folders('folder_foo'), "removed folder_foo"); + ok( !is_requested_folder('folder_foo') ); + my @f; + ok( @f = add_to_requested_folders('folder_bar', 'folder_toto'), "add result: @f"); + ok( is_requested_folder('folder_bar') ); + ok( is_requested_folder('folder_toto') ); + ok( remove_from_requested_folders('folder_toto') ); + ok( !is_requested_folder('folder_toto') ); +} + + +sub is_requested_folder { + my ( $folder ) = @_; + + defined( $requested_folder{ $folder } ); +} + + +sub add_to_requested_folders { + my @wanted_folders = @_; + + foreach my $folder ( @wanted_folders ) { + ++$requested_folder{ $folder }; + } + return( keys( %requested_folder ) ); +} + +sub remove_from_requested_folders { + my @wanted_folders = @_; + + foreach my $folder (@wanted_folders) { + delete $requested_folder{$folder}; + } + return( keys(%requested_folder) ); +} + +sub compare_lists { + my ($list_1_ref, $list_2_ref) = @_; + + return(-1) if ((not defined($list_1_ref)) and defined($list_2_ref)); + return(0) if ((not defined($list_1_ref)) and not defined($list_2_ref)); # end if no list + return(1) if (not defined($list_2_ref)); # end if only one list + + if (not ref($list_1_ref)) {$list_1_ref = [$list_1_ref]}; + if (not ref($list_2_ref)) {$list_2_ref = [$list_2_ref]}; + + + my $last_used_indice = -1; + #print "\$#$list_1_ref:", $#$list_1_ref, "\n"; + #print "\$#$list_2_ref:", $#$list_2_ref, "\n"; + ELEMENT: + foreach my $indice ( 0 .. $#$list_1_ref ) { + $last_used_indice = $indice; + + # End of list_2 + return 1 if ($indice > $#$list_2_ref); + + my $element_list_1 = $list_1_ref->[$indice]; + my $element_list_2 = $list_2_ref->[$indice]; + my $balance = $element_list_1 cmp $element_list_2 ; + next ELEMENT if ($balance == 0) ; + return $balance; + } + # each element equal until last indice of list_1 + return -1 if ($last_used_indice < $#$list_2_ref); + + # same size, each element equal + return 0 +} + +sub tests_compare_lists { + + + my $empty_list_ref = []; + + ok( 0 == compare_lists() , 'compare_lists, no args'); + ok( 0 == compare_lists(undef) , 'compare_lists, undef = nothing'); + ok( 0 == compare_lists(undef, undef) , 'compare_lists, undef = undef'); + ok(-1 == compare_lists(undef , []) , 'compare_lists, undef < []'); + ok(-1 == compare_lists(undef , [1]) , 'compare_lists, undef < [1]'); + ok(-1 == compare_lists(undef , [0]) , 'compare_lists, undef < [0]'); + ok(+1 == compare_lists([]) , 'compare_lists, [] > nothing'); + ok(+1 == compare_lists([], undef) , 'compare_lists, [] > undef'); + ok( 0 == compare_lists([] , []) , 'compare_lists, [] = []'); + + ok(-1 == compare_lists([] , [1]) , 'compare_lists, [] < [1]'); + ok(+1 == compare_lists([1] , []) , 'compare_lists, [1] > []'); + + + ok( 0 == compare_lists([1], 1 ) , "compare_lists, [1] = 1 ") ; + ok( 0 == compare_lists( 1 , [1]) , "compare_lists, 1 = [1]") ; + ok( 0 == compare_lists( 1 , 1 ) , "compare_lists, 1 = 1 ") ; + ok(-1 == compare_lists( 0 , 1 ) , "compare_lists, 0 < 1 ") ; + ok(-1 == compare_lists(-1 , 0 ) , "compare_lists, -1 < 0 ") ; + ok(-1 == compare_lists( 1 , 2 ) , "compare_lists, 1 < 2 ") ; + ok(+1 == compare_lists( 2 , 1 ) , "compare_lists, 2 > 1 ") ; + + + ok( 0 == compare_lists([1,2], [1,2]) , "compare_lists, [1,2] = [1,2]") ; + ok(-1 == compare_lists([1], [1,2]) , "compare_lists, [1] < [1,2]") ; + ok(+1 == compare_lists([2], [1,2]) , "compare_lists, [2] > [1,2]") ; + ok(-1 == compare_lists([1], [1,1]) , "compare_lists, [1] < [1,1]") ; + ok(+1 == compare_lists([1, 1], [1]) , "compare_lists, [1, 1] > [1]") ; + ok( 0 == compare_lists([1 .. 20_000] , [1 .. 20_000]) + , "compare_lists, [1..20_000] = [1..20_000]") ; + ok(-1 == compare_lists([1], [3]) , 'compare_lists, [1] < [3]') ; + ok( 0 == compare_lists([2], [2]) , 'compare_lists, [0] = [2]') ; + ok(+1 == compare_lists([3], [1]) , 'compare_lists, [3] > [1]') ; + + ok(-1 == compare_lists(["a"], ["b"]) , 'compare_lists, ["a"] < ["b"]') ; + ok( 0 == compare_lists(["a"], ["a"]) , 'compare_lists, ["a"] = ["a"]') ; + ok( 0 == compare_lists(["ab"], ["ab"]) , 'compare_lists, ["ab"] = ["ab"]') ; + ok(+1 == compare_lists(["b"], ["a"]) , 'compare_lists, ["b"] > ["a"]') ; + ok(-1 == compare_lists(["a"], ["aa"]) , 'compare_lists, ["a"] < ["aa"]') ; + ok(-1 == compare_lists(["a"], ["a", "a"]), 'compare_lists, ["a"] < ["a", "a"]') ; + ok( 0 == compare_lists([split(" ", "a b")], ["a", "b"]), 'compare_lists, split') ; + ok( 0 == compare_lists([sort split(" ", "b a")], ["a", "b"]), 'compare_lists, sort split') ; +} + + + +sub get_prefix { + my($imap, $prefix_in, $prefix_opt) = @_; + my($prefix_out); + + $debug and print "Getting prefix namespace\n"; + if (defined($prefix_in)) { + print "Using [$prefix_in] given by $prefix_opt\n"; + $prefix_out = $prefix_in; + return($prefix_out); + } + $debug and print "Calling namespace capability\n"; + if ($imap->has_capability("namespace")) { + my $r_namespace = $imap->namespace(); + $prefix_out = $r_namespace->[0][0][0]; + return($prefix_out); + } + else{ + print + "No NAMESPACE capability in imap server ", + $imap->Server(),"\n", + "Give the prefix namespace with the $prefix_opt option\n"; + exit_clean(1); + } +} + + +sub get_separator { + my($imap, $sep_in, $sep_opt) = @_; + my($sep_out); + + + if ($sep_in) { + print "Using [$sep_in] given by $sep_opt\n"; + $sep_out = $sep_in; + return($sep_out); + } + $debug and print "Calling namespace capability\n"; + if ($imap->has_capability("namespace")) { + $sep_out = $imap->separator(); + return($sep_out) if defined $sep_out; + warn + "NAMESPACE request failed for ", + $imap->Server(), ": ", $imap->LastError, "\n"; + exit_clean(1); + } + else{ + warn + "No NAMESPACE capability in imap server ", + $imap->Server(),"\n", + "Give the separator character with the $sep_opt option\n"; + exit_clean(1); + } +} + +sub separator_invert { + # The separator we hope we'll never encounter: 00000000 + my $o_sep="\000"; + + my($h1_fold, $h1_sep, $h2_sep) = @_; + + my $h2_fold = $h1_fold; + $h2_fold =~ s@\Q$h2_sep@$o_sep@g; + $h2_fold =~ s@\Q$h1_sep@$h2_sep@g; + $h2_fold =~ s@\Q$o_sep@$h1_sep@g; + return($h2_fold); +} + + +sub tests_imap2_folder_name { + +$h1_prefix = $h2_prefix = ''; +$h1_sep = '/'; +$h2_sep = '.'; + +$debug and print +"prefix1: [$h1_prefix] +prefix2: [$h2_prefix] +sep1:[$h1_sep] +sep2:[$h2_sep] +"; + +ok('' eq imap2_folder_name(''), 'imap2_folder_name: empty string'); +ok('blabla' eq imap2_folder_name('blabla'), 'imap2_folder_name: blabla'); +ok('spam.spam' eq imap2_folder_name('spam/spam'), 'imap2_folder_name: spam/spam'); +ok('spam/spam' eq imap2_folder_name('spam.spam'), 'imap2_folder_name: spam.spam'); +ok('spam.spam/spam' eq imap2_folder_name('spam/spam.spam'), 'imap2_folder_name: spam/spam.spam'); +@regextrans2 = ('s,/,X,g'); +ok('' eq imap2_folder_name(''), 'imap2_folder_name: empty string [s,/,X,g]'); +ok('blabla' eq imap2_folder_name('blabla'), 'imap2_folder_name: blabla [s,/,X,g]'); +ok('spam.spam' eq imap2_folder_name('spam/spam'), 'imap2_folder_name: spam/spam [s,/,X,g]'); +ok('spamXspam' eq imap2_folder_name('spam.spam'), 'imap2_folder_name: spam.spam [s,/,X,g]'); +ok('spam.spamXspam' eq imap2_folder_name('spam/spam.spam'), 'imap2_folder_name: spam/spam.spam [s,/,X,g]'); + +@regextrans2 = ('s, ,_,g'); +ok('blabla' eq imap2_folder_name('blabla'), 'imap2_folder_name: blabla [s, ,_,g]'); +ok('bla_bla' eq imap2_folder_name('bla bla'), 'imap2_folder_name: blabla [s, ,_,g]'); + +@regextrans2 = ('s,(.*),\U$1,'); +ok('BLABLA' eq imap2_folder_name('blabla'), 'imap2_folder_name: blabla [s,\U(.*)\E,$1,]'); + + +} + +sub imap2_folder_name { + my ($h2_fold); + my ($x_fold) = @_; + # first we remove the prefix + $x_fold =~ s/^\Q$h1_prefix\E//; + $debug and print "removed host1 prefix: [$x_fold]\n"; + $h2_fold = separator_invert($x_fold,$h1_sep, $h2_sep); + $debug and print "inverted separators: [$h2_fold]\n"; + # Adding the prefix supplied by namespace or the --prefix2 option + $h2_fold = $h2_prefix . $h2_fold + unless(($h2_prefix eq "INBOX" . $h2_sep) and ($h2_fold =~ m/^INBOX$/i)); + $debug and print "added host2 prefix: [$h2_fold]\n"; + + # Transforming the folder name by the --regextrans2 option(s) + foreach my $regextrans2 (@regextrans2) { + my $h2_fold_before = $h2_fold; + eval("\$h2_fold =~ $regextrans2"); + $debug and print "[$h2_fold_before] -> [$h2_fold] using re [$regextrans2]\n"; + die_clean("error: eval regextrans2 '$regextrans2': $@\n") if $@; + } + return($h2_fold); +} + + +sub foldersizes { + + my ($side, $imap, @folders) = @_; + my $tot = 0; + my $tmess = 0; + + print "++++ Calculating sizes\n"; + foreach my $folder (@folders) { + my $stot = 0; + my $smess = 0; + printf("$side folder %-35s", "[$folder]"); + unless($imap->exists($folder)) { + print("does not exist yet\n"); + next; + } + unless ($imap->examine($folder)) { + warn + "$side Folder $folder: Could not examine: ", + $imap->LastError, "\n"; + $nb_errors++; + next; + } + + my $hash_ref = {}; + my @msgs = select_msgs($imap); + $smess = scalar(@msgs); + @$hash_ref{@msgs} = (undef); + unless ($smess == 0) { + $imap->fetch_hash_2("RFC822.SIZE",$hash_ref) or die_clean("$@"); + #print map {$hash_ref->{$_}->{"RFC822.SIZE"}, " "} keys %$hash_ref; + map {$stot += $hash_ref->{$_}->{"RFC822.SIZE"}} keys %$hash_ref; + } + + printf(" Size: %9s", $stot); + printf(" Messages: %5s\n", $smess); + $tot += $stot; + $tmess += $smess; + } + print "Total size: $tot\n"; + print "Total messages: $tmess\n"; + print "Time: ", timenext(), " s\n"; +} + +sub timenext { + my ($timenow, $timerel); + # $timebefore is global, beurk ! + $timenow = time; + $timerel = $timenow - $timebefore; + $timebefore = $timenow; + return($timerel); +} + + +sub tests_flags_regex { + + my $string; + ok('' eq flags_regex(''), "flags_regex, null string ''"); + ok('\Seen NonJunk $Spam' eq flags_regex('\Seen NonJunk $Spam'), 'flags_regex, nothing to do'); + ok('\Seen NonJunk $Spam' eq flags_regex('\Seen NonJunk $Spam'), 'flags_regex,'); + @regexflag = ('s/NonJunk//g'); + ok('\Seen $Spam' eq flags_regex('\Seen NonJunk $Spam'), "flags_regex, remove NonJunk: 's/NonJunk//g'"); + @regexflag = ('s/\$Spam//g'); + ok('\Seen NonJunk ' eq flags_regex('\Seen NonJunk $Spam'), 'flags_regex, remove $Spam: '."'s/\$Spam//g'"); + + @regexflag = ('s/\\\\Seen//g'); + + ok(' NonJunk $Spam' eq flags_regex('\Seen NonJunk $Spam'), 'flags_regex, remove \Seen: '. "'s/\\\\\\\\Seen//g'"); + + @regexflag = ('s/(\s|^)[^\\\\]\w+//g'); + ok('\Seen \Middle \End' eq flags_regex('\Seen NonJunk \Middle $Spam \End'), 'flags_regex, only \word [' . flags_regex('\Seen NonJunk \Middle $Spam \End'.']')); + ok(' \Seen \Middle \End1' eq flags_regex('Begin \Seen NonJunk \Middle $Spam \End1 End'), 'flags_regex, only \word [' . flags_regex('Begin \Seen NonJunk \Middle $Spam \End1 End'.']')); + + @regexflag = ('s/.*?(Keep1|Keep2|Keep3)/$1 /g'); + ok('Keep1 Keep2 ReB' eq flags_regex('ReA Keep1 REM Keep2 ReB'), "Keep only regex"); + #ok('Keep1 Keep2' eq flags_regex('Keep1 Keep2 Remove1'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('REM REM Keep1 Keep2'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('Keep1 REM REM Keep2'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 REM REM Keep2'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('Keep1 Keep2'), "Keep only regex"); + ok('Keep1 ' eq flags_regex('REM Keep1'), "Keep only regex"); + + @regexflag = ('s/(Keep1|Keep2|Keep3) (?!(Keep1|Keep2|Keep3)).*/$1 /g'); + ok('Keep1 Keep2 ' eq flags_regex('Keep1 Keep2 ReB'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('Keep1 Keep2 REM REM REM'), "Keep only regex"); + ok('Keep2 ' eq flags_regex('Keep2 REM REM REM'), "Keep only regex"); + #ok('' eq flags_regex('REM REM'), "Keep only regex"); + + @regexflag = ('s/.*?(Keep1|Keep2|Keep3)/$1 /g', + 's/(Keep1|Keep2|Keep3) (?!(Keep1|Keep2|Keep3)).*/$1 /g'); + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 REM Keep2 REM'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('Keep1 REM Keep2 REM'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 Keep2 REM'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 REM Keep2'), "Keep only regex"); + ok('Keep1 Keep2 Keep3 ' eq flags_regex('REM Keep1 REM Keep2 REM REM Keep3 REM'), "Keep only regex"); + ok('Keep1 ' eq flags_regex('REM REM Keep1 REM REM REM '), "Keep only regex"); + ok('Keep1 Keep3 ' eq flags_regex('RE1 Keep1 RE2 Keep3 RE3 RE4 RE5 '), "Keep only regex"); + + @regexflag = ('s/(.*)/$1 jrdH8u/'); + ok('REM REM REM REM REM jrdH8u' eq flags_regex('REM REM REM REM REM'), "Keep only regex 's/(.*)/\$1 jrdH8u/'"); + @regexflag = ('s/jrdH8u *//'); + ok('REM REM REM REM REM ' eq flags_regex('REM REM REM REM REM jrdH8u'), "Keep only regex s/jrdH8u *//"); + + @regexflag = ( + 's/(.*)/$1 jrdH8u/', + 's/.*?(Keep1|Keep2|Keep3|jrdH8u)/$1 /g', + 's/(Keep1|Keep2|Keep3|jrdH8u) (?!(Keep1|Keep2|Keep3|jrdH8u)).*/$1 /g', + 's/jrdH8u *//' + ); + + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 REM Keep2 REM'), "Keep only regex 'REM Keep1 REM Keep2 REM'"); + ok('Keep1 Keep2 ' eq flags_regex('Keep1 REM Keep2 REM'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 Keep2 REM'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 REM Keep2'), "Keep only regex"); + ok('Keep1 Keep2 Keep3 ' eq flags_regex('REM Keep1 REM Keep2 REM REM Keep3 REM'), "Keep only regex"); + ok('Keep1 ' eq flags_regex('REM REM Keep1 REM REM REM '), "Keep only regex"); + ok('Keep1 Keep3 ' eq flags_regex('RE1 Keep1 RE2 Keep3 RE3 RE4 RE5 '), "Keep only regex"); + ok('' eq flags_regex('REM REM REM REM REM'), "Keep only regex"); + + @regexflag = ( + 's/(.*)/$1 jrdH8u/', + 's/.*?(\\\\Seen|\\\\Answered|\\\\Flagged|\\\\Deleted|\\\\Draft|jrdH8u)/$1 /g', + 's/(\\\\Seen|\\\\Answered|\\\\Flagged|\\\\Deleted|\\\\Draft|jrdH8u) (?!(\\\\Seen|\\\\Answered|\\\\Flagged|\\\\Deleted|\\\\Draft|jrdH8u)).*/$1 /g', + 's/jrdH8u *//' + ); + + ok('\\Deleted \\Answered ' + eq flags_regex('Blabla $Junk \\Deleted machin \\Answered truc'), "Keep only regex: Exchange case"); + ok('' eq flags_regex(''), "Keep only regex: Exchange case, null string"); + ok('' + eq flags_regex('Blabla $Junk machin truc'), "Keep only regex: Exchange case, no accepted flags "); + ok('\\Deleted \\Answered \\Draft \\Flagged ' + eq flags_regex('\\Deleted \\Answered \\Draft \\Flagged '), "Keep only regex: Exchange case"); + + + @regexflag = ( + 's/.*?(?:(\\\\(?:Answered|Flagged|Deleted|Seen|Draft)\s?)|$)/defined($1)?$1:q()/eg' + ); + + ok('\\Deleted \\Answered ' + eq flags_regex('Blabla \$Junk \\Deleted machin \\Answered truc'), + "Keep only regex: Exchange case (Phil)"); + + ok('' eq flags_regex(''), "Keep only regex: Exchange case, null string (Phil)"); + + ok('' + eq flags_regex('Blabla $Junk machin truc'), + "Keep only regex: Exchange case, no accepted flags (Phil)"); + + ok('\\Deleted \\Answered \\Draft \\Flagged ' + eq flags_regex('\\Deleted \\Answered \\Draft \\Flagged '), + "Keep only regex: Exchange case (Phil)"); + + +} + +sub flags_regex { + my ($h1_flags) = @_; + foreach my $regexflag (@regexflag) { + my $h1_flags_orig = $h1_flags; + $debug and print "eval \$h1_flags =~ $regexflag\n"; + eval("\$h1_flags =~ $regexflag"); + die_clean("error: eval regexflag '$regexflag': $@\n") if $@; + $debug and print "regexflag $regexflag [$h1_flags_orig] -> [$h1_flags]\n"; + } + return($h1_flags); +} + +sub acls_sync { + my($h1_fold, $h2_fold) = @_; + if ($syncacls) { + my $h1_hash = $imap1->getacl($h1_fold) + or warn "Could not getacl for $h1_fold: $@\n"; + my $h2_hash = $imap2->getacl($h2_fold) + or warn "Could not getacl for $h2_fold: $@\n"; + my %users = map({ ($_, 1) } (keys(%$h1_hash), keys(%$h2_hash))); + foreach my $user (sort(keys(%users))) { + my $acl = $h1_hash->{$user} || "none"; + print "acl $user: [$acl]\n"; + next if ($h1_hash->{$user} && $h2_hash->{$user} && + $h1_hash->{$user} eq $h2_hash->{$user}); + unless ($dry) { + print "setting acl $h2_fold $user $acl\n"; + $imap2->setacl($h2_fold, $user, $acl) + or warn "Could not set acl: $@\n"; + } + } + } +} + + +sub tests_permanentflags { + + my $string; + ok('' eq permanentflags(' * OK [PERMANENTFLAGS (\* \Draft \Answered)] Limited'), + 'permanentflags \*'); + ok('\Draft \Answered' eq permanentflags(' * OK [PERMANENTFLAGS (\Draft \Answered)] Limited'), + 'permanentflags \Draft \Answered'); + ok('\Draft \Answered' + eq permanentflags('Blabla', + ' * OK [PERMANENTFLAGS (\Draft \Answered)] Limited', + 'Blabla'), + 'permanentflags \Draft \Answered' + ); + ok('' eq permanentflags('Blabla'), 'permanentflags nothing'); +} + +sub permanentflags { + my @lines = @_; + + foreach my $line (@lines) { + if ($line =~ m{\[PERMANENTFLAGS \(([^)]+?)\)\]}) { + #print "%%%$1%%%\n"; + my $permanentflags = $1; + if ($permanentflags =~ m{\\\*}) { + $permanentflags = ''; + } + return($permanentflags); + }; + } +} + +sub tests_flags_filter { + + ok( '\Seen' eq flags_filter('\Seen', '\Draft \Seen \Answered'), 'flags_filter ' ); + ok( '' eq flags_filter('\Seen', '\Draft \Answered'), 'flags_filter ' ); + ok( '\Seen' eq flags_filter('\Seen', '\Seen'), 'flags_filter ' ); + ok( '\Seen' eq flags_filter('\Seen', ' \Seen '), 'flags_filter ' ); + ok( '\Seen \Draft' + eq flags_filter('\Seen \Draft', '\Draft \Seen \Answered'), 'flags_filter ' ); + ok( '\Seen \Draft' + eq flags_filter('\Seen \Draft', ' \Draft \Seen \Answered '), 'flags_filter ' ); + +} + +sub flags_filter { + my($flags, $allowed_flags) = @_; + + my @flags = split(/\s+/, $flags); + my %allowed_flags = map { $_ => 1 } split(' ', $allowed_flags ); + my @flags_out = map { exists $allowed_flags{$_} ? $_ : () } @flags; + + my $flags_out = join(' ', @flags_out); + #print "%%%$flags_out%%%\n"; + return($flags_out); +} + + + +sub select_msgs { + my ($imap) = @_; + my (@msgs,@max,@min,@union,@inter); + + unless (defined($maxage) or defined($minage)) { + @msgs = $imap->search("ALL"); + return(@msgs); + } + if (defined($maxage)) { + @max = $imap->sentsince(time - 86400 * $maxage); + } + if (defined($minage)) { + @min = $imap->sentbefore(time - 86400 * $minage); + } + SWITCH: { + unless(defined($minage)) {@msgs = @max; last SWITCH}; + unless(defined($maxage)) {@msgs = @min; last SWITCH}; + my (%union, %inter); + foreach my $m (@min, @max) {$union{$m}++ && $inter{$m}++} + @inter = keys(%inter); + @union = keys(%union); + # normal case + if ($minage <= $maxage) {@msgs = @inter; last SWITCH}; + # just exclude messages between + if ($minage > $maxage) {@msgs = @union; last SWITCH}; + + } + return(@msgs); +} + + + + +sub tests_regexmess { + + ok("blabla" eq regexmess("blabla"), "regexmess, no regexmess, nothing to do"); + + @regexmess = ('s/p/Z/g'); + ok("ZoZoZo" eq regexmess("popopo"), "regexmess, s/p/Z/g"); + + @regexmess = 's{c}{C}gxms'; + ok("H1: abC\nH2: Cde\n\nBody abC" + eq regexmess("H1: abc\nH2: cde\n\nBody abc"), + "regexmess, c->C"); + + @regexmess = 's{\AFrom\ }{From:}gxms'; + ok( '' + eq regexmess(''), + 'From mbox 1 add colon blank'); + + ok( 'From:' + eq regexmess('From '), + 'From mbox 2 add colo'); + + ok( "\n" . 'From ' + eq regexmess("\n" . 'From '), + 'From mbox 3 add colo'); + + ok( "From: zzz\n" . 'From ' + eq regexmess("From zzz\n" . 'From '), + 'From mbox 4 add colo'); + + @regexmess = 's{\AFrom\ [^\n]*(\n)?}{}gxms'; + ok( '' + eq regexmess(''), + 'From mbox 1 remove, blank'); + + ok( '' + eq regexmess('From '), + 'From mbox 2 remove'); + + ok( "\n" . 'From ' + eq regexmess("\n" . 'From '), + 'From mbox 3 remove'); + + #print "[", regexmess("From zzz\n" . 'From '), "]"; + ok( "" . 'From ' + eq regexmess("From zzz\n" . 'From '), + 'From mbox 4 remove'); + + + ok( +'Date: Sat, 10 Jul 2010 05:34:45 -0700 +From: + +Hello, +Bye.' + eq regexmess( +'From zzz +Date: Sat, 10 Jul 2010 05:34:45 -0700 +From: + +Hello, +Bye.' + ), + 'From mbox 5 remove'); +} + +sub regexmess { + my ($string) = @_; + foreach my $regexmess (@regexmess) { + $debug and print "eval \$string =~ $regexmess\n"; + eval("\$string =~ $regexmess"); + die_clean("error: eval regexmess '$regexmess': $@\n") if $@; + } + return($string); +} + + +sub stats { + print "++++ Statistics\n"; + print "Transfer time : $timediff sec\n"; + print "Messages transferred : $nb_msg_transferred "; + print "(could be $nb_msg_skipped_dry_mode without dry mode)" if ($dry); + print "\n"; + print "Messages skipped : $nb_msg_skipped\n"; + print "Messages found duplicate on host1 : $h1_nb_msg_duplicate\n"; + print "Messages found duplicate on host2 : $h2_nb_msg_duplicate\n"; + print "Messages void (noheader) on host1 : $h1_nb_msg_noheader\n"; + print "Messages void (noheader) on host2 : $h2_nb_msg_noheader\n"; + print "Messages deleted on host1 : $h1_nb_msg_deleted\n"; + print "Messages deleted on host2 : $h2_nb_msg_deleted\n"; + print "Total bytes transferred : $total_bytes_transferred\n"; + print "Total bytes duplicate host1 : $h1_total_bytes_duplicate\n"; + print "Total bytes duplicate host2 : $h2_total_bytes_duplicate\n"; + print "Total bytes skipped : $total_bytes_skipped\n"; + print "Total bytes error : $total_bytes_error\n"; + $timediff ||= 1; # No division per 0 + printf ("Message rate : %.1f messages/s\n", $nb_msg_transferred / $timediff); + printf ("Average bandwidth rate : %.1f KiB/s\n", $total_bytes_transferred / 1024 / $timediff); + print "Reconnections to host1 : $host1_reconnect_count\n"; + print "Reconnections to host2 : $host2_reconnect_count\n"; + printf ("Memory consumption : %.1f MB\n", $memory_consumption / 1024 / 1024); + print "Memory/biggest message ratio : $memory_ratio\n"; + print "Detected $nb_errors errors\n\n"; + + print $warn_release, "\n"; + print thank_author(); +} + +sub thank_author { + + return(join("", "Happy with this free, open and gratis DWTFPL software?\n", + "Encourage the author (Gilles LAMIRAL) by giving him a book\n", + "or just money via paypal:\n", + "http://www.linux-france.org/prj/imapsync/\n")); +} + +sub get_options { + my $numopt = scalar(@ARGV); + my $argv = join("¤", @ARGV); + + $test_builder = Test::More->builder; + $test_builder->no_ending(1); + + if($argv =~ m/-delete¤2/) { + print "May be you mean --delete2 instead of --delete 2\n"; + exit 1; + } + my $opt_ret = GetOptions( + "debug!" => \$debug, + "debugimap!" => \$debugimap, + "debugimap1!" => \$debugimap1, + "debugimap2!" => \$debugimap2, + "host1=s" => \$host1, + "host2=s" => \$host2, + "port1=i" => \$port1, + "port2=i" => \$port2, + "user1=s" => \$user1, + "user2=s" => \$user2, + "password1=s" => \$password1, + "password2=s" => \$password2, + "passfile1=s" => \$passfile1, + "passfile2=s" => \$passfile2, + "authmd5!" => \$authmd5, + "sep1=s" => \$sep1, + "sep2=s" => \$sep2, + "folder=s" => \@folder, + "folderrec=s" => \@folderrec, + "include=s" => \@include, + "exclude=s" => \@exclude, + "prefix1=s" => \$prefix1, + "prefix2=s" => \$prefix2, + "regextrans2=s" => \@regextrans2, + "regexmess=s" => \@regexmess, + "regexflag=s" => \@regexflag, + "delete!" => \$delete, + "delete2!" => \$delete2, + "delete2folders!" => \$delete2folders, + "syncinternaldates!" => \$syncinternaldates, + "idatefromheader!" => \$idatefromheader, + "syncacls!" => \$syncacls, + "maxsize=i" => \$maxsize, + "minsize=i" => \$minsize, + "maxage=i" => \$maxage, + "minage=i" => \$minage, + "buffersize=i" => \$buffersize, + "foldersizes!" => \$foldersizes, + "dry!" => \$dry, + "expunge!" => \$expunge, + "expunge1!" => \$expunge1, + "expunge2!" => \$expunge2, + "uidexpunge2!" => \$uidexpunge2, + "subscribed!" => \$subscribed, + "subscribe!" => \$subscribe, + "subscribe_all!" => \$subscribe_all, + "justbanner!" => \$justbanner, + "justconnect!"=> \$justconnect, + "justfolders!"=> \$justfolders, + "justfoldersizes!" => \$justfoldersizes, + "fast!" => \$fast, + "version" => \$version, + "help" => \$help, + "timeout=i" => \$timeout, + "skipheader=s" => \$skipheader, + "useheader=s" => \@useheader, + "skipsize!" => \$skipsize, + "allowsizemismatch!" => \$allowsizemismatch, + "fastio1!" => \$fastio1, + "fastio2!" => \$fastio2, + "ssl1!" => \$ssl1, + "ssl2!" => \$ssl2, + "tls1!" => \$tls1, + "tls2!" => \$tls2, + "authmech1=s" => \$authmech1, + "authmech2=s" => \$authmech2, + "authuser1=s" => \$authuser1, + "authuser2=s" => \$authuser2, + "split1=i" => \$split1, + "split2=i" => \$split2, + "reconnectretry1=i" => \$reconnectretry1, + "reconnectretry2=i" => \$reconnectretry2, + "tests" => \$tests, + "tests_debug" => \$tests_debug, + "allow3xx!" => \$allow3xx, + "justlogin!" => \$justlogin, + "tmpdir=s" => \$tmpdir, + "pidfile=s" => \$pidfile, + "releasecheck!" => \$releasecheck, + "modules_version!" => \$modules_version, + ); + + $debug and print "get options: [$opt_ret]\n"; + + # just the version + print imapsync_version(), "\n" and exit if ($version) ; + + if ($tests) { + $test_builder->no_ending(0); + tests(); + exit; + } + if ($tests_debug) { + $test_builder->no_ending(0); + tests_debug(); + exit; + } + + $help = 1 if ! $numopt; + load_modules(); + + # exit with --help option or no option at all + usage() and exit if ($help or ! $numopt) ; + + # don't go on if options are not all known. + exit(EX_USAGE()) unless ($opt_ret) ; + +} + + +sub load_modules { + + require IO::Socket::SSL if ($ssl1 or $ssl2 or $tls1 or $tls2); + + require Term::ReadKey if ( + ((not($password1 or $passfile1)) + or (not($password2 or $passfile2))) + and (not $help)); + + #require Data::Dumper if ($debug); +} + + + +sub parse_header_msg { + my ($imap, $m_uid, $s_heads, $s_fir, $s, $s_hash) = @_; + + my $head = $s_heads->{$m_uid}; + my $headnum = scalar(keys(%$head)); + $debug and print "Head NUM:", $headnum, "\n"; + unless($headnum) { print "Warning: no header used or found for message $m_uid\n"; } + my $headstr; + + foreach my $h (sort keys(%$head)){ + foreach my $val (sort @{$head->{$h}}) { + # no 8-bit data in headers ! + $val =~ s/[\x80-\xff]/X/g; + + # remove the first blanks (dbmail bug ?) + $val =~ s/^\s*(.+)$/$1/; + + # and uppercase header line + # (dbmail and dovecot) + + my $H = uc("$h: $val"); + # show stuff in debug mode + $debug and print "${s}H $H", "\n"; + + if ($skipheader and $H =~ m/$skipheader/i) { + $debug and print "Skipping header $H\n"; + next; + } + $headstr .= "$H"; + } + } + #return unless ($headstr); + unless ($headstr){ + # taking everything is too heavy, + # should take only 1 Ko + #print "no header so taking everything\n"; + #$headstr = $imap->message_string($m_uid); + + print "no header so we ignore this message\n"; + return undef; + } + my $size = $s_fir->{$m_uid}->{"RFC822.SIZE"}; + my $flags = $s_fir->{$m_uid}->{"FLAGS"}; + my $idate = $s_fir->{$m_uid}->{"INTERNALDATE"}; + $size = length($headstr) unless ($size); + my $m_md5 = md5_base64($headstr); + $debug and print "$s msg $m_uid:$m_md5:$size\n"; + my $key; + if ($skipsize) { + $key = "$m_md5"; + } + else { + $key = "$m_md5:$size"; + } + # 0 return code is used to identify duplicate message hash + return 0 if exists $s_hash->{"$key"}; + $s_hash->{"$key"}{'5'} = $m_md5; + $s_hash->{"$key"}{'s'} = $size; + $s_hash->{"$key"}{'D'} = $idate; + $s_hash->{"$key"}{'F'} = $flags; + $s_hash->{"$key"}{'m'} = $m_uid; +} + + +sub firstline { + # extract the first line of a file (without \n) + + my($file) = @_; + my $line = ""; + + open FILE, $file or die_clean("error [$file]: $! "); + chomp($line = ); + close FILE; + $line = ($line) ? $line: "error !EMPTY! [$file]"; + return $line; +} + + +sub file_to_string { + my($file) = @_; + my @string; + open FILE, $file or die_clean("error [$file]: $! "); + @string = ; + close FILE; + return join("", @string); +} + + +sub string_to_file { + my($string, $file) = @_; + sysopen(FILE, $file,O_WRONLY|O_TRUNC|O_CREAT, 0600) or die_clean("$! $file"); + print FILE $string; + close FILE; +} + +sub tests_is_a_release_number { + ok(is_a_release_number(1.351), 'is_a_release_number 1.351'); + ok(is_a_release_number(42.4242), 'is_a_release_number 42.4242'); + ok(is_a_release_number(imapsync_version()), 'is_a_release_number imapsync_version()'); + ok(! is_a_release_number('blabla' ), '! is_a_release_number blabla'); + +} + +sub is_a_release_number { + my $number = shift; + + $number =~ m{\d\.\d+}; +} + +sub check_last_release { + + my $public_release = not_long('imapsync_version_lfo'); + return('unknown') if ($public_release eq 'unknown'); + return('unknown') if (! is_a_release_number($public_release)); + return('timeout') if ($public_release eq 'timeout'); + + my $imapsync_here = imapsync_version(); + + if ($public_release > $imapsync_here) { + return("New imapsync release $public_release available"); + }else{ + return("This current imapsync is up to date"); + } +} + +sub imapsync_version { + my $rcs = '$Id: imapsync,v 1.366 2010/10/25 17:15:52 gilles Exp $ '; + $rcs =~ m/,v (\d+\.\d+)/; + my $VERSION = ($1) ? $1: "UNKNOWN"; + return($VERSION); +} + +sub tests_imapsync_basename { + + ok('imapsync' eq imapsync_basename(), 'imapsync_basename: imapsync'); + ok('blabla' ne imapsync_basename(), '! imapsync_basename: blabla'); +} + +sub imapsync_basename { + + return basename($0); + +} + +sub imapsync_version_lfo { + + my $local_version = imapsync_version(); + my $imapsync_basename = imapsync_basename(); + my $agent_info = "$OSNAME system, perl " + . sprintf("%vd", $PERL_VERSION) + . ", Mail::IMAPClient $Mail::IMAPClient::VERSION" + . " $imapsync_basename"; + my $sock = new IO::Socket::INET ( + PeerAddr => 'linux-france.org', + PeerPort => '80', + Proto => 'tcp'); + return('unknown') if not $sock; + print $sock + "GET /prj/imapsync/VERSION HTTP/1.0\n", + "User-Agent: imapsync/$local_version ($agent_info)\n", + "Host: www.linux-france.org\n\n"; + my @line = <$sock>; + close($sock); + my $last_release = $line[-1]; + chomp($last_release); + return($last_release); +} + +sub not_long { + #print "Entering not_long\n"; + my ($func) = @_; + my $val; + + # Doesn't work with gethostbyname (see perlipc) + #local $SIG{ALRM} = sub { die "alarm\n" }; + + if ('MSWin32' eq $OSNAME) { + local $SIG{ALRM} = sub { die "alarm\n" }; + }else{ + + POSIX::sigaction(SIGALRM, + POSIX::SigAction->new(sub { die "alarm" })) + or warn "Error setting SIGALRM handler: $!\n"; + } + + eval { + + alarm(3); + #print $func, "\n"; + { + no strict "refs"; + #print "Calling $func\n"; + $val = &$func(); + #print "End of $func\n"; + } + alarm(0); + }; + if ($@) { + if ($@ =~ /alarm/) { + # timed out + return('timeout'); + }else{ + alarm(0); + return('unknown'); # propagate unexpected errors + } + }else { + # didn't + return($val); + } +} + +sub localhost_info { + + my($infos) = join("", + "Here is a [$OSNAME] system (", + join(" ", + uname(), + ), + ")\n", + "With perl ", + sprintf("%vd", $PERL_VERSION), + " Mail::IMAPClient $Mail::IMAPClient::VERSION", + ); + return($infos); + +} + +sub usage { + my $localhost_info = localhost_info(); + my $thank = thank_author(); + my $warn_release =''; + $warn_release = check_last_release() if (not defined($releasecheck)); + print < : "from" imap server. Mandatory. +--port1 : port to connect on host1. Default is 143. +--user1 : user to login on host1. Mandatory. +--authuser1 : user to auth with on host1 (admin user). + Avoid using --authmech1 SOMETHING with --authuser1. +--password1 : password for the user1. Dangerous, use --passfile1 +--passfile1 : password file for the user1. Contains the password. +--host2 : "destination" imap server. Mandatory. +--port2 : port to connect on host2. Default is 143. +--user2 : user to login on host2. Mandatory. +--authuser2 : user to auth with on host2 (admin user). +--password2 : password for the user2. Dangerous, use --passfile2 +--passfile2 : password file for the user2. Contains the password. +--noauthmd5 : don't use MD5 authentification. +--authmech1 : auth mechanism to use with host1: + PLAIN, LOGIN, CRAM-MD5 etc. Use UPPERCASE. +--authmech2 : auth mechanism to use with host2. See --authmech1 +--ssl1 : use an SSL connection on host1. +--ssl2 : use an SSL connection on host2. +--tls1 : use an TLS connection on host1. +--tls2 : use an TLS connection on host2. +--folder : sync this folder. +--folder : and this one, etc. +--folderrec : sync this folder recursively. +--folderrec : and this one, etc. +--include : sync folders matching this regular expression +--include : or this one, etc. + in case both --include --exclude options are + use, include is done before. +--exclude : skips folders matching this regular expression + Several folders to avoid: + --exclude 'fold1|fold2|f3' skips fold1, fold2 and f3. +--exclude : or this one, etc. +--tmpdir : where to store temporary files and subdirectories. + Will be created if it doesn't exist. + Default is system specific and should be ok. +--pidfile : the file where imapsync pid is written. +--prefix1 : remove prefix to all destination folders + (usually INBOX. for cyrus imap servers) + you can use --prefix1 if your source imap server + does not have NAMESPACE capability. +--prefix2 : add prefix to all destination folders + (usually INBOX. for cyrus imap servers) + use --prefix2 if your target imap server does not + have NAMESPACE capability. +--regextrans2 : Apply the whole regex to each destination folders. +--regextrans2 : and this one. etc. + When you play with the --regextrans2 option, first + add also the safe options --dry --justfolders + Then, when happy, remove --dry, remove --justfolders +--regexmess : Apply the whole regex to each message before transfer. + Example: 's/\\000/ /g' # to replace null by space. +--regexmess : and this one. +--regexmess : and this one, etc. +--regexflag : Apply the whole regex to each flags list. + Example: 's/\"Junk"//g' # to remove "Junk" flag. +--regexflag : and this one, etc. +--sep1 : separator in case namespace is not supported. +--sep2 : idem. +--delete : delete messages on host1 server after + a successful transfer. Useful in case you + want to migrate from one server to another one. + With imap, "delete" tags messages as deleted, they + are not really deleted. See expunge. +--delete2 : delete messages in host2 that are not in + host1 server. +--delete2folders : delete folders in host2 that are not in + host1 server. For safety try it like this: + --delete2folders --dry --justfolders --nofoldersizes +--expunge : expunge messages on host1. + expunge really deletes messages marked deleted. + expunge is made at the beginning, on host1 only. + Newly transferred messages are expunged if + option --expunge is given. + No expunge is done on destination account + (see --expunge2) but it may change in future releases. +--expunge1 : expunge messages on host1. +--expunge2 : expunge messages on host2. +--uidexpunge2 : uidexpunge messages on the destination imap server + that are not on the source server, requires --delete2 +--syncinternaldates : sets the internal dates on host2 same as host1. + Turned on by default. Internal date is the date + a message arrived on a host (mtime). +--idatefromheader : sets the internal dates on host2 same as the + "Date:" headers. +--buffersize : sets the size of a block of I/O. +--maxsize : skip messages larger (or equal) than bytes +--minsize : skip messages smaller (or equal) than bytes +--maxage : skip messages older than days. + final stats (skipped) don't count older messages + see also --minage +--minage : skip messages newer than days. + final stats (skipped) don't count newer messages + You can do (+ are the messages selected): + past|----maxage+++++++++++++++>now + past|+++++++++++++++minage---->now + past|----maxage+++++minage---->now (intersection) + past|++++minage-----maxage++++>now (union) +--skipheader : Don't take into account header keyword + matching ex: --skipheader 'X.*' +--useheader : Use this header to compare messages on both sides. + Ex: Message-ID or Subject or Date. +--useheader and this one, etc. +--skipsize : Don't take message size into account to compare + messages on both sides. On by default. + Use --no-skipsize for using size comparaison. +--allowsizemismatch : allow RFC822.SIZE != fetched msg size + consider also --skipsize to avoid duplicate messages + when running syncs more than one time per mailbox +--dry : do nothing, just print what would be done. +--subscribed : transfers subscribed folders. +--subscribe : subscribe to the folders transferred on the + host2 that are subscribed on host1. +--subscribe_all : subscribe to the folders transferred on the + host2 even if they are not subscribed on host1. +--nofoldersizes : Do not calculate the size of each folder in bytes + and message counts. Default is to calculate them. +--justfoldersizes : exit after printed the folder sizes. +--syncacls : Synchronises acls (Access Control Lists). +--nosyncacls : Does not synchronise acls. This is the default. +--debug : debug mode. +--debugimap1 : imap debug mode for host1. imap debug is very verbose. +--debugimap2 : imap debug mode for host2. +--debugimap : imap debug mode for host1 and host2. +--version : print software version. +--noreleasecheck : do not check for new imapsync release (a http request). +--justconnect : just connect to both servers and print useful + information. Need only --host1 and --host2 options. +--justlogin : just login to both host1 and host2 with users + credentials, then exit. +--justfolders : just do things about folders (ignore messages). +--fast : be faster (just does not sync flags of messages + already transfered). +--reconnectretry1 : reconnect to host1 if connection is lost up to + times per imap command (default is 3) +--reconnectretry2 : same as --reconnectretry1 but for host2 +--split1 : split the requests in several parts on host1. + is the number of messages handled per request. + default is like --split1 1000. +--split2 : same thing on host2. +--fastio1 : use fastio with host1. +--fastio2 : use fastio with host2. +--timeout : imap connect timeout. +--help : print this help. + +Example: to synchronise imap account "foo" on "imap.truc.org" + to imap account "bar" on "imap.trac.org" + with foo password "secret1" + and bar password "secret2" + +$0 \\ + --host1 imap.truc.org --user1 foo --password1 secret1 \\ + --host2 imap.trac.org --user2 bar --password2 secret2 + +$localhost_info +$rcs +$warn_release + +$thank +EOF +} + + +sub good_date { + # two incoming formats: + # header Tue, 24 Aug 2010 16:00:00 +0200 + # internal 24-Aug-2010 16:00:00 +0200 + + # outgoing format: internal date format + # 24-Aug-2010 16:00:00 +0200 + + my ($d) = @_; + return ('') if not defined($d); + + if ( $d =~ m{(\d?)(\d-...-\d{4})( \d{2}:\d{2}:\d{2})( (?:\+|-)\d{4})?}o ) { + #print "internal: [$1][$2][$3][$4]\n"; + my ($day_1, $date_rest, $hour, $zone) = ($1,$2,$3,$4); + $day_1 = '0' if ($day_1 eq ''); + $zone = '' if not defined($zone); + $d = $day_1 . $date_rest . $hour . $zone; + + + }elsif ($d =~ m{(?:.{3}, )(\d?)(\d) (...) (\d{4})( \d{2}:\d{2}:\d{2})( (?:\+|-)\d{4})?}o ) { + #print "header: [$1][$2][$3][$4][$5][$6]\n"; + my ($day_1, $day_rest, $month, $year, $hour, $zone) = ($1,$2,$3,$4,$5,$6); + $day_1 = '0' if ($day_1 eq ''); + $zone = '' if not defined($zone); + $d = $day_1 . "$day_rest-$month-$year" . $hour . $zone; + + }else{ + # unknown/unmatch => return same string + return($d); + } + + $d = qq("$d"); + return($d); +} + +sub memory_consumption { + # memory consumed by imapsync until now in bytes + return((memory_consumption_of_pids())[0]); +} + +sub memory_consumption_of_pids { + + my @PID = (@_) ? @_ : ($PROCESS_ID); + + #print "PIDs: @PID\n"; + my @val; + if ('MSWin32' eq $OSNAME) { + @val = memory_consumption_of_pids_win32(@PID); + }else{ + # Unix + my @ps = qx{ ps o vsz @PID }; + shift @ps; # First line is column name "VSZ" + chomp @ps; + # convert to + @val = map { $_ * 1024 } @ps; + return(@val); + } +} + +sub memory_consumption_of_pids_win32 { + # Windows + my @PID = @_; + my %PID; + # hash of pids as key values + map { $PID{$_}++ } @PID; + + # Does not work but should reading the tasklist documentation + #@ps = qx{ tasklist /FI "PID eq @PID" }; + + my @ps = qx{ tasklist /NH /FO CSV }; + #print "-" x 80, "\n", @ps, "-" x 80, "\n"; + my @val; + foreach my $line (@ps) { + my($name, $pid, $mem) = (split(',', $line))[0,1,4]; + next if (! $pid); + #print "[$name][$pid][$mem]"; + if ($PID{remove_qq($pid)}) { + #print "MATCH !\n"; + chomp($mem); + $mem = remove_qq($mem); + $mem = remove_Ko($mem); + $mem = remove_not_num($mem); + #print "[$mem]\n"; + push(@val, $mem * 1024); + } + } + return(@val); +} + +sub remove_not_num { + + my $string = shift; + $string =~ tr/0-9//cd; + #print "tr [$string]\n"; + return($string); +} + +sub tests_remove_not_num { + + ok('123' eq remove_not_num(123), 'remove_not_num( 123 )'); + ok('123' eq remove_not_num('123'), "remove_not_num( '123' )"); + ok('123' eq remove_not_num('12 3'), "remove_not_num( '12 3' )"); + ok('123' eq remove_not_num('a 12 3 Ko'), "remove_not_num( 'a 12 3 Ko' )"); +} + +sub remove_Ko { + my $string = shift; + if ($string =~ /^(.*) Ko$/) { + return($1); + }else{ + return($string); + } +} + +sub remove_qq { + my $string = shift; + if ($string =~ /^"(.*)"$/) { + return($1); + }else{ + return($string); + } +} + +sub memory_consumption_ratio { + + my ($base) = @_; + $base ||= 1; + my $consu = memory_consumption(); + return($consu / $base); +} + +sub tests_memory_consumption { + + ok(print join("\n", memory_consumption_of_pids()), "\n"); + ok(print join("\n", memory_consumption_of_pids('1')), "\n"); + ok(print join("\n", memory_consumption_of_pids('1', $$)), "\n"); + + ok(print memory_consumption_ratio(), "\n"); + ok(print memory_consumption_ratio(1), "\n"); + ok(print memory_consumption_ratio(10), "\n"); + + ok(print memory_consumption(), "\n"); +} + +sub tests_good_date { + + ok('' eq good_date(), 'good_date no arg'); + ok('"24-Aug-2010 16:00:00 +0200"' eq good_date('24-Aug-2010 16:00:00 +0200'), 'good_date internal 2digit zone'); + ok('"24-Aug-2010 16:00:00"' eq good_date('24-Aug-2010 16:00:00'), 'good_date internal 2digit no zone'); + ok('"01-Sep-2010 16:00:00 +0200"' eq good_date( '1-Sep-2010 16:00:00 +0200'), 'good_date internal SP 1digit'); + ok('"24-Aug-2010 16:00:00 +0200"' eq good_date('Tue, 24 Aug 2010 16:00:00 +0200'), 'good_date header 2digit zone'); + ok('"01-Sep-2010 16:00:00"' eq good_date('Wed, 1 Sep 2010 16:00:00'), 'good_date header SP 1digit zone'); + ok('"01-Sep-2010 16:00:00 +0200"' eq good_date('Wed, 1 Sep 2010 16:00:00 +0200'), 'good_date header SP 1digit zone'); + ok('"01-Sep-2010 16:00:00 +0200"' eq good_date('Wed, 1 Sep 2010 16:00:00 +0200 (CEST)'), 'good_date header SP 1digit zone'); + +} + + +sub tests_list_keys_in_2_not_in_1 { + + my @list; + ok( ! list_keys_in_2_not_in_1( {}, {}), 'list_keys_in_2_not_in_1: {} {}'); + ok( 0 == compare_lists( [], [ list_keys_in_2_not_in_1( {}, {} ) ] ), 'list_keys_in_2_not_in_1: {} {}'); + ok( 0 == compare_lists( ['a','b'], [ list_keys_in_2_not_in_1( {}, {'a' => 1, 'b' => 1}) ]), 'list_keys_in_2_not_in_1: {} {a, b}'); + ok( 0 == compare_lists( ['b'], [ list_keys_in_2_not_in_1( {'a' => 1}, {'a' => 1, 'b' => 1}) ]), 'list_keys_in_2_not_in_1: {a} {a, b}'); + ok( 0 == compare_lists( [], [ list_keys_in_2_not_in_1( {'a' => 1, 'b' => 1}, {'a' => 1, 'b' => 1}) ]), 'list_keys_in_2_not_in_1: {a, b} {a, b}'); + ok( 0 == compare_lists( [], [ list_keys_in_2_not_in_1( {'a' => 1, 'b' => 1, 'c' => 1}, {'a' => 1, 'b' => 1}) ]), 'list_keys_in_2_not_in_1: {a, b, c} {a, b}'); + ok( 0 == compare_lists( ['b'], [ list_keys_in_2_not_in_1( {'a' => 1, 'c' => 1}, {'a' => 1, 'b' => 1}) ]), 'list_keys_in_2_not_in_1: {a, b, c} {a, b}'); + +} + +sub list_keys_in_2_not_in_1 { + + my $folders1_ref = shift; + my $folders2_ref = shift; + my @list; + + foreach my $folder ( sort keys %$folders2_ref ) { + next if exists($folders1_ref->{$folder}); + push(@list, $folder); + } + return(@list); +} + + +sub list_folders_in_2_not_in_1 { + + my (@h2_folders_not_in_1, %h2_folders_not_in_1); + @h2_folders_not_in_1 = list_keys_in_2_not_in_1( \%h1_folders_all, \%h2_folders_all); + map { $h2_folders_not_in_1{$_} = 1} @h2_folders_not_in_1; + @h2_folders_not_in_1 = list_keys_in_2_not_in_1( \%h2_folders_from_1, \%h2_folders_not_in_1); + + return( reverse @h2_folders_not_in_1 ); +} + +sub delete_folders_in_2_not_in_1 { + + my $dry_message = ''; + $dry_message = "\t(not really since --dry mode)" if $dry; + foreach my $folder (@h2_folders_not_in_1) { + + my $res = $dry; # always success in dry mode! + $res = $imap2->delete($folder) if ( ! $dry ) ; + if ($res) { + print "Delete $folder", "$dry_message", "\n"; + }else{ + print "Delete $folder failure", "\n"; + } + } +} + +sub tests_debug { + + SKIP: { + skip "No test in normal run" if (not $tests_debug); + tests_list_keys_in_2_not_in_1(); + } +} + +sub tests { + + SKIP: { + skip "No test in normal run" if (not $tests); + tests_folder_routines(); + tests_compare_lists(); + tests_regexmess(); + tests_flags_regex(); + tests_permanentflags(); + tests_flags_filter(); + tests_imap2_folder_name(); + tests_command_line_nopassword(); + tests_good_date(); + tests_max(); + tests_remove_not_num(); + tests_memory_consumption(); + tests_is_a_release_number(); + tests_imapsync_basename(); + tests_list_keys_in_2_not_in_1(); + } +} + +# IMAPClient 2.2.9 overrides + +sub override_imapclient { +no warnings 'redefine'; +no strict 'subs'; + +use constant Unconnected => 0; +use constant Connected => 1; # connected; not logged in +use constant Authenticated => 2; # logged in; no mailbox selected +use constant Selected => 3; # mailbox selected +use constant INDEX => 0; # Array index for output line number +use constant TYPE => 1; # Array index for line type + # (either OUTPUT, INPUT, or LITERAL) +use constant DATA => 2; # Array index for output line data +use constant NonFolderArg => 1; # Value to pass to Massage to + # indicate non-folder argument + + +*Mail::IMAPClient::append_file = sub { + + my $self = shift; + my $folder = $self->Massage(shift); + my $file = shift; + my $control = shift || undef; + my $count = $self->Count($self->Count+1); + my $flags = shift || undef; + my $date = shift || undef; + + if (defined($flags)) { + $flags =~ s/^\s+//g; + $flags =~ s/\s+$//g; + } + + if (defined($date)) { + $date =~ s/^\s+//g; + $date =~ s/\s+$//g; + } + + $flags = "($flags)" if $flags and $flags !~ /^\(.*\)$/ ; + $date = qq/"$date"/ if $date and $date !~ /^"/ ; + + + unless ( -f $file ) { + $self->LastError("File $file not found.\n"); + return undef; + } + + my $fh = IO::File->new($file) ; + + unless ($fh) { + $self->LastError("Unable to open $file: $!\n"); + $@ = "Unable to open $file: $!" ; + carp "unable to open $file: $!"; + return undef; + } + + my $bare_nl_count = scalar grep { /^\x0a$|[^\x0d]\x0a$/} <$fh>; + + seek($fh,0,0); + + my $clear = $self->Clear; + + $self->Clear($clear) + if $self->Count >= $clear and $clear > 0; + + my $length = ( -s $file ) + $bare_nl_count; + + my $string = "$count APPEND $folder " . + ( $flags ? "$flags " : "" ) . + ( $date ? "$date " : "" ) . + "{" . $length . "}\x0d\x0a" ; + + $self->_record($count,[ $self->_next_index($count), "INPUT", "$string" ] ); + + my $feedback = $self->_send_line("$string"); + + unless ($feedback) { + $self->LastError("Error sending '$string' to IMAP: $!\n"); + $fh->close; + return undef; + } + + my ($code, $output) = ("",""); + + until ( $code ) { + $output = $self->_read_line or $fh->close, return undef; + foreach my $o (@$output) { + $self->_record($count,$o); # $o is already an array ref + ($code) = $o->[DATA] =~ /(^\+|^\d+\sNO|^\d+\sBAD)/i; + if ($o->[DATA] =~ /^\*\s+BYE/) { + carp $o->[DATA]; + $self->State(Unconnected); + $fh->close; + return undef ; + } elsif ( $o->[DATA]=~ /^\d+\s+(NO|BAD)/i ) { + carp $o->[DATA]; + $fh->close; + return undef; + } + } + } + + { # Narrow scope + # Slurp up headers: later we'll make this more efficient I guess + local $/ = "\x0d\x0a\x0d\x0a"; + my $text = <$fh>; + $text =~ s/\x0d?\x0a/\x0d\x0a/g; + $self->_record($count,[ $self->_next_index($count), "INPUT", "{From file $file}" ] ) ; + $feedback = $self->_send_line($text); + + unless ($feedback) { + $self->LastError("Error sending append msg text to IMAP: $!\n"); + $fh->close; + return undef; + } + _debug($self, "control points to $$control\n") if ref($control) and $self->Debug; + $/ = ref($control) ? "\x0a" : $control ? $control : "\x0a"; + while (defined($text = <$fh>)) { + $text =~ s/\x0d?\x0a/\x0d\x0a/g; + $self->_record( $count, + [ $self->_next_index($count), "INPUT", "{from $file}\x0d\x0a" ] + ); + $feedback = $self->_send_line($text,1); + + unless ($feedback) { + $self->LastError("Error sending append msg text to IMAP: $!\n"); + $fh->close; + return undef; + } + } + $feedback = $self->_send_line("\x0d\x0a"); + + unless ($feedback) { + $self->LastError("Error sending append msg text to IMAP: $!\n"); + $fh->close; + return undef; + } + } + + # Now for the crucial test: Did the append work or not? + ($code, $output) = ("",""); + + my $uid = undef; + until ( $code ) { + $output = $self->_read_line or return undef; + foreach my $o (@$output) { + $self->_record($count,$o); # $o is already an array ref + $self->_debug("append_file: Deciding if " . $o->[DATA] . " has the code.\n") + if $self->Debug; + ($code) = $o->[DATA] =~ /^\d+\s(NO|BAD|OK)/i; + # try to grab new msg's uid from o/p + $o->[DATA] =~ m#UID\s+\d+\s+(\d+)\]# and $uid = $1; + if ($o->[DATA] =~ /^\*\s+BYE/) { + carp $o->[DATA]; + $self->State(Unconnected); + $fh->close; + return undef ; + } elsif ( $o->[DATA]=~ /^\d+\s+(NO|BAD)/i ) { + carp $o->[DATA]; + $fh->close; + return undef; + } + } + } + $fh->close; + + if ($code !~ /^OK/i) { + return undef; + } + + + return defined($uid) ? $uid : $self; +}; + + + + +*Mail::IMAPClient::fetch_hash = sub { + # taken from original lib, + # just added split code. + my $self = shift; + my $hash = ref($_[-1]) ? pop @_ : {}; + my @words = @_; + for (@words) { + s/([\( ])FAST([\) ])/${1}FLAGS INTERNALDATE RFC822\.SIZE$2/i ; + s/([\( ])FULL([\) ])/${1}FLAGS INTERNALDATE RFC822\.SIZE ENVELOPE BODY$2/i ; + } + my $msgs_ref_all = scalar($self->messages); + my $split = $self->Split() || scalar(@$msgs_ref_all); + while(my @msgs = splice(@$msgs_ref_all, 0, $split)) { + #print "SPLIT: @msgs\n"; + my $msgs_ref = \@msgs; + my $output = scalar($self->fetch($msgs_ref,"(" . join(" ",@_) . ")")) + ; # unless grep(/\b(?:FAST|FULL)\b/i,@words); + my $x; + for ($x = 0; $x <= $#$output ; $x++) { + my $entry = {}; + my $l = $output->[$x]; + if ($self->Uid) { + my($uid) = $l =~ /\((?:.* )?UID (\d+).*\)/i; + next unless $uid; + if ( exists $hash->{$uid} ) { + $entry = $hash->{$uid} ; + } + else { + $hash->{$uid} ||= $entry; + } + } + else { + my($mid) = $l =~ /^\* (\d+) FETCH/i; + next unless $mid; + if ( exists $hash->{$mid} ) { + $entry = $hash->{$mid} ; + } + else { + $hash->{$mid} ||= $entry; + } + } + + foreach my $w (@words) { + if ( $l =~ /\Q$w\E\s*$/i ) { + $entry->{$w} = $output->[$x+1]; + $entry->{$w} =~ s/(?:\x0a?\x0d)+$//g; + chomp $entry->{$w}; + } + else { + $l =~ /\( # open paren followed by ... + (?:.*\s)? # ...optional stuff and a space + \Q$w\E\s # escaped fetch field + (?:" # then: a dbl-quote + (\\.| # then bslashed anychar(s) or ... + [^"]+) # ... nonquote char(s) + "| # then closing quote; or ... + \( # ...an open paren + (\\.| # then bslashed anychar or ... + [^\)]*) # ... non-close-paren char + \)| # then closing paren; or ... + (\S+)) # unquoted string + (?:\s.*)? # possibly followed by space-stuff + \) # close paren + /xi; + $entry->{$w}=defined($1)?$1:defined($2)?$2:$3; + } + } + } +} + return wantarray ? %$hash : $hash; +}; + + + +*Mail::IMAPClient::login = sub { + my $self = shift; + return $self->authenticate($self->Authmechanism,$self->Authcallback) + if $self->{Authmechanism}; + + my $id = $self->User; + my $has_quotes = $id =~ /^".*"$/ ? 1 : 0; + my $string = "Login " . ( $has_quotes ? $id : qq("$id") ) . + " " . $self->Password . "\r\n"; + $self->_imap_command($string) + and $self->State(Authenticated); + # $self->folders and $self->separator unless $self->NoAutoList; + unless ( $self->IsAuthenticated) { + my($carp) = $self->LastError; + $carp =~ s/^[\S]+ ([^\x0d\x0a]*)\x0d?\x0a/$1/; + carp $carp unless defined wantarray; + return undef; + }; + return $self; +}; + + +*Mail::IMAPClient::get_header = sub { + my($self , $msg, $header ) = @_; + my $val; + + #eval { $val = $self->parse_headers([$msg],$header)->{$header}[0] }; + my $h = $self->parse_headers([$msg],$header); + #require Data::Dumper; + #print Data::Dumper->Dump([$h]); + #$val = $self->parse_headers([$msg],$header)->{$header}[0]; + + $val = $h->{$msg}{$header}[0]; + return defined($val)? $val : undef; +}; + + +*Mail::IMAPClient::parse_headers = sub { + my($self,$msgspec_all,@fields) = @_; + my(%fieldmap) = map { ( lc($_),$_ ) } @fields; + my $msg; my $string; my $field; + #print ref($msgspec_all), "\n"; + #if(ref($msgspec_all) eq 'HASH') { + # print ref($msgspec_all), "\n"; + #$msgspec_all = [$msgspec_all]; + #} + + unless(ref($msgspec_all) eq 'ARRAY') { + print "parse_headers want an ARRAY ref\n"; + #exit 1; + return undef; + } + + my $headers = {}; # hash from message ids to header hash + my $split = $self->Split() || scalar(@$msgspec_all); + while(my @msgs = splice(@$msgspec_all, 0, $split)) { + $debug and print "SPLIT: @msgs\n"; + my $msgspec = \@msgs; + + # Make $msg a comma separated list, of messages we want + $msg = $self->Range($msgspec); + + if ($fields[0] =~ /^[Aa][Ll]{2}$/ ) { + + $string = "$msg body" . + # use ".peek" if Peek parameter is a) defined and true, + # or b) undefined, but not if it's defined and untrue: + + ( defined($self->Peek) ? + ( $self->Peek ? ".peek" : "" ) : + ".peek" + ) . "[header]" ; + + }else { + $string = "$msg body" . + # use ".peek" if Peek parameter is a) defined and true, or + # b) undefined, but not if it's defined and untrue: + + ( defined($self->Peek) ? + ( $self->Peek ? ".peek" : "" ) : + ".peek" + ) . "[header.fields (" . join(" ",@fields) . ')]' ; + } + + my @raw=$self->fetch( $string ) or return undef; + + + my $h = 0; # reference to hash of current msgid, or 0 between msgs + + for my $header (map { split(/(?:\x0d\x0a)/,$_) } @raw) { + + no warnings; + if ( $header =~ /^\*\s+\d+\s+FETCH\s+\(.*BODY\[HEADER(?:\]|\.FIELDS)/i) { + if ($self->Uid) { + if ( my($msgid) = $header =~ /UID\s+(\d+)/ ) { + $h = {}; + $headers->{$msgid} = $h; + } + else { + $h = {}; + } + } + else { + if ( my($msgid) = $header =~ /^\*\s+(\d+)/ ) { + #start of new message header: + $h = {}; + $headers->{$msgid} = $h; + } + } + } + next if $header =~ /^\s+$/; + + # ( for vi + if ($header =~ /^\)/) { # end of this message + $h = 0; # set to be between messages + next; + } + # check for 'UID)' + # when parsing headers by UID. + if ($self->Uid and my($msgid) = $header =~ /^\s*UID\s+(\d+)\s*\)/) { + $headers->{$msgid} = $h; # store in results against this message + $h = 0; # set to be between messages + next; + } + + if ($h != 0) { # do we expect this to be a header? + my $hdr = $header; + chomp $hdr; + $hdr =~ s/\r$//; + #print "W[$hdr]", ref($hdr), "!\n"; + #next if ( ! defined($hdr)); + #print "X[$hdr]\n"; + + if (defined($hdr) and ($hdr =~ s/^(\S+):\s*//)) { + # if ($hdr =~ s/^(\S+):\s*//) { + #print "X1\n"; + $field = exists $fieldmap{lc($1)} ? $fieldmap{lc($1)} : $1 ; + push @{$h->{$field}} , $hdr ; + } elsif ($hdr =~ s/^.*FETCH\s\(.*BODY\[HEADER\.FIELDS.*\)\]\s(\S+):\s*//) { + #print "X2\n"; + $field = exists $fieldmap{lc($1)} ? $fieldmap{lc($1)} : $1 ; + push @{$h->{$field}} , $hdr ; + } elsif ( ref($h->{$field}) eq 'ARRAY') { + #print "X3\n"; + + $hdr =~ s/^\s+/ /; + $h->{$field}[-1] .= $hdr ; + } + } + } + use warnings; +# my $candump = 0; +# if ($self->Debug) { +# eval { +# require Data::Dumper; +# Data::Dumper->import; +# }; +# $candump++ unless $@; +# } + + } + # if we asked for one message, just return its hash, + # otherwise, return hash of numbers => header hash + # if (ref($msgspec) eq 'ARRAY') { + + return $headers; + +}; + + +*Mail::IMAPClient::authenticate = sub { + + my $self = shift; + my $scheme = shift; + my $response = shift; + + $scheme ||= $self->Authmechanism; + $response ||= $self->Authcallback; + my $clear = $self->Clear; + + $self->Clear($clear) + if $self->Count >= $clear and $clear > 0; + + my $count = $self->Count($self->Count+1); + + + my $string = "$count AUTHENTICATE $scheme"; + + $self->_record($count,[ $self->_next_index($self->Transaction), + "INPUT", "$string\x0d\x0a"] ); + + my $feedback = $self->_send_line("$string"); + + unless ($feedback) { + $self->LastError("Error sending '$string' to IMAP: $!\n"); + return undef; + } + + my ($code, $output); + + until ($code) { + $output = $self->_read_line or return undef; + + foreach my $o (@$output) { + $self->_record($count,$o); # $o is a ref + ($code) = $o->[DATA] =~ /^\+(.*)$/ ; + if ($o->[DATA] =~ /^\*\s+BYE/) { + $self->State(Unconnected); + return undef ; + } + if ($o->[DATA]=~ /^\d+\s+(NO|BAD)/i) { + return undef ; + } + } + } + + if ('CRAM-MD5' eq $scheme && ! $response) { + if ($Mail::IMAPClient::_CRAM_MD5_ERR) { + $self->LastError($Mail::IMAPClient::_CRAM_MD5_ERR); + carp $Mail::IMAPClient::_CRAM_MD5_ERR; + } + else { + $response = \&Mail::IMAPClient::_cram_md5; + } + } + + $feedback = $self->_send_line($response->($code, $self)); + + unless ($feedback) { + $self->LastError("Error sending append msg text to IMAP: $!\n"); + return undef; + } + + $code = ""; # clear code + until ($code) { + $output = $self->_read_line or return undef; + foreach my $o (@$output) { + $self->_record($count,$o); # $o is a ref + if ( ($code) = $o->[DATA] =~ /^\+ (.*)$/ ) { + $feedback = $self->_send_line($response->($code,$self)); + unless ($feedback) { + $self->LastError("Error sending append msg text to IMAP: $!\n"); + return undef; + } + $code = "" ; # Clear code; we're still not finished + } else { + $o->[DATA] =~ /^$count (OK|NO|BAD)/ and $code = $1; + if ($o->[DATA] =~ /^\*\s+BYE/) { + $self->State(Unconnected); + return undef ; + } + } + } + } + + $code =~ /^OK/ and $self->State(Authenticated) ; + return $code =~ /^OK/ ? $self : undef ; + +}; + + + +*Mail::IMAPClient::_cram_md5 = sub { + my ($code, $client) = @_; + my $hmac = Digest::HMAC_MD5::hmac_md5_hex(MIME::Base64::decode($code), + $client->Password()); + return MIME::Base64::encode($client->User() . " $hmac", ""); +}; + +*Mail::IMAPClient::message_string = sub { + my $self = shift; + my $msg = shift; + my $expected_size = $self->size($msg); + return undef unless(defined $expected_size); # unable to get size + my $cmd = $self->has_capability('IMAP4REV1') ? + "BODY" . ( $self->Peek ? '.PEEK[]' : '[]' ) : + "RFC822" . ( $self->Peek ? '.PEEK' : '' ) ; + + #print "Message_string Beg fetch:\n", memory_consumption(); + $self->fetch($msg,$cmd) or return undef; + #print "Message_string End fetch:\n", memory_consumption(); + + my $string = ""; + + + foreach my $result (@{$self->{"History"}{$self->Transaction}}) { + $string .= $result->[DATA] + if defined($result) and $self->_is_literal($result) ; + } + #print "Message_string End string:\n", memory_consumption(); + + # BUG? should probably return undef if length != expected + # No bug, somme servers are buggy. + + if (! $self->Ignoresizeerrors ) { + if ( length($string) != $expected_size ) { + warn "message_string: " . + "expected $expected_size bytes but received " . + length($string) . "\n"; + $self->LastError("message_string: expected ". + "$expected_size bytes but received " . + length($string)."\n"); + } + } + return $string; +}; + + + +{ +no warnings 'once'; + +*Mail::IMAPClient::Ssl = sub { + my $self = shift; + + if (@_) { $self->{SSL} = shift } + return $self->{SSL}; +}; + +*Mail::IMAPClient::exists = sub { + my ( $self, $folder ) = @_; + $self->status($folder) ? $self : undef; +}; + + + +*Mail::IMAPClient::Authuser = sub { + my $self = shift; + + if (@_) { $self->{AUTHUSER} = shift } + return $self->{AUTHUSER}; +}; + + +*Mail::IMAPClient::Ignoresizeerrors = sub { + my $self = shift; + + if (@_) { $self->{IGNORESIZEERRORS} = shift } + return $self->{IGNORESIZEERRORS}; +}; + +*Mail::IMAPClient::Reconnectretry = sub { + my $self = shift; + + if (@_) { $self->{RECONNECTRETRY} = shift } + return $self->{RECONNECTRETRY}; +}; + + +*Mail::IMAPClient::reconnect = sub { + my $self = shift; + + if ( $self->IsAuthenticated ) { + $self->_debug("reconnect called but already authenticated"); + return $self; + } + + my $einfo = $self->LastError || ""; + $self->_debug( "reconnecting to ", $self->Server, ", last error: $einfo" ); + + # reconnect and select appropriate folder + $self->connect or return undef; + + return ( defined $self->Folder ) ? $self->select( $self->Folder ) : $self; +}; + + +# wrapper for _imap_command_do to enable retrying on lost connections +*Mail::IMAPClient::_imap_command = sub { + my $self = shift; + + my $tries = 0; + my $retry = $self->Reconnectretry || 0; + my ( $rc, @err ); + + #print "@_ Beg _imap_command:\n", memory_consumption(); + + # LastError (if set) will be overwritten masking any earlier errors + while ( $tries++ <= $retry ) { + # do command on the first try or if Connected (reconnect ongoing) + if ( $tries == 1 or $self->IsConnected ) { + #print "call @_\n"; + $rc = $self->_imap_command_do(@_); + push( @err, $self->LastError ) if $self->LastError; + #print "call @_ done [", $rc || '', "] [$tries/$retry][" . $self->IsUnconnected . "]\n"; + } + + if ( !defined($rc) and $retry and $self->IsUnconnected + and $self->LastIMAPCommand !~ /LOGOUT/) { + print "\nWarning: disconnected. "; + if ( $self->reconnect ) { + print "Reconnect successful on try #$tries\n"; + $self->Reconnect_counter($self->Reconnect_counter() + 1); + } + else { + print "Reconnect failed on try #$tries\n"; + push( @err, $self->LastError ) if $self->LastError; + } + } + else { + last; + } + } + + unless ($rc) { + my ( %seen, @keep, @info ); + + foreach my $str (@err) { + my ( $sz, $len ) = ( 96, length($str) ); + $str =~ s/$CR?$LF$/\\n/omg; + if ( !$self->Debug and $len > $sz * 2 ) { + my $beg = substr( $str, 0, $sz ); + my $end = substr( $str, -$sz, $sz ); + $str = $beg . "..." . $end; + } + next if $seen{$str}++; + push( @keep, $str ); + } + foreach my $msg (@keep) { + push( @info, $msg . ( $seen{$msg} > 1 ? " ($seen{$msg}x)" : "" ) ); + } + $self->LastError( join( "; ", @info ) ); + } + #print "@_ End _imap_command:\n", memory_consumption(); + return $rc; +}; + + +*Mail::IMAPClient::_imap_command_do = sub { + + my $self = shift; + my $string = shift or return undef; + my $good = shift || 'GOOD'; + + my $qgood = quotemeta($good); + + my $clear = ""; + $clear = $self->Clear; + + $self->Clear($clear) + if $self->Count >= $clear and $clear > 0; + + my $count = $self->Count($self->Count+1); + + $string = "$count $string" ; + + #print "$string\n", memory_consumption(); + $self->_record($count,[ 0, "INPUT", "$string\x0d\x0a"] ); + #print "\n2 $count\n", memory_consumption(); + my $feedback = $self->_send_line("$string"); + + unless ($feedback) { + $self->LastError( "Error sending '$string' to IMAP: $!\n"); + $@ = "Error sending '$string' to IMAP: $!"; + carp "Error sending '$string' to IMAP: $!"; + return undef; + } + + my ($code, $output); + $output = ""; + + READ: until ( $code) { + # escape infinite loop if read_line never returns any data: + $output = $self->_read_line or return undef; + + for my $o (@$output) { + + $self->_record($count,$o); # $o is a ref + # $self->_debug("Received from readline: ${\($o->[DATA])}<>\n"); + next unless $self->_is_output($o); + if ( $good eq '+' ) { + $o->[DATA] =~ /^$count (OK|BAD|NO|$qgood)|^($qgood)/mi ; + $code = $1||$2 ; + } else { + ($code) = $o->[DATA] =~ /^$count (OK|BAD|NO|$qgood)/mi ; + } + if ($o->[DATA] =~ /^\*\s+BYE/im) { + $self->State(Unconnected); + return undef ; + } + } + } + #print "$string: returned $code\n", memory_consumption(); + # $self->_debug("Command $string: returned $code\n"); + return $code =~ /^OK|$qgood/im ? $self : undef ; + +}; + +# capability 2.2.9 is stupid: it caches and return first imap CAPABILITY call +# but call imap CAPABILITY each time. +# Copy/paste from 3.25 +*Mail::IMAPClient::capability = sub { + my $self = shift; + + if ( $self->{CAPABILITY} ) { + my @caps = keys %{ $self->{CAPABILITY} }; + return wantarray ? @caps : \@caps; + } + + $self->_imap_command('CAPABILITY') + or return undef; + + my @caps = map { split } grep s/^\*\s+CAPABILITY\s+//, $self->History; + foreach (@caps) { + $self->{CAPABILITY}{ uc $_ }++; + $self->{ uc $1 } = uc $2 if /(.*?)\=(.*)/; + } + + return wantarray ? @caps : \@caps; +}; + +*Mail::IMAPClient::_read_line = sub { + my $self = shift; + my $sh = $self->Socket; + my $literal_callback = shift; + my $output_callback = shift; + + unless ($self->IsConnected and $self->Socket) { + $self->LastError("NO Not connected.\n"); + carp "Not connected" if $^W; + return undef; + } + + my $iBuffer = ""; + my $oBuffer = []; + my $count = 0; + my $index = $self->_next_index($self->Transaction); + my $rvec = my $ready = my $errors = 0; + my $timeout = $self->Timeout; + + my $readlen = 1; + my $fast_io = $self->Fast_io; # Remember setting to reduce future method calls + + if ( $fast_io ) { + + # set fcntl if necessary: + exists $self->{_fcntl} or $self->Fast_io($fast_io); + $readlen = $self->{Buffer}||4096; + } + until ( + # there's stuff in output buffer: + scalar(@$oBuffer) and + + # the last thing there has cr-lf: + $oBuffer->[-1][DATA] =~ /\x0d\x0a$/ and + + # that thing is an output line: + $oBuffer->[-1][TYPE] eq "OUTPUT" and + + # and the input buffer has been MT'ed: + $iBuffer eq "" + + ) { + #print memory_consumption(); + my $transno = $self->Transaction; # used below in several places + if ($timeout) { + vec($rvec, fileno($self->Socket), 1) = 1; + my @ready = $self->{_select}->can_read($timeout) ; + unless ( @ready ) { + $self->LastError("Tag $transno: " . + "Timeout after $timeout seconds " . + "waiting for data from server\n"); + $self->_record($transno, + [ $self->_next_index($transno), + "ERROR", + "$transno * NO Timeout after ". + "$timeout seconds " . + "during read from " . + "server\x0d\x0a" + ] + ); + $self->LastError( + "Timeout after $timeout seconds " . + "during read from server\x0d\x0a" + ); + return undef; + } + } + + #local($^W) = undef; # Now quiet down warnings + + # read "$readlen" bytes (or less): + # need to check return code from $self->_sysread + # in case other end has shut down!!! + my $ret = $self->_sysread( $sh, \$iBuffer, $readlen, length($iBuffer)) ; + # $self->_debug("Read so far: $iBuffer<>\n"); + redo if(! defined($ret)) ; + if(($timeout and ! defined($ret))) { # Blocking read error... + my $msg = "Error while reading data from server: $!\x0d\x0a"; + $self->LastError('Error while reading data from server'); + $self->State(Unconnected); + print $msg; + $self->_record($transno, + [ $self->_next_index($transno), + "ERROR", "$transno * NO $msg " + ]); + $@ = "$msg"; + + return undef; + } + elsif(defined($ret) and $ret == 0) { # Caught EOF... + my $msg="Socket closed while reading data from server [$!]\x0d\x0a"; + print "$msg"; + $self->LastError('Socket closed while reading data from server'); + $self->State(Unconnected); + $self->_record($transno, + [ $self->_next_index($transno), + "ERROR", "$transno * NO $msg " + ]); + $@ = "$msg"; + return undef; + } + + # successfully wrote to other end, keep going... + $count += $ret; + LINES: while ( $iBuffer =~ s/^(.*?\x0d?\x0a)// ) { + my $current_line = $1; + #print memory_consumption(); + + # $self->_debug("BUFFER: pulled from buffer: ${current_line}\n" . + # "and left with buffer contents of: ${iBuffer}\n"); + + LITERAL: if ($current_line =~ s/\{(\d+)\}\x0d\x0a$//) { + # This part handles IMAP "Literals", + # which according to rfc2060 look something like this: + # [tag]|* BLAH BLAH {nnn}\r\n + # [nnn bytes of literally transmitted stuff] + # [part of line that follows literal data]\r\n + + # Set $len to be length of impending literal: + my $len = $1 ; + + $self->_debug("LITERAL: received literal in line ". + "$current_line of length $len; ". + "attempting to ". + "retrieve from the " . length($iBuffer) . + " bytes in: $iBuffer\n"); + + # Xfer up to $len bytes from front of $iBuffer to $litstring: + my $litstring = substr($iBuffer, 0, $len); + $iBuffer = substr($iBuffer, length($litstring), + length($iBuffer) - length($litstring) ) ; + + # Figure out what's left to read (i.e. what part of + # literal wasn't in buffer): + my $remainder_count = $len - length($litstring); + my $callback_value = ""; + + if ( defined($literal_callback) ) { + if ( $literal_callback =~ /GLOB/) { + print $literal_callback $litstring ; + $litstring = ""; + } elsif ($literal_callback =~ /CODE/ ) { + # Don't do a thing + + } else { + $self->LastError( + ref($literal_callback) . + " is an invalid callback type; " . + "must be a filehandle or coderef\n" + ); + } + + + } + if ($remainder_count > 0 and $timeout) { + # If we're doing timeouts then here we set up select + # and wait for data from the the IMAP socket. + vec($rvec, fileno($self->Socket), 1) = 1; + unless ( CORE::select( $ready = $rvec, + undef, + $errors = $rvec, + $timeout) + ) { + # Select failed; that means bad news. + # Better tell someone. + $self->LastError("Tag " . $transno . + ": Timeout waiting for literal data " . + "from server\n"); + carp "Tag " . $transno . + ": Timeout waiting for literal data " . + "from server\n" + if $self->Debug or $^W; + return undef; + } + } + + fcntl($sh, F_SETFL, $self->{_fcntl}) + if $fast_io and defined($self->{_fcntl}); + while ( $remainder_count > 0 ) { # As long as not done, + $self->_debug("Still need $remainder_count to " . + "complete literal string\n"); + my $ret = $self->_sysread( # bytes read + $sh, # IMAP handle + \$litstring, # place to read into + $remainder_count, # bytes left to read + length($litstring) # offset to read into + ) ; + $self->_debug("Received ret=$ret and buffer = " . + "\n$litstring\nwhile processing LITERAL\n"); + if ( $timeout and !defined($ret)) { # possible timeout + $self->_record($transno, [ + $self->_next_index($transno), + "ERROR", + "$transno * NO Error reading data " . + "from server: $!\n" + ] + ); + return undef; + } elsif ( $ret == 0 and eof($sh) ) { + $self->_record($transno, [ + $self->_next_index($transno), + "ERROR", + "$transno * ". + "BYE Server unexpectedly " . + "closed connection: $!\n" + ] + ); + $self->State(Unconnected); + return undef; + } + # decrement remaining bytes by amt read: + $remainder_count -= $ret; + + if ( length($litstring) > $len ) { + # copy the extra struff into the iBuffer: + $iBuffer = substr( + $litstring, + $len, + length($litstring) - $len + ); + $litstring = substr($litstring, 0, $len) ; + } + + if ( defined($literal_callback) ) { + if ( $literal_callback =~ /GLOB/ ) { + print $literal_callback $litstring; + $litstring = ""; + } + } + + } + $literal_callback->($litstring) + if defined($litstring) and + defined($literal_callback) and $literal_callback =~ /CODE/; + + $self->Fast_io($fast_io) if $fast_io; + + # Now let's make sure there are no IMAP server output lines + # (i.e. [tag|*] BAD|NO|OK Text) embedded in the literal string + # (There shouldn't be but I've seen it done!), but only if + # EnableServerResponseInLiteral is set to true + + my $embedded_output = 0; + my $lastline = ( split(/\x0d?\x0a/,$litstring))[-1] + if $litstring; + + if ( $self->EnableServerResponseInLiteral and + $lastline and + $lastline =~ /^(?:\*|(\d+))\s(BAD|NO|OK)/i + ) { + $litstring =~ s/\Q$lastline\E\x0d?\x0a//; + $embedded_output++; + + $self->_debug("Got server output mixed in " . + "with literal: $lastline\n" + ) if $self->Debug; + + } + # Finally, we need to stuff the literal onto the + # end of the oBuffer: + push @$oBuffer, [ $index++, "OUTPUT" , $current_line], + [ $index++, "LITERAL", $litstring ]; + push @$oBuffer, [ $index++, "OUTPUT", $lastline ] + if $embedded_output; + + } else { + push @$oBuffer, [ $index++, "OUTPUT" , $current_line ]; + } + + } + #$self->_debug("iBuffer is now: $iBuffer<>\n"); + } + # _debug $self, "Buffer is now $buffer\n"; + _debug $self, "Read: " . join("",map {$_->[DATA]} @$oBuffer) ."\n" + if $self->Debug; + return scalar(@$oBuffer) ? $oBuffer : undef ; +}; + + + +} + +# End of sub override_imapclient (yes, very bad indentation) +} + +# IMAPClient 2.2.9 3.xx ads + +package Mail::IMAPClient; + +sub Split { + my $self = shift; + + if (@_) { + $self->{SPLIT} = shift; + $self->{Maxcommandlength} = 10 * $self->{SPLIT}; + } + return $self->{SPLIT}; +} + +sub Tls { + my $self = shift; + + if (@_) { $self->{TLS} = shift } + return $self->{TLS}; +} + +sub Reconnect_counter { + my $self = shift; + if (@_) { $self->{Reconnect_counter} = shift } + return $self->{Reconnect_counter}; + +} + + +sub Banner { + my $self = shift; + + if (@_) { $self->{BANNER} = shift } + return $self->{BANNER}; +} + + +sub RawSocket2 { + my ( $self, $sock ) = @_; + defined $sock + or return $self->{Socket}; + + $self->{Socket} = $sock; + $self->{_select} = IO::Select->new($sock); + delete $self->{_fcntl}; + #$self->Fast_io( $self->Fast_io ); + $sock; +} + +sub capability_update { + my $self = shift; + + delete $self->{CAPABILITY}; + $self->capability; +} + +sub fetch_hash_2 { + # taken from above *Mail::IMAPClient::fetch_hash + # if last arg is a ref then the fetch is done only + # on the messages listed as the keys of this hash. + # Init an "empty" $hash_ref by value can be done this way: + # @$hash_ref{2, 3, 4, 55} = (undef); + + my $self = shift; + my $hash_ref = ref($_[-1]) ? pop @_ : {}; + my @words = @_; + for (@words) { + s/([\( ])FAST([\) ])/${1}FLAGS INTERNALDATE RFC822\.SIZE$2/i ; + s/([\( ])FULL([\) ])/${1}FLAGS INTERNALDATE RFC822\.SIZE ENVELOPE BODY$2/i ; + } + + my $msgs_ref_all; + if (scalar %$hash_ref) { + $msgs_ref_all = [ sort { $a <=> $b } keys (%$hash_ref) ]; + #print "ZZZZ 1 [@$msgs_ref_all]\n"; + }else{ + $msgs_ref_all = scalar($self->messages); + #print "ZZZZ 2 [@$msgs_ref_all]\n"; + } + + my $split = $self->Split() || scalar(@$msgs_ref_all); + while(my @msgs = splice(@$msgs_ref_all, 0, $split)) { + #print "SPLIT: @msgs\n"; + my $msgs_ref = \@msgs; + my $output = scalar($self->fetch($msgs_ref,"(" . join(" ",@_) . ")")) + ; # unless grep(/\b(?:FAST|FULL)\b/i,@words); + my $x; + for ($x = 0; $x <= $#$output ; $x++) { + my $entry = {}; + my $l = $output->[$x]; + if ($self->Uid) { + my($uid) = $l =~ /\((?:.* )?UID (\d+).*\)/i; + next unless $uid; + if ( defined $hash_ref->{$uid} ) { + $entry = $hash_ref->{$uid} ; + } + else { + $hash_ref->{$uid} ||= $entry; + } + } + else { + my($mid) = $l =~ /^\* (\d+) FETCH/i; + next unless $mid; + if ( defined $hash_ref->{$mid} ) { + $entry = $hash_ref->{$mid} ; + } + else { + $hash_ref->{$mid} ||= $entry; + } + } + + foreach my $w (@words) { + if ( $l =~ /\Q$w\E\s*$/i ) { + $entry->{$w} = $output->[$x+1]; + $entry->{$w} =~ s/(?:\x0a?\x0d)+$//g; + chomp $entry->{$w}; + } + else { + $l =~ /\( # open paren followed by ... + (?:.*\s)? # ...optional stuff and a space + \Q$w\E\s # escaped fetch field + (?:" # then: a dbl-quote + (\\.| # then bslashed anychar(s) or ... + [^"]+) # ... nonquote char(s) + "| # then closing quote; or ... + \( # ...an open paren + (\\.| # then bslashed anychar or ... + [^\)]*) # ... non-close-paren char + \)| # then closing paren; or ... + (\S+)) # unquoted string + (?:\s.*)? # possibly followed by space-stuff + \) # close paren + /xi; + $entry->{$w}=defined($1)?$1:defined($2)?$2:$3; + } + } + } +} + return wantarray ? %$hash_ref : $hash_ref; +} diff --git a/imapsync-1.404 b/imapsync-1.404 new file mode 100755 index 0000000..f75d4b5 --- /dev/null +++ b/imapsync-1.404 @@ -0,0 +1,4830 @@ +#!/usr/bin/perl + +# structure +# pod documentation +# pragmas +# main program +# global variables initialisation +# default values +# folder loop +# subroutines +# IMAPClient 2.2.9 overrides +# IMAPClient 2.2.9 3.xx ads + +=pod + +=head1 NAME + +imapsync - IMAP synchronisation, sync, copy or migration +tool. Synchronise mailboxes between two imap servers. Good +at IMAP migration. More than 36 different IMAP server softwares +supported with success. + +$Revision: 1.404 $ + +=head1 SYNOPSIS + +To synchronise imap account "foo" on "imap.truc.org" + to imap account "bar" on "imap.trac.org" + with foo password "secret1" + and bar password "secret2": + + imapsync \ + --host1 imap.truc.org --user1 foo --password1 secret1 \ + --host2 imap.trac.org --user2 bar --password2 secret2 + +=head1 INSTALL + + imapsync works fine under any Unix OS with perl. + imapsync works fine under Windows (2000, XP) + with Strawberry Perl 5.10 or 5.12 + or as a standalone binary software imapsync.exe + +imapsync is already available directly on the following distributions +(at least): +FreeBSD, Debian, Ubuntu, Gentoo, Fedora, +NetBSD, Darwin, Mandriva and OpenBSD. + + Get imapsync at + http://www.linux-france.org/prj/imapsync/ + + You'll receive a link to a compressed tarball called imapsync-x.xx.tgz + where x.xx is the version number. Untar the tarball where + you want (on Unix): + + tar xzvf imapsync-x.xx.tgz + + Go into the directory imapsync-x.xx and read the INSTALL file. + The INSTALL file is also at + http://www.linux-france.org/prj/imapsync/INSTALL + + The freshmeat record is at http://freshmeat.net/projects/imapsync/ + +=head1 USAGE + + imapsync [options] + +To get a description of each option just run imapsync like this: + + imapsync --help + imapsync + +The option list: + + imapsync [--host1 server1] [--port1 ] + [--user1 ] [--passfile1 ] + [--host2 server2] [--port2 ] + [--user2 ] [--passfile2 ] + [--ssl1] [--ssl2] + [--tls1] [--tls2] + [--authmech1 ] [--authmech2 ] + [--proxyauth1] [--proxyauth2] + [--domain1] [--domain2] + [--authmd51] [--authmd52] + [--folder --folder ...] + [--folderrec --folderrec ...] + [--include ] [--exclude ] + [--prefix2 ] [--prefix1 ] + [--regextrans2 --regextrans2 ...] + [--sep1 ] + [--sep2 ] + [--justfolders] [--justfoldersizes] [--justconnect] [--justbanner] + [--syncinternaldates] + [--idatefromheader] + [--syncacls] + [--regexmess ] [--regexmess ] + [--maxsize ] + [--minsize ] + [--maxage ] + [--minage ] + [--skipheader ] + [--useheader ] [--useheader ] + [--nouid1] [--nouid1] + [--usecache] + [--skipsize] [--allowsizemismatch] + [--delete] [--delete2] + [--expunge] [--expunge1] [--expunge2] [--uidexpunge2] + [--delete2folders] [--delete2foldersonly] [--delete2foldersbutnot] + [--subscribed] [--subscribe] [--subscribe_all] + [--nofoldersizes] + [--dry] + [--debug] [--debugimap][--debugimap1][--debugimap2] + [--timeout ] [--fast] + [--split1] [--split2] + [--reconnectretry1 ] [--reconnectretry2 ] + [--noreleasecheck] + [--pidfile ] + [--tmpdir ] + [--version] [--help] + [--tests] [--tests_debug] + +=cut +# comment + +=pod + +=head1 DESCRIPTION + +The command imapsync is a tool allowing incremental and +recursive imap transfer from one mailbox to another. + +By default all folders are transferred, recursively. + +We sometimes need to transfer mailboxes from one imap server to +another. This is called migration. + +imapsync is a good tool because it reduces the amount +of data transferred by not transferring a given message if it +is already on both sides. Same headers +and the transfer is done only once. All flags are +preserved, unread will stay unread, read will stay read, +deleted will stay deleted. You can stop the transfer at any +time and restart it later, imapsync works well with bad +connections. imapsync is CPU hungry so nice and renice +commands can be a good help. imapsync can be memory hungry too, +especially with large messages. + +You can decide to delete the messages from the source mailbox +after a successful transfer (it is a good feature when migrating). +In that case, use the --delete option. Option --delete implies +also option --expunge so all messages marked deleted on host1 +will be really deleted. +(you can use --noexpunge to avoid this but I don't see any +real world scenario for the combinaison --delete --noexpunge). + +You can also just synchronize a mailbox A from another mailbox B +in case you just want to keep a "live" copy of B in A (--delete2 +may help) + +=head1 OPTIONS + +To get a description of each option just invoke: + +imapsync --help + +=head1 HISTORY + +I wrote imapsync because an enterprise (basystemes) paid me to install +a new imap server without losing huge old mailboxes located on a far +away remote imap server accessible by a low bandwidth link. The tool +imapcp (written in python) could not help me because I had to verify +every mailbox was well transferred and delete it after a good +transfer. imapsync started life as a copy_folder.pl patch. +The tool copy_folder.pl comes from the Mail-IMAPClient-2.1.3 perl +module tarball source (in the examples/ directory of the tarball). + +=head1 EXAMPLE + +While working on imapsync parameters please run imapsync in +dry mode (no modification induced) with the --dry +option. Nothing bad can be done this way. + +To synchronize the imap account "buddy" (with password "secret1") +on host "imap.src.fr" to the imap account "max" (with password "secret2") +on host "imap.dest.fr": + + imapsync --host1 imap.src.fr --user1 buddy --password1 secret1 \ + --host2 imap.dest.fr --user2 max --password2 secret2 + +Then you will have max's mailbox updated from buddy's +mailbox. + +=head1 SECURITY + +You can use --passfile1 instead of --password1 to give the +password since it is safer. With --password1 option any user +on your host can see the password by using the 'ps auxwwww' +command. Using a variable (like $PASSWORD1) is also +dangerous because of the 'ps auxwwwwe' command. So, saving +the password in a well protected file (600 or rw-------) is +the best solution. + +imasync is not totally protected against sniffers on the +network since passwords may be transferred in plain text +if CRAM-MD5 is not supported by your imap servers. Use +--ssl1 (or --tls1) and --ssl2 (or --tls2) to enable +encryption on host1 and host2. + +You may authenticate as one user (typically an admin user), +but be authorized as someone else, which means you don't +need to know every user's personal password. Specify +--authuser1 "adminuser" to enable this on host1. In this +case, --authmech1 PLAIN will be used by default since it +is the only way to go for now. So don't use --authmech1 SOMETHING +with --authuser1 "adminuser", it will not work. +Same behavior with the --authuser2 option. + +When working on Sun/iPlanet/Netscape IMAP servers you must use +--proxyauth1 to enable administrative user to masquerade as another user. +Can also be used on destination server with --proxyauth2 + +=head1 EXIT STATUS + +imapsync will exit with a 0 status (return code) if everything went good. +Otherwise, it exits with a non-zero status. + +So if you have an unreliable internet connection, you can use this loop +in a Bourne shell: + + while ! imapsync ...; do + echo imapsync not complete + done + +=head1 LICENSE + +imapsync is free, open source but not always gratis software cover by +the Do What The Fuck You Want To Public License (WTFPL). +See COPYING file included in the distribution or the web site +http://sam.zoy.org/wtfpl/COPYING + +=head1 MAILING-LIST + +The public mailing-list may be the best way to get support. + +To write on the mailing-list, the address is: + + +To subscribe, send any message (even empty) to: + +then just reply to the confirmation message. + +To unsubscribe, send a message to: + + +To contact the person in charge for the list: + + +The list archives may be available at: +http://www.linux-france.org/prj/imapsync_list/ +So consider that the list is public, anyone +can see your post. Use a pseudonym or do not +post to this list if you want to stay private. + +Thank you for your participation. + +=head1 AUTHOR + +Gilles LAMIRAL + +Feedback good or bad is always welcome. + +The newsgroup comp.mail.imap may be a good place to talk about +imapsync. I read it when imapsync is concerned. +A better place is the public imapsync mailing-list +(see below). + +Gilles LAMIRAL earns his living writing, installing, +configuring and teaching free, open and often gratis +softwares. Do not hesitate to pay him for that services. + +=head1 BUG REPORT GUIDELINES + +Help us to help you: follow the following guidelines. + +Report any bugs or feature requests to the public mailing-list +or to the author. + +Before reporting bugs, read the FAQ, the README and the +TODO files. http://www.linux-france.org/prj/imapsync/ + +Upgrade to last imapsync release, maybe the bug +is already fixed. + +Upgrade to last Mail-IMAPClient Perl module. +http://search.cpan.org/dist/Mail-IMAPClient/ +maybe the bug is already fixed. + +Make a good title with word "imapsync" in it (my spam filter won't filter it), +Don't write an email title with just "imapsync" or "problem", +a good title is made of keywords summary, not too long (one visible line). + +Don't write imapsync in uppercase in the email title, we'll +know you run Windows and you haven't read this README yet. + +Help us to help you: in your report, please include: + + - imapsync version. + + - output given with --debug --debugimap near the failure point. + Isolate a message or two in a folder 'BUG' and use + + imapsync ... --folder 'BUG' --debug --debugimap + + - imap server software on both side and their version number. + + - imapsync with all the options you use, the full command line + you use (except the passwords of course). + + - IMAPClient.pm version. + + - operating system running imapsync. + + - operating systems on both sides and the third side in case + you run imapsync on a foreign host from the both. + + - virtual software context (vmware, xen etc.) + +Most of those values can be found as a copy/paste at the begining of the output. + +One time in your life, read the paper +"How To Ask Questions The Smart Way" +http://www.catb.org/~esr/faqs/smart-questions.html +and then forget it. + +=head1 IMAP SERVERS + +Failure stories reported with the following 3 imap servers: + + - MailEnable 1.54 (Proprietary) http://www.mailenable.com/ + - DBMail 0.9, 2.0.7 (GPL). But DBMail 1.2.1 works. + Patient and confident testers are welcome. + - Imail 7.04 (maybe). + +Success stories reported with the following 40 imap servers +(software names are in alphabetic order): + + - 1und1 H mimap1 84498 [host1] + - a1.net imap.a1.net IMAP4 Ready WARSBL614 00029c23 [host1] + - Archiveopteryx 2.03, 2.04, 2.09, 2.10 [host2], 3.0.0 [host2] + (OSL 3.0) http://www.archiveopteryx.org/ + - BincImap 1.2.3 (GPL) (http://www.bincimap.org/) + - CommuniGatePro server (Redhat 8.0) (Solaris), CommuniGate Pro 5.2.17[host2] (CentOS 5.4) + - Courier IMAP 1.5.1, 2.2.0, 2.1.1, 2.2.1, 3.0.8, 3.0.3, 4.1.1 (GPL) + (http://www.courier-mta.org/) + - Critical Path (7.0.020) + - Cyrus IMAP 1.5, 1.6, 2.1, 2.1.15, 2.1.16, 2.1.18 + 2.2.1, 2.2.2-BETA, 2.2.10, 2.2.12, + v2.2.3-Invoca-RPM-2.2.3-8, + 2.3-alpha (OSI Approved), + v2.2.12-Invoca-RPM-2.2.12-3.RHEL4.1, + 2.2.13, + v2.3.1-Invoca-RPM-2.3.1-2.7.fc5, + v2.3.7, + (http://asg.web.cmu.edu/cyrus/) + - David Tobit V8 (proprietary Message system). + - DBMail 1.2.1, 2.0.4, 2.0.9, 2.2rc1 (GPL) (http://www.dbmail.org/). + 2.0.7 seems buggy. + - Deerfield VisNetic MailServer 5.8.6 [host1] + - dkimap4 [host1] + - Domino (Notes) 4.61[host1], 6.5[host1], 5.0.6, 5.0.7, 7.0.2, 6.0.2CF1, + 7.0.1[host1], 8.0.1[host1], 8.5.2[host2] + - Dovecot 0.99.10.4, 0.99.14, 0.99.14-8.fc4, 1.0-0.beta2.7, + 1.0.0 [dest/source] (LGPL) (http://www.dovecot.org/) + - Eudora WorldMail v2 + - GMX IMAP4 StreamProxy. + - Groupwise IMAP (Novell) 6.x and 7.0. Buggy so see the FAQ. + - hMailServer 5.3.3 [host2], 4.4.1 [host1] (see FAQ) + - iPlanet Messaging server 4.15, 5.1, 5.2 + - IMail 7.15 (Ipswitch/Win2003), 8.12 + - MDaemon 7.0.1, 8.0.2, 8.1, 9.5.4 (Windows server 2003 R2 platform) + - Mercury 4.1 (Windows server 2000 platform) + - Microsoft Exchange Server 5.5, 6.0.6249.0[host1], 6.0.6487.0[host1], + 6.5.7638.1 [host2], Exchange 2007 SP1 (with Update Rollup 2), + Exchange2007-EP-SP2, + Exchange 2010 RTM (Release to Manufacturing) [host2] + - Mirapoint + - Netscape Mail Server 3.6 (Wintel !) + - Netscape Messaging Server 4.15 Patch 7 + - OpenMail IMAP server B.07.00.k0 (Samsung Contact ?) + - OpenWave + - Oracle Beehive [host1] + - Qualcomm Worldmail (NT) + - Rockliffe Mailsite 5.3.11, 4.5.6 + - Samsung Contact IMAP server 8.5.0 + - Scalix v10.1, 10.0.1.3, 11.0.0.431 + - SmarterMail, Smarter Mail 5.0 Enterprise, Smarter Mail 5.5 [host1]. + - SunONE Messaging server 5.2, 6.0 (SUN JES - Java Enterprise System) + - Sun Java(tm) System Messaging Server 6.2-2.05, 6.2-7.05, 6.3 + - Surgemail 3.6f5-5 + - UW-imap servers (imap-2000b) rijkkramer IMAP4rev1 2000.287 + (RedHat uses UW like 2003.338rh), v12.264 Solaris 5.7 (OSI Approved) + (http://www.washington.edu/imap/) + - UW - QMail v2.1 + - Imap part of TCP/IP suite of VMS 7.3.2 + - Zimbra-IMAP 3.0.1 GA 160, 3.1.0 Build 279, 4.0.5, 4.5.2, 4.5.6, 5.5, 6.x + +Please report to the author any success or bad story with +imapsync and do not forget to mention the IMAP server +software names and version on both sides. This will help +future users. To help the author maintaining this section +report the two lines at the begining of the output if they +are useful to know the softwares. Example: + + Host1 software:* OK louloutte Cyrus IMAP4 v1.5.19 server ready + Host2 software:* OK Courier-IMAP ready + +You can use option --justconnect to get those lines. +Example: + + imapsync --host1 imap.troc.org --host2 imap.trac.org --justconnect + + +=head1 HUGE MIGRATION + +Pay special attention to options +--subscribed +--subscribe +--delete +--delete2 +--delete2folders +--expunge +--expunge1 +--expunge2 +--uidexpunge2 +--maxage +--minage +--maxsize +--useheader +--fast +--useuid +--usecache + +If you have many mailboxes to migrate think about a little +shell program. Write a file called file.csv (for example) +containing users and passwords. +The separator used in this example is ';' + +The file.csv file contains: + +user0001;password0001;user0002;password0002 +user0011;password0011;user0012;password0012 +... + +And the shell program is just: + + { while IFS=';' read u1 p1 u2 p2; do + imapsync --user1 "$u1" --password1 "$p1" --user2 "$u2" --password2 "$p2" ... + done ; } < file.csv + +Welcome in shell programming ! + +=head1 Hacking + +Feel free to hack imapsync as the WTFPL Licence permits it. + +=head1 Links + +Entries for imapsync: + http://www.imap.org/products/showall.php + + +=head1 SIMILAR SOFTWARES + + imap_tools : http://www.athensfbc.com/imap_tools + offlineimap : http://software.complete.org/offlineimap + mailsync : http://mailsync.sourceforge.net/ + imapxfer : http://www.washington.edu/imap/ + part of the imap-utils from UW. + mailutil : replace imapxfer in + part of the imap-utils from UW. + http://www.gsp.com/cgi-bin/man.cgi?topic=mailutil + imaprepl : http://www.bl0rg.net/software/ + http://freshmeat.net/projects/imap-repl/ + imap_migrate : http://freshmeat.net/projects/imapmigration/ + imapcopy : http://home.arcor.de/armin.diehl/imapcopy/imapcopy.html + migrationtool : http://sourceforge.net/projects/migrationtool/ + imapmigrate : http://sourceforge.net/projects/cyrus-utils/ + wonko_imapsync: http://wonko.com/article/554 + see also tools/wonko_ruby_imapsync + pop2imap : http://www.linux-france.org/prj/pop2imap/ + + +Feedback (good or bad) will often be welcome. + +$Id: imapsync,v 1.404 2011/02/21 03:35:39 gilles Exp $ + +=cut + + +# pragmas + +use warnings; +++$|; +use strict; +use Carp; +use Getopt::Long; +use Mail::IMAPClient; +use Digest::MD5 qw(md5_base64); +#use Term::ReadKey; +#use IO::Socket::SSL; +use MIME::Base64; +use English; +use File::Basename; +use POSIX qw(uname SIGALRM); +use Fcntl; +use File::Spec; +use File::Path qw(mkpath rmtree); +use IO::Socket qw(:crlf SOL_SOCKET SO_KEEPALIVE); +use Errno qw(EAGAIN EPIPE ECONNRESET); +use File::Glob qw( :glob ) ; +use IO::File; + +use Test::More 'no_plan'; + +eval { require 'usr/include/sysexits.ph' }; + +use constant { + Unconnected => 0, + Connected => 1, # connected; not logged in + Authenticated => 2, # logged in; no mailbox selected + Selected => 3, # mailbox selected +}; + + +# global variables + +my( + $rcs, $pidfile, + $debug, $debugimap, $debugimap1, $debugimap2, $nb_errors, + $host1, $host2, $port1, $port2, + $user1, $user2, $domain1, $domain2, + $password1, $password2, $passfile1, $passfile2, + @folder, @include, @exclude, @folderrec, + $prefix1, $prefix2, + @regextrans2, @regexmess, @regexflag, + $sep1, $sep2, + $syncinternaldates, + $idatefromheader, + $usedatemanip, + $syncacls, + $fastio1, $fastio2, + $maxsize, $minsize, $maxage, $minage, + $skipheader, @useheader, + $skipsize, $allowsizemismatch, $foldersizes, $buffersize, + $delete, $delete2, + $expunge, $expunge1, $expunge2, $uidexpunge2, $dry, + $justfoldersizes, + $authmd5, $authmd51, $authmd52, + $subscribed, $subscribe, $subscribe_all, + $version, $help, + $justconnect, $justfolders, $justbanner, + $fast, + $total_bytes_transferred, + $total_bytes_skipped, + $total_bytes_error, + $nb_msg_transferred, + $nb_msg_skipped, + $nb_msg_skipped_dry_mode, + $h1_nb_msg_duplicate, + $h2_nb_msg_duplicate, + $h1_nb_msg_noheader, + $h2_nb_msg_noheader, + $h1_total_bytes_duplicate, + $h2_total_bytes_duplicate, + $h1_nb_msg_deleted, + $h2_nb_msg_deleted, + $timeout, + $timestart, $timeend, $timediff, + $timesize, $timebefore, + $ssl1, $ssl2, + $tls1, $tls2, + $uid1, $uid2, + $authuser1, $authuser2, + $proxyauth1, $proxyauth2, + $authmech1, $authmech2, + $split1, $split2, + $reconnectretry1, $reconnectretry2, + $tests, $test_builder, $tests_debug, + $allow3xx, $justlogin, + $tmpdir, + $releasecheck, + $max_msg_size_in_bytes, + $modules_version, + $delete2folders, $delete2foldersonly, $delete2foldersbutnot, + $usecache, $debugcache, + $takebody, %h1_msgs_copy_by_uid, $useuid, $h2_uidguess, +); + +# main program + +# global variables initialisation + +$rcs = '$Id: imapsync,v 1.404 2011/02/21 03:35:39 gilles Exp $ '; + +$total_bytes_transferred = 0; +$total_bytes_skipped = 0; +$total_bytes_error = 0; +$nb_msg_transferred = 0; +$nb_msg_skipped = $nb_msg_skipped_dry_mode = 0; +$h1_nb_msg_deleted = $h2_nb_msg_deleted = 0; +$h1_nb_msg_duplicate = $h2_nb_msg_duplicate = 0; +$h1_nb_msg_noheader = $h2_nb_msg_noheader = 0; +$h1_total_bytes_duplicate = $h2_total_bytes_duplicate = 0; + +$nb_errors = 0; +$max_msg_size_in_bytes = 0; + +unless(defined(&_SYSEXITS_H)) { + # 64 on my linux box. + eval 'sub EX_USAGE () {64;}' unless defined(&EX_USAGE); +} + +# @ARGV will be eat by get_options() +my @argv_copy = @ARGV; + +get_options(); + +$modules_version = defined($modules_version) ? $modules_version : 1; + +# $SIG{ INT } = \&catch_continue ; + +$releasecheck = defined($releasecheck) ? $releasecheck : 1; +my $warn_release = ($releasecheck) ? check_last_release() : ''; + +$SIG{ INT } = \&catch_exit ; + +# default values + +$tmpdir ||= File::Spec->tmpdir(); +$pidfile ||= $tmpdir . '/imapsync.pid'; + +# allow Mail::IMAPClient 3.0.xx by default +$allow3xx = defined($allow3xx) ? $allow3xx : 1; + +$takebody = defined($takebody) ? $takebody : 1; + +if ( $fast ) { + $useuid = 1 ; + $foldersizes = 0 ; +} + +# Activate --usecache if --useuid is set and no --nousecache +$usecache = 1 if ( $useuid and ( ! defined( $usecache ) ) ) ; + + + +print banner_imapsync(@argv_copy); + +print "Temp directory is $tmpdir\n"; + +is_valid_directory($tmpdir); +write_pidfile($pidfile) if ($pidfile); + +$modules_version and print "Modules version list:\n", modules_VERSION(), "\n"; + +check_lib_version() or + die "imapsync needs perl lib Mail::IMAPClient release 2.2.9, or 3.25 or superior \n"; + +exit_clean(0) if ($justbanner); + +# By default, 1000 at a time, not more. +$split1 ||= 1000; +$split2 ||= 1000; + +$host1 || missing_option("--host1") ; +$port1 ||= (defined $ssl1 and !defined $tls1) ? 993 : 143; + +$host2 || missing_option("--host2") ; +$port2 ||= (defined $ssl2 && !defined $tls2) ? 993 : 143; + +$debugimap1 = $debugimap2 = 1 if ( $debugimap ) ; +$debug = 1 if ( $debugimap1 or $debugimap2 ) ; + +# By default, don't take size to compare +$skipsize = (defined $skipsize) ? $skipsize : 1; + +$uid1 = defined($uid1) ? $uid1 : 1; +$uid2 = defined($uid2) ? $uid2 : 1; + +# Allow size mismatch by default +$allowsizemismatch = defined($allowsizemismatch) ? $allowsizemismatch : 1; + +$delete2folders = 1 + if ( defined( $delete2foldersbutnot ) or defined( $delete2foldersonly ) ) ; + +if ($justconnect) { + justconnect(); + exit_clean(0); +} + +$user1 || missing_option("--user1"); +$user2 || missing_option("--user2"); + +$syncinternaldates = defined($syncinternaldates) ? $syncinternaldates : 1; + +# Turn on expunge if there is not explicit option --noexpunge and option +# --delete is given. +# Done because --delete --noexpunge is very dangerous on the second run: +# the Deleted flag is then synced to all previously transfered messages. +# So --delete implies --expunge is a better usability default behaviour. +if ($delete) { + if ( ! defined($expunge)) { + $expunge = 1; + } +} + +if($idatefromheader) { + print "Turned ON idatefromheader, ", + "will set the internal dates on host2 from the 'Date:' header line.\n"; + $syncinternaldates = 0; + +} +if ($syncinternaldates) { + print "Turned ON syncinternaldates, ", + "will set the internal dates (arrival dates) on host2 same as host1.\n"; +}else{ + print "Turned OFF syncinternaldates\n"; +} + +if(defined($authmd5) and ($authmd5)) { + $authmd51 = 1 ; + $authmd52 = 1 ; +} + +if(defined($authmd51) and ($authmd51)) { + $authmech1 ||= 'CRAM-MD5'; +} +else{ + $authmech1 ||= $authuser1 ? 'PLAIN' : 'LOGIN'; +} + +if(defined($authmd52) and ($authmd52)) { + $authmech2 ||= 'CRAM-MD5'; +} +else{ + $authmech2 ||= $authuser2 ? 'PLAIN' : 'LOGIN'; +} + +$authmech1 = uc($authmech1); +$authmech2 = uc($authmech2); + +if (defined $proxyauth1 && !$authuser1) { + missing_option("With --proxyauth1, --authuser1"); +} + +if (defined $proxyauth2 && !$authuser2) { + missing_option("With --proxyauth2, --authuser2"); +} + +$authuser1 ||= $user1; +$authuser2 ||= $user2; + +print "Will try to use $authmech1 authentication on host1\n"; +print "Will try to use $authmech2 authentication on host2\n"; + +$syncacls = (defined($syncacls)) ? $syncacls : 0; +$foldersizes = (defined($foldersizes)) ? $foldersizes : 1; + +$fastio1 = (defined($fastio1)) ? $fastio1 : 0; +$fastio2 = (defined($fastio2)) ? $fastio2 : 0; + +$reconnectretry1 = (defined($reconnectretry1)) ? $reconnectretry1 : 3; +$reconnectretry2 = (defined($reconnectretry2)) ? $reconnectretry2 : 3; + +@useheader = ("Message-Id") unless (@useheader); + +print "Host1: imap server [$host1] port [$port1] user [$user1]\n"; +print "Host2: imap server [$host2] port [$port2] user [$user2]\n"; + +$password1 || $passfile1 || do { + $password1 = ask_for_password($authuser1 || $user1, $host1); +}; + +$password1 = (defined($passfile1)) ? firstline ($passfile1) : $password1; + +$password2 || $passfile2 || do { + $password2 = ask_for_password($authuser2 || $user2, $host2); +}; + +$password2 = (defined($passfile2)) ? firstline ($passfile2) : $password2; + +my $imap1 = (); +my $imap2 = (); + +$timestart = time(); +$timebefore = $timestart; + +$debugimap1 and print "Host1 connection\n"; +$imap1 = login_imap($host1, $port1, $user1, $domain1, $password1, + $debugimap1, $timeout, $fastio1, $ssl1, $tls1, + $authmech1, $authuser1, $reconnectretry1, + $proxyauth1, $uid1); + +$debugimap2 and print "Host2 connection\n"; +$imap2 = login_imap($host2, $port2, $user2, $domain2, $password2, + $debugimap2, $timeout, $fastio2, $ssl2, $tls2, + $authmech2, $authuser2, $reconnectretry2, + $proxyauth2, $uid2); + +# history + +$debug and print "Host1 Buffer I/O: ", $imap1->Buffer(), "\n"; +$debug and print "Host2 Buffer I/O: ", $imap2->Buffer(), "\n"; + + + +die_clean() unless $imap1->IsAuthenticated(); +print "Host1: state Authenticated\n"; +die_clean() unless $imap2->IsAuthenticated(); +print "Host2: state Authenticated\n"; + +print "Host1 capability: ", join(" ", $imap1->capability_update()), "\n"; +print "Host2 capability: ", join(" ", $imap2->capability_update()), "\n"; + + +exit_clean(0) if ($justlogin); + +$split1 and $imap1->Split($split1); +$split2 and $imap2->Split($split2); + +# +# Folder stuff +# + +my ( +@h1_folders_all, %h1_folders_all, @h1_folders_wanted, %requested_folder, %subscribed_folder, +@h2_folders_all, %h2_folders_all, @h2_folders_from_1, %h2_folders_from_1, +); + + +# Make a hash of subscribed folders in source server. +map { $subscribed_folder{$_} = 1 } $imap1->subscribed(); + +# All folders on host1 and host2 +@h1_folders_all = sort $imap1->folders(); +@h2_folders_all = sort $imap2->folders(); + +map { $h1_folders_all{$_} = 1} @h1_folders_all; +map { $h2_folders_all{$_} = 1} @h2_folders_all; + +if (scalar(@folder) or $subscribed or scalar(@folderrec)) { + # folders given by option --folder + if (scalar(@folder)) { + add_to_requested_folders(@folder); + } + + # option --subscribed + if ($subscribed) { + add_to_requested_folders(keys (%subscribed_folder)); + } + + # option --folderrec + if (scalar(@folderrec)) { + foreach my $folderrec (@folderrec) { + add_to_requested_folders($imap1->folders($folderrec)); + } + } +} +else { + # no include, no folder/subscribed/folderrec options => all folders + if (not scalar(@include)) { + add_to_requested_folders(@h1_folders_all); + } +} + + +# consider (optional) includes and excludes +if (scalar(@include)) { + foreach my $include (@include) { + my @included_folders = grep /$include/, @h1_folders_all; + add_to_requested_folders(@included_folders); + print "Including folders matching pattern '$include': @included_folders\n"; + } +} + +if (scalar(@exclude)) { + foreach my $exclude (@exclude) { + my @requested_folder = sort(keys(%requested_folder)); + my @excluded_folders = grep /$exclude/, @requested_folder; + remove_from_requested_folders(@excluded_folders); + print "Excluding folders matching pattern '$exclude': @excluded_folders\n"; + } +} + +# Remove no selectable folders + +foreach my $folder (keys(%requested_folder)) { + if ( not $imap1->selectable($folder)) { + print "Warning: ignoring folder $folder because it is not selectable\n"; + remove_from_requested_folders($folder); + } +} + + +my @requested_folder = sort(keys(%requested_folder)); + +@h1_folders_wanted = @requested_folder; + +my($h1_sep,$h2_sep); +# what are the private folders separators for each server ? + +$debug and print "Getting separators\n"; +$h1_sep = get_separator($imap1, $sep1, "--sep1"); +$h2_sep = get_separator($imap2, $sep2, "--sep2"); + +#my $h1_namespace = $imap1->namespace(); +#my $h2_namespace = $imap2->namespace(); +#$debug and print "Host1 namespace:\n", Data::Dumper->Dump([$h1_namespace]); +#$debug and print "Host2 namespace:\n", Data::Dumper->Dump([$h2_namespace]); + +my($h1_prefix,$h2_prefix); +$h1_prefix = get_prefix($imap1, $prefix1, "--prefix1"); +$h2_prefix = get_prefix($imap2, $prefix2, "--prefix2"); + + +print "Host1 separator and prefix: [$h1_sep][$h1_prefix]\n"; +print "Host2 separator and prefix: [$h2_sep][$h2_prefix]\n"; + + +foreach my $h1_fold (@h1_folders_wanted) { + my $h2_fold; + $h2_fold = imap2_folder_name($h1_fold); + $h2_folders_from_1{$h2_fold}++; +} + +@h2_folders_from_1 = sort keys(%h2_folders_from_1); + +if ($foldersizes) { + foldersizes("Host1", $imap1, @h1_folders_wanted); + foldersizes("Host2", $imap2, @h2_folders_from_1); +} + + +exit_clean(0) if ($justfoldersizes); + +print + "++++ Listing folders\n", + "Host1 folders list:\n", map("[$_]\n",@h1_folders_all),"\n", + "Host2 folders list:\n", map("[$_]\n",@h2_folders_all),"\n"; + +print + "Host1 subscribed folders list: ", + map("[$_] ", sort keys(%subscribed_folder)), "\n" + if ($subscribed); + +my @h2_folders_not_in_1; +@h2_folders_not_in_1 = list_folders_in_2_not_in_1(); + +print "Folders in host2 not in host1:\n", + map("[$_]\n", @h2_folders_not_in_1),"\n"; + +delete_folders_in_2_not_in_1() if $delete2folders; + +# folder loop +print "++++ Looping on each folder\n"; + +FOLDER: foreach my $h1_fold (@h1_folders_wanted) { + + my $h2_fold = imap2_folder_name($h1_fold); + + printf("%-35s -> %-35s\n", "[$h1_fold]", "[$h2_fold]"); + + select_folder($imap1, $h1_fold, 'Host1') or next FOLDER; + + + if ( ! exists($h2_folders_all{$h2_fold})) { + create_folder($imap2, $h2_fold, 'Host2') or next FOLDER; + } + + acls_sync($h1_fold, $h2_fold); + + select_folder($imap2, $h2_fold, 'Host2') or next FOLDER; + my @select_results = $imap2->Results(); + + #print "%%% @select_results\n"; + my $permanentflags2 = permanentflags(@select_results); + + if ($expunge){ + print "Expunging host1 $h1_fold\n"; + unless($dry) { $imap1->expunge() }; + #print "Expunging host2 $h2_fold\n"; + #unless($dry) { $imap2->expunge() }; + } + + if (($subscribe and exists $subscribed_folder{$h1_fold}) or $subscribe_all) { + print "Subscribing to folder $h2_fold on destination server\n"; + unless($dry) { $imap2->subscribe($h2_fold) }; + } + + next FOLDER if ($justfolders); + + my @h1_msgs = select_msgs($imap1); + + $debug and print "LIST Host1: ", scalar(@h1_msgs), " messages [@h1_msgs]\n"; + # internal dates on host2 are after the ones on host1 + # normally... + my @h2_msgs = select_msgs($imap2); + + $debug and print "LIST Host2: ", scalar(@h2_msgs), " messages [@h2_msgs]\n"; + + my $cache_base = "$tmpdir/imapsync_cache/$host1/$user1/$host2/$user2"; + my $cache_dir = cache_folder( $cache_base, $h1_fold, $h2_fold ); + my ( $cache_1_2_ref, $cache_2_1_ref ) = ( {}, {} ); + + if ( $usecache ) { + print "cache directory: $cache_dir\n" ; + mkpath( "$cache_dir" ) ; + ( $cache_1_2_ref, $cache_2_1_ref ) = get_cache($cache_dir, \@h1_msgs, \@h2_msgs) if ($usecache) ; + print "CACHE h1 h2: ", scalar( keys %$cache_1_2_ref ), " files\n" ; + $debug and print '[', + map ( { "$_->$cache_1_2_ref->{$_} " } keys %$cache_1_2_ref ), " ]\n"; + #print "CACHE h2 h1: ", scalar( keys %$cache_2_1_ref ), " files\n" ; + #$debug and print '[', + # map ( { "$_->$cache_2_1_ref->{$_} " } keys %$cache_2_1_ref ), " ]\n"; + } + #sleep 4 ; + + my %h1_hash = (); + my %h2_hash = (); + + my ( %h1_msgs_all, %h2_msgs_all ) ; + @h1_msgs_all{ @h1_msgs } = (); + @h2_msgs_all{ @h2_msgs } = (); + + my @h1_msgs_in_cache = sort { $a <=> $b } keys %$cache_1_2_ref ; + my @h2_msgs_in_cache = keys %$cache_2_1_ref ; + + my ( %h1_msgs_no_cache, %h2_msgs_no_cache ) ; + %h1_msgs_no_cache = %h1_msgs_all ; + %h2_msgs_no_cache = %h2_msgs_all ; + delete @h1_msgs_no_cache{ @h1_msgs_in_cache } ; + delete @h2_msgs_no_cache{ @h2_msgs_in_cache } ; + + my @h1_msgs_no_cache = keys %h1_msgs_no_cache ; + my @h2_msgs_no_cache = keys %h2_msgs_no_cache ; + + + if ( $useuid ) { + @h1_msgs_copy_by_uid{ @h1_msgs_no_cache } = ( ) ; + @h1_msgs_no_cache = ( ) ; + @h2_msgs_no_cache = ( ) ; + } + + $debug and print "Host1 folder [$h1_fold] parsing headers\n"; + + my ($h1_heads_ref, $h1_fir_ref) = ({}, {}); + $h1_heads_ref = $imap1->parse_headers([@h1_msgs_no_cache], @useheader) if (@h1_msgs_no_cache); + $debug and print "Time headers: ", timenext(), " s\n"; + + @$h1_fir_ref{@h1_msgs} = (undef); + $h1_fir_ref = $imap1->fetch_hash_2("FLAGS", "INTERNALDATE", "RFC822.SIZE", $h1_fir_ref) + if (@h1_msgs); + $debug and print "Time fir: ", timenext(), " s\n"; + unless ($h1_fir_ref) { + warn + "Host1 folder $h1_fold: Could not fetch_hash_2 ", + scalar(@h1_msgs), " msgs: ", $imap1->LastError, "\n"; + $nb_errors++; + next FOLDER; + } + + my @h1_msgs_duplicate; + foreach my $m (@h1_msgs_no_cache) { + my $rc = parse_header_msg($imap1, $m, $h1_heads_ref, $h1_fir_ref, "F", \%h1_hash); + if (! defined($rc)) { + my $h1_size = $h1_fir_ref->{$m}->{"RFC822.SIZE"} || 0; + print "+ Skipping msg #$m:$h1_size on host1 folder $h1_fold (no header so we ignore this message)\n"; + $total_bytes_skipped += $h1_size; + $nb_msg_skipped += 1; + $h1_nb_msg_noheader +=1; + } elsif(0 == $rc) { + # duplicate + push(@h1_msgs_duplicate, $m); + # duplicate, same id same size? + my $h1_size = $h1_fir_ref->{$m}->{"RFC822.SIZE"} || 0; + $nb_msg_skipped += 1; + $h1_total_bytes_duplicate += $h1_size; + $h1_nb_msg_duplicate += 1; + } + } + $debug and print "Time parsing headers on host1: ", timenext(), " s\n"; + + $debug and print "Host2 folder [$h2_fold] parsing headers\n"; + + my ($h2_heads_ref, $h2_fir_ref) = ( {}, {} ); + $h2_heads_ref = $imap2->parse_headers([@h2_msgs_no_cache], @useheader) if (@h2_msgs_no_cache); + $debug and print "Time headers: ", timenext(), " s\n"; + + @$h2_fir_ref{@h2_msgs} = ( ); # fetch_hash_2 can select by uid with last arg as ref + $h2_fir_ref = $imap2->fetch_hash_2("FLAGS", "INTERNALDATE", "RFC822.SIZE", $h2_fir_ref) + if (@h2_msgs); + $debug and print "Time fir: ", timenext(), " s\n"; + + my @h2_msgs_duplicate; + foreach my $m (@h2_msgs_no_cache) { + my $rc = parse_header_msg($imap2, $m, $h2_heads_ref, $h2_fir_ref, "T", \%h2_hash); + my $h2_size = $h2_fir_ref->{$m}->{"RFC822.SIZE"} || 0; + if (! defined($rc)) { + print "+ Skipping msg #$m:$h2_size in host2 folder $h2_fold (no header so we ignore this message)\n"; + $h2_nb_msg_noheader += 1 ; + } elsif(0 == $rc) { + # duplicate + $h2_nb_msg_duplicate += 1; + $h2_total_bytes_duplicate += $h2_size; + push(@h2_msgs_duplicate, $m); + } + } + $debug and print "Time parsing headers on host2: ", timenext(), " s\n"; + + $debug and print "++++ Verifying [$h1_fold] -> [$h2_fold]\n"; + # messages in host1 that are not in host2 + + my @h1_hash_keys_sorted_by_uid + = sort {$h1_hash{$a}{'m'} <=> $h1_hash{$b}{'m'}} keys(%h1_hash); + + #print map { $h1_hash{$_}{'m'} . " "} @h1_hash_keys_sorted_by_uid; + + my @h2_hash_keys_sorted_by_uid + = sort {$h2_hash{$a}{'m'} <=> $h2_hash{$b}{'m'}} keys(%h2_hash); + + + if($delete2) { + my @h2_expunge; + foreach my $m_id (@h2_hash_keys_sorted_by_uid) { + #print "$m_id "; + unless (exists($h1_hash{$m_id})) { + my $h2_msg = $h2_hash{$m_id}{'m'}; + my $h2_flags = $h2_hash{$m_id}{'F'} || ""; + my $isdel = $h2_flags =~ /\B\\Deleted\b/ ? 1 : 0; + print "msg $h2_fold/$h2_msg deleted on host2 [$m_id]\n" + if ! $isdel; + push(@h2_expunge, $h2_msg) if $uidexpunge2; + unless ($dry or $isdel) { + $imap2->delete_message($h2_msg); + $h2_nb_msg_deleted += 1; + } + } + } + foreach my $h2_msg (@h2_msgs_duplicate) { + print "msg $h2_fold/$h2_msg deleted [duplicate] on host2\n"; + push(@h2_expunge, $h2_msg) if $uidexpunge2; + unless ($dry) { + $imap2->delete_message($h2_msg); + $h2_nb_msg_deleted += 1; + } + } + + my $cnt = scalar @h2_expunge; + if(@h2_expunge and !$imap2->can("uidexpunge")) { + warn "uidexpunge not supported (< IMAPClient 3.17)\n"; + } + elsif(@h2_expunge) { + print "uidexpunge $cnt message(s)\n"; + $imap2->uidexpunge(\@h2_expunge) if !$dry; + } + } + + my $h2_uidnext = $imap2->uidnext( $h2_fold ) ; + $h2_uidguess = $h2_uidnext ; + MESS: foreach my $m_id (@h1_hash_keys_sorted_by_uid) { + my $h1_size = $h1_hash{$m_id}{'s'}; + my $h1_msg = $h1_hash{$m_id}{'m'}; + my $h1_idate = $h1_hash{$m_id}{'D'}; + + if (defined $maxsize and $h1_size >= $maxsize) { + print "msg $h1_fold/$h1_msg skipping ($h1_size exceeds maxsize limit $maxsize bytes)\n"; + $total_bytes_skipped += $h1_size; + $nb_msg_skipped += 1; + next MESS; + } + if (defined $minsize and $h1_size <= $minsize) { + print "msg $h1_fold/$h1_msg skipping ($h1_size smaller than minsize $minsize bytes)\n"; + $total_bytes_skipped += $h1_size; + $nb_msg_skipped += 1; + next MESS; + } + + unless (exists($h2_hash{$m_id})) { + # copy + copy_message( $h1_msg, $h1_fold, $h2_fold, $h1_fir_ref, $permanentflags2, $cache_dir ) ; + next MESS; + } + else{ + # already on host2 + my $h2_msg = $h2_hash{$m_id}{'m'} ; + $debug and print "msg $h1_fold/$h1_msg equals $h2_fold/$h2_msg\n" ; + $total_bytes_skipped += $h1_size ; + $nb_msg_skipped += 1 ; + $debugcache and print "touch $cache_dir/${h1_msg}_$h2_msg\n" if ( $usecache ) ; + touch( "$cache_dir/${h1_msg}_$h2_msg" ) if ( $usecache ) ; + } + + #$debug and print "MESSAGE $m_id\n"; + my $h2_msg = $h2_hash{$m_id}{'m'}; + + sync_flags( $h1_msg, $h2_msg, $h2_fold, $permanentflags2, $h1_fir_ref, $h2_fir_ref ) ; + + # Good + my $h2_size = $h2_hash{$m_id}{'s'}; + $debug and print + "msg $h1_fold/$h1_msg sizes $h1_size <> $h2_size $h2_fold/$h2_msg\n"; + if( $delete ) { + print "msg $h1_fold/$h1_msg deleted on host1\n"; + unless( $dry ) { + $imap1->delete_message( $h1_msg ); + $h1_nb_msg_deleted += 1; + $imap1->expunge() if ( $expunge ); + } + } + + } + # END MESS: loop + MESS_IN_CACHE: foreach my $h1_msg ( @h1_msgs_in_cache ) { + my $h2_msg = $cache_1_2_ref->{ $h1_msg } ; + $debugcache and print "cache messages update $h1_msg->$h2_msg\n"; + sync_flags( $h1_msg, $h2_msg, $h2_fold, $permanentflags2, $h1_fir_ref, $h2_fir_ref ) ; + my $h1_size = $h1_fir_ref->{ $h1_msg }->{ 'RFC822.SIZE' } ; + $total_bytes_skipped += $h1_size; + $nb_msg_skipped += 1; + } + + MESS_BY_UID: foreach my $h1_msg ( sort { $a <=> $b } keys %h1_msgs_copy_by_uid ) { + # copy_message + #print "Copy by uid $h1_fold/$h1_msg\n" ; + copy_message( $h1_msg, $h1_fold, $h2_fold, $h1_fir_ref, $permanentflags2, $cache_dir ) ; + + } + + if ($expunge1){ + print "Expunging host1 folder $h1_fold\n"; + unless($dry) { $imap1->expunge() }; + } + if ($expunge2){ + print "Expunging host2 folder $h2_fold\n"; + unless($dry) { $imap2->expunge() }; + } + +$debug and print "Time: ", timenext(), " s\n"; +} + +sub sync_flags { + my ( $h1_msg, $h2_msg, $h2_fold, $permanentflags2, $h1_fir_ref, $h2_fir_ref ) = @_ ; + $debug and print "sync flags $h1_msg->$h2_msg\n"; + + # used cached flag values for efficiency + my $h1_flags = $h1_fir_ref->{ $h1_msg }->{ "FLAGS" } ; + my $h2_flags = $h2_fir_ref->{ $h2_msg }->{ "FLAGS" } ; + + # RFC 2060: This flag can not be altered by any client + $h1_flags =~ s@\\Recent\s?@@gi; + $h1_flags = flags_regex($h1_flags) if @regexflag; + $h1_flags = flags_filter($h1_flags, $permanentflags2) if ( $permanentflags2 ); + + # compare flags - set flags if there a difference + my @h1_flags = sort split(' ', $h1_flags ); + my @h2_flags = sort split(' ', $h2_flags ); + my $diff = compare_lists( \@h1_flags, \@h2_flags ); + + #$diff = 1 ; + $diff and $debug and print "msg $h2_fold/$h2_msg replacing h2 flags( $h2_flags ) with h1 flags( $h1_flags )\n"; + # This sets flags so flags can be removed with this + # When you remove a \Seen flag on host1 you want to it + # to be removed on host2. Just add flags is not what + # we need most of the time. + + if ( ! $dry and $diff and ! $imap2->store( $h2_msg, "FLAGS.SILENT (@h1_flags)" ) ) { + warn "- msg $h2_fold/$h2_msg could not add flags @h1_flags", + $imap2->LastError, "\n"; + #$nb_errors++; + } +} + +print "++++ End looping on each folder\n"; +#print memory_consumption(); + + +$imap1->logout(); +$imap2->logout(); + + +stats(); +exit_clean(1) if( $nb_errors ); +exit_clean(0); + +# END of main program + +# subroutines + +sub max { + return(undef) if (0 == scalar(@_)); + my @sorted = sort { $a <=> $b } @_; + return(pop(@sorted)); +} + +sub tests_max { + ok(0 == max(0), "max 0"); + ok(1 == max(1), "max 1"); + ok(-1 == max(-1), "max -1"); + ok(! defined(max()), "max no arg"); + ok(100 == max(1, 100), "max 1 100"); + ok(100 == max(100, 1), "max 100 1"); + ok(100 == max(100, 42, 1), "max 100 42 1"); + ok(100 == max(100, "42", 1), "max 100 42 1"); + ok(100 == max("100", "42", 1), "max 100 42 1"); + #ok(100 == max(100, "haha", 1), "max 100 42 1"); +} + +sub check_lib_version { + $debug and print "IMAPClient $Mail::IMAPClient::VERSION\n"; + if ($Mail::IMAPClient::VERSION eq '2.2.9') { + override_imapclient(); + return(1); + } + else{ + # 3.x.x is no longer buggy with imapsync. + if ($allow3xx) { + return(1); + }else{ + return(0); + } + } +} + +sub modules_VERSION { + + my @list_version; + + foreach my $module (qw( +Mail::IMAPClient +IO::Socket +IO::Socket::SSL +Digest::MD5 +Digest::HMAC_MD5 +Term::ReadKey +Authen::NTLM)) + { + my $v = "?"; + + if (eval "require $module") { + # module is here + $v = eval "\$${module}::VERSION"; + }else{ + # no module + $v = "?"; + } + #print ("$module ", $v, "\n"); + push (@list_version, sprintf("%-20s %s\n", $module, $v)); + } + return(@list_version); +} + +# Construct a command line copy with passwords replaced by MASKED. +sub command_line_nopassword { + my @argv_copy = @_; + my @argv_nopassword; + while (@argv_copy) { + my $arg = shift(@argv_copy); # option name or value + if ($arg =~ m/-password[12]/) { + shift(@argv_copy); # password value + push(@argv_nopassword, $arg, "MASKED"); # option name and fake value + }else{ + push(@argv_nopassword, $arg); # same option or value + } + } + return("@argv_nopassword"); +} + +sub tests_command_line_nopassword { + + ok('' eq command_line_nopassword(), 'command_line_nopassword void'); + ok('--blabla' eq command_line_nopassword('--blabla'), 'command_line_nopassword --blabla'); + #print command_line_nopassword((qw{ --password1 secret1 })), "\n"; + ok('--password1 MASKED' eq command_line_nopassword(qw{ --password1 secret1}), 'command_line_nopassword --password1'); + ok('--blabla --password1 MASKED --blibli' + eq command_line_nopassword(qw{ --blabla --password1 secret1 --blibli }), 'command_line_nopassword --password1 --blibli'); + + +} + +sub ask_for_password { + my ($user, $host) = @_; + print "What's the password for $user\@$host? "; + Term::ReadKey::ReadMode(2); + my $password = <>; + chomp $password; + printf "\n"; + Term::ReadKey::ReadMode(0); + return $password; +} + +sub catch_exit { + my $signame = shift ; + print "\nGot a SIG$signame!\n" ; + stats( ) ; + exit_clean( ) ; +} + +sub catch_continue { + my $signame = shift ; + print "\nGot a SIG$signame!\n" ; +} + +sub myconnect { + my $self = shift; + + $debug and print "Entering myconnect\n"; + %$self = (%$self, @_); + + my $sock = (($self->Ssl) ? IO::Socket::SSL->new : IO::Socket::INET->new); + my $dp = ($self->Ssl ? 'imaps(993)' : 'imap(143)'); + + $debug and print "Calling configure\n"; + my $ret = $sock->configure({ + PeerAddr => $self->Server , + PeerPort => $self->Port||$dp , + Proto => 'tcp' , + Timeout => $self->Timeout||0 , + Debug => $self->Debug , + }); + unless ( defined($ret) ) { + $self->LastError( "$@\n"); + $@ = "$@"; + carp "$@" + unless defined wantarray; + return undef; + } + $sock->autoflush(1); + + my $banner = $sock->getline(); + $debug and print "Read: $banner"; + + $self->Banner($banner); + $self->RawSocket2($sock); + $self->State(Connected); + + if ($self->Tls) { + starttls($self); + } + + $self->Ignoresizeerrors($allowsizemismatch); + + if ($self->User and $self->Password) { + $debug and print "Calling login\n"; + return $self->login ; + } + else { + return $self; + } +} + + + + +sub starttls { + my $self = shift; + my $socket = $self->RawSocket2(); + + $debug and print "Entering starttls\n"; + unless ($self->has_capability("STARTTLS")) { + die_clean( "No STARTTLS capability" ); + } + print $socket, "\n"; + print $socket "z00 STARTTLS\015\012"; + CORE::select( undef, undef, undef, 0.025 ); + my $txt = $socket->getline(); + $debug and print "Read tls: $txt"; + unless($txt =~ /^z00 OK/){ + die_clean( "Invalid response for STARTTLS: $txt\n" ); + } + $debug and print "Calling start_SSL\n"; + unless(IO::Socket::SSL->start_SSL($socket, + { + SSL_version => "TLSV1", + SSL_startHandshake => 1, + SSL_verify_depth => 1, + })) + { + die_clean( "Couldn't start TLS: ".IO::Socket::SSL::errstr()."\n"); + } + if (ref($socket) ne "IO::Socket::SSL") { + die_clean( "Socket has NOT been converted to SSL"); + }else{ + $debug and print "Socket successfuly converted to SSL\n"; + } + $debug and print "Ending starttls\n"; +} + + + +sub connect_imap { + my($host, $port, $debugimap, $ssl, $tls) = @_; + my $imap = Mail::IMAPClient->new(); + $imap->Ssl($ssl) if ($ssl); + $imap->Tls($tls) if ($tls); + $imap->Server($host); + $imap->Port($port); + $imap->Debug($debugimap); + #$imap->connect() + myconnect($imap) + or die_clean("Can not open imap connection on [$host]: $@\n"); +} + +sub justconnect { + my $imap1 = (); + my $imap2 = (); + + $imap1 = connect_imap($host1, $port1, $debugimap1, $ssl1, $tls1); + print "Host1 software: ", server_banner($imap1); + print "Host1 capability: ", join(" ", $imap1->capability()), "\n"; + $imap2 = connect_imap($host2, $port2, $debugimap2, $ssl2, $tls2); + print "Host2 software: ", server_banner($imap2); + print "Host2 capability: ", join(" ", $imap2->capability()), "\n"; + $imap1->logout(); + $imap2->logout(); + +} + + +sub login_imap { + my($host, $port, $user, $domain, $password, + $debugimap, $timeout, $fastio, + $ssl, $tls, $authmech, $authuser, $reconnectretry, + $proxyauth, $uid) = @_; + my ($imap); + + $imap = Mail::IMAPClient->new(); + + $imap->Ssl($ssl) if ($ssl); + $imap->Tls($tls) if ($tls); + $imap->Clear(1); + $imap->Server($host); + $imap->Port($port); + $imap->Fast_io($fastio); + $imap->Buffer($buffersize || 4096); + $imap->Uid($uid); + #$imap->Uid(0); + $imap->Peek(1); + $imap->Debug($debugimap); + $timeout and $imap->Timeout($timeout); + + $imap->Reconnectretry($reconnectretry) if ($reconnectretry); + + #$imap->connect() + myconnect($imap) + or die_clean("Can not open imap connection on [$host] with user [$user]: $@\n"); + + print "Banner: ", server_banner($imap); + + if ($imap->has_capability("AUTH=$authmech") + or $imap->has_capability($authmech) + ) { + printf("Host %s says it has CAPABILITY for AUTHENTICATE %s\n", + $imap->Server, $authmech); + } + else { + printf("Host %s says it has NO CAPABILITY for AUTHENTICATE %s\n", + $imap->Server, $authmech); + if ($authmech eq 'PLAIN') { + print "Frequently PLAIN is only supported with SSL, ", + "try --ssl1 or --ssl2 option\n"; + } + } + + if ($proxyauth) { + $imap->Authmechanism(""); + } else { + $imap->Authmechanism($authmech) unless ($authmech eq 'LOGIN'); + } + + $imap->Authcallback(\&plainauth) if $authmech eq "PLAIN"; + + + if ($proxyauth) { + $imap->User($authuser); + $imap->Domain($domain) if (defined($domain)); + $imap->Authuser($authuser); + $imap->Password($password); + } else { + $imap->User($user); + $imap->Domain($domain) if (defined($domain)); + $imap->Authuser($authuser); + $imap->Password($password); + } + + unless ($imap->login()) { + my $info = "Error login: [$host] with user [$user] auth"; + my $einfo = $imap->LastError || @{$imap->History}[-1]; + chomp($einfo); + my $error = "$info [$authmech]: $einfo\n"; + print $error; # note: duplicating error on stdout/stderr + die_clean($error) if ($authmech eq 'LOGIN' or $imap->IsUnconnected() or $authuser); + print "Trying LOGIN Auth mechanism on [$host] with user [$user]\n"; + $imap->Authmechanism(""); + $imap->login() or + die_clean("$info [LOGIN]: ", $imap->LastError, "\n"); + } + $proxyauth && $imap->proxyauth($user); + + print "Success login on [$host] with user [$user] auth [$authmech]\n"; + return($imap); +} + + +sub plainauth() { + my $code = shift; + my $imap = shift; + + my $string = sprintf("%s\x00%s\x00%s", $imap->User, + $imap->Authuser, $imap->Password); + return encode_base64("$string", ""); +} + + +sub server_banner { + my $imap = shift; + my $banner = $imap->Banner() || "No banner\n"; + return $banner; + } + + +sub banner_imapsync { + + my @argv_copy = @_; + my $banner_imapsync = join("", + '$RCSfile: imapsync,v $ ', + '$Revision: 1.404 $ ', + '$Date: 2011/02/21 03:35:39 $ ', + "\n",localhost_info(), "\n", + "Command line used:\n", + "$0 ", command_line_nopassword(@argv_copy), "\n", + ); +} + +sub is_valid_directory { + my $dir = shift; + return(1) if (-d $dir and -r _ and -w _); + # Trying to create it + mkpath($dir) or die "Error creating tmpdir $tmpdir : $!"; + die "Error with tmpdir $tmpdir : $!" if not (-d $dir and -r _ and -w _); + return(1); +} + + +sub write_pidfile { + my $pidfile = shift; + + print "PID file is $pidfile\n"; + if (-e $pidfile) { + warn "$pidfile already exists, overwriting it\n"; + } + open(PIDFILE, ">$pidfile") or do { + warn "Could not open $pidfile for writing"; + return undef; + }; + + print PIDFILE $PROCESS_ID; + close PIDFILE; + return($PROCESS_ID); +} + +sub exit_clean { + my $status = shift; + $status = defined( $status ) ? $status : 1 ; + unlink($pidfile); + exit($status); +} + +sub die_clean { + + unlink($pidfile); + die @_; +} + +sub missing_option { + my ($option) = @_; + die_clean("$option option must be used, run $0 --help for help\n"); +} + + +sub select_folder { + my ($imap, $folder, $hostside) = @_; + if ( ! $imap->select($folder)) { + warn + "$hostside folder $folder: Could not select: ", + $imap->LastError, "\n"; + $nb_errors++; + return(0); + }else{ + # ok select succeeded + return(1); + } +} + + +sub create_folder { + my ($imap, $folder, $hostside) = @_; + print "$hostside folder $folder does not exist\n"; + print "Creating folder [$folder]\n"; + if ( ! $dry){ + if ( ! $imap->create($folder)){ + warn "Couldn't create [$folder] on $hostside: ", + $imap->LastError,"\n"; + $nb_errors++; + return(0); + }else{ + #create succeeded + return(1); + } + }else{ + # dry mode, no folder so many imap will fail, assuming failure + return(0); + } +} + + + +sub tests_folder_routines { + ok( !is_requested_folder('folder_foo') ); + ok( add_to_requested_folders('folder_foo') ); + ok( is_requested_folder('folder_foo') ); + ok( !is_requested_folder('folder_NO_EXIST') ); + ok( !remove_from_requested_folders('folder_foo'), "removed folder_foo"); + ok( !is_requested_folder('folder_foo') ); + my @f; + ok( @f = add_to_requested_folders('folder_bar', 'folder_toto'), "add result: @f"); + ok( is_requested_folder('folder_bar') ); + ok( is_requested_folder('folder_toto') ); + ok( remove_from_requested_folders('folder_toto') ); + ok( !is_requested_folder('folder_toto') ); +} + + +sub is_requested_folder { + my ( $folder ) = @_; + + defined( $requested_folder{ $folder } ); +} + + +sub add_to_requested_folders { + my @wanted_folders = @_; + + foreach my $folder ( @wanted_folders ) { + ++$requested_folder{ $folder }; + } + return( keys( %requested_folder ) ); +} + +sub remove_from_requested_folders { + my @wanted_folders = @_; + + foreach my $folder (@wanted_folders) { + delete $requested_folder{$folder}; + } + return( keys(%requested_folder) ); +} + +sub compare_lists { + my ($list_1_ref, $list_2_ref) = @_; + + return(-1) if ((not defined($list_1_ref)) and defined($list_2_ref)); + return(0) if ((not defined($list_1_ref)) and not defined($list_2_ref)); # end if no list + return(1) if (not defined($list_2_ref)); # end if only one list + + if (not ref($list_1_ref)) {$list_1_ref = [$list_1_ref]}; + if (not ref($list_2_ref)) {$list_2_ref = [$list_2_ref]}; + + + my $last_used_indice = -1; + #print "\$#$list_1_ref:", $#$list_1_ref, "\n"; + #print "\$#$list_2_ref:", $#$list_2_ref, "\n"; + ELEMENT: + foreach my $indice ( 0 .. $#$list_1_ref ) { + $last_used_indice = $indice; + + # End of list_2 + return 1 if ($indice > $#$list_2_ref); + + my $element_list_1 = $list_1_ref->[$indice]; + my $element_list_2 = $list_2_ref->[$indice]; + my $balance = $element_list_1 cmp $element_list_2 ; + next ELEMENT if ($balance == 0) ; + return $balance; + } + # each element equal until last indice of list_1 + return -1 if ($last_used_indice < $#$list_2_ref); + + # same size, each element equal + return 0 +} + +sub tests_compare_lists { + + + my $empty_list_ref = []; + + ok( 0 == compare_lists() , 'compare_lists, no args'); + ok( 0 == compare_lists(undef) , 'compare_lists, undef = nothing'); + ok( 0 == compare_lists(undef, undef) , 'compare_lists, undef = undef'); + ok(-1 == compare_lists(undef , []) , 'compare_lists, undef < []'); + ok(-1 == compare_lists(undef , [1]) , 'compare_lists, undef < [1]'); + ok(-1 == compare_lists(undef , [0]) , 'compare_lists, undef < [0]'); + ok(+1 == compare_lists([]) , 'compare_lists, [] > nothing'); + ok(+1 == compare_lists([], undef) , 'compare_lists, [] > undef'); + ok( 0 == compare_lists([] , []) , 'compare_lists, [] = []'); + + ok(-1 == compare_lists([] , [1]) , 'compare_lists, [] < [1]'); + ok(+1 == compare_lists([1] , []) , 'compare_lists, [1] > []'); + + + ok( 0 == compare_lists([1], 1 ) , "compare_lists, [1] = 1 ") ; + ok( 0 == compare_lists( 1 , [1]) , "compare_lists, 1 = [1]") ; + ok( 0 == compare_lists( 1 , 1 ) , "compare_lists, 1 = 1 ") ; + ok(-1 == compare_lists( 0 , 1 ) , "compare_lists, 0 < 1 ") ; + ok(-1 == compare_lists(-1 , 0 ) , "compare_lists, -1 < 0 ") ; + ok(-1 == compare_lists( 1 , 2 ) , "compare_lists, 1 < 2 ") ; + ok(+1 == compare_lists( 2 , 1 ) , "compare_lists, 2 > 1 ") ; + + + ok( 0 == compare_lists([1,2], [1,2]) , "compare_lists, [1,2] = [1,2]") ; + ok(-1 == compare_lists([1], [1,2]) , "compare_lists, [1] < [1,2]") ; + ok(+1 == compare_lists([2], [1,2]) , "compare_lists, [2] > [1,2]") ; + ok(-1 == compare_lists([1], [1,1]) , "compare_lists, [1] < [1,1]") ; + ok(+1 == compare_lists([1, 1], [1]) , "compare_lists, [1, 1] > [1]") ; + ok( 0 == compare_lists([1 .. 20_000] , [1 .. 20_000]) + , "compare_lists, [1..20_000] = [1..20_000]") ; + ok(-1 == compare_lists([1], [3]) , 'compare_lists, [1] < [3]') ; + ok( 0 == compare_lists([2], [2]) , 'compare_lists, [0] = [2]') ; + ok(+1 == compare_lists([3], [1]) , 'compare_lists, [3] > [1]') ; + + ok(-1 == compare_lists(["a"], ["b"]) , 'compare_lists, ["a"] < ["b"]') ; + ok( 0 == compare_lists(["a"], ["a"]) , 'compare_lists, ["a"] = ["a"]') ; + ok( 0 == compare_lists(["ab"], ["ab"]) , 'compare_lists, ["ab"] = ["ab"]') ; + ok(+1 == compare_lists(["b"], ["a"]) , 'compare_lists, ["b"] > ["a"]') ; + ok(-1 == compare_lists(["a"], ["aa"]) , 'compare_lists, ["a"] < ["aa"]') ; + ok(-1 == compare_lists(["a"], ["a", "a"]), 'compare_lists, ["a"] < ["a", "a"]') ; + ok( 0 == compare_lists([split(" ", "a b")], ["a", "b"]), 'compare_lists, split') ; + ok( 0 == compare_lists([sort split(" ", "b a")], ["a", "b"]), 'compare_lists, sort split') ; +} + + + +sub get_prefix { + my($imap, $prefix_in, $prefix_opt) = @_; + my($prefix_out); + + $debug and print "Getting prefix namespace\n"; + if (defined($prefix_in)) { + print "Using [$prefix_in] given by $prefix_opt\n"; + $prefix_out = $prefix_in; + return($prefix_out); + } + $debug and print "Calling namespace capability\n"; + if ($imap->has_capability("namespace")) { + my $r_namespace = $imap->namespace(); + $prefix_out = $r_namespace->[0][0][0]; + return($prefix_out); + } + else{ + print + "No NAMESPACE capability in imap server ", + $imap->Server(),"\n", + help_to_guess_prefix($imap, $prefix_opt); + exit_clean(1); + } +} + + +sub get_separator { + my($imap, $sep_in, $sep_opt) = @_; + my($sep_out); + + + if ($sep_in) { + print "Using [$sep_in] given by $sep_opt\n"; + $sep_out = $sep_in; + return($sep_out); + } + $debug and print "Calling namespace capability\n"; + if ($imap->has_capability("namespace")) { + $sep_out = $imap->separator(); + return($sep_out) if defined $sep_out; + print + "NAMESPACE request failed for ", + $imap->Server(), ": ", $imap->LastError, "\n"; + exit_clean(1); + } + else{ + print + "No NAMESPACE capability in imap server ", + $imap->Server(),"\n", + help_to_guess_sep($imap, $sep_opt); + exit_clean(1); + } +} + +sub help_to_guess_sep { + my($imap, $sep_opt) = @_; + + my $help = "Give the separator character with the $sep_opt option,\n" + . "the folowing listing of folders may help you to find it:\n" + . folders_list_to_help($imap) + . "Most of the time it is character . or /\n" + . "so try $sep_opt . or $sep_opt /\n"; + + return($help); +} + +sub help_to_guess_prefix { + my($imap, $prefix_opt) = @_; + + my $help = "Give the prefix namespace with the $prefix_opt option,\n" + . "the folowing listing of folders may help you to find it:\n" + . folders_list_to_help($imap) + . "Most of the time it is INBOX. or an empty string\n" + . "so try $prefix_opt INBOX. or $prefix_opt ''\n"; + + return($help); +} + + +sub folders_list_to_help { + my($imap) = @_; + + my @folders = $imap->folders; + my $listing = join('', map { "[$_]\n" } @folders); + return $listing; + +} + +sub separator_invert { + # The separator we hope we'll never encounter: 00000000 + my $o_sep="\000"; + + my($h1_fold, $h1_sep, $h2_sep) = @_; + + my $h2_fold = $h1_fold; + $h2_fold =~ s@\Q$h2_sep@$o_sep@g; + $h2_fold =~ s@\Q$h1_sep@$h2_sep@g; + $h2_fold =~ s@\Q$o_sep@$h1_sep@g; + return($h2_fold); +} + + +sub tests_imap2_folder_name { + +$h1_prefix = $h2_prefix = ''; +$h1_sep = '/'; +$h2_sep = '.'; + +$debug and print +"prefix1: [$h1_prefix] +prefix2: [$h2_prefix] +sep1:[$h1_sep] +sep2:[$h2_sep] +"; + +ok('' eq imap2_folder_name(''), 'imap2_folder_name: empty string'); +ok('blabla' eq imap2_folder_name('blabla'), 'imap2_folder_name: blabla'); +ok('spam.spam' eq imap2_folder_name('spam/spam'), 'imap2_folder_name: spam/spam'); +ok('spam/spam' eq imap2_folder_name('spam.spam'), 'imap2_folder_name: spam.spam'); +ok('spam.spam/spam' eq imap2_folder_name('spam/spam.spam'), 'imap2_folder_name: spam/spam.spam'); +@regextrans2 = ('s,/,X,g'); +ok('' eq imap2_folder_name(''), 'imap2_folder_name: empty string [s,/,X,g]'); +ok('blabla' eq imap2_folder_name('blabla'), 'imap2_folder_name: blabla [s,/,X,g]'); +ok('spam.spam' eq imap2_folder_name('spam/spam'), 'imap2_folder_name: spam/spam [s,/,X,g]'); +ok('spamXspam' eq imap2_folder_name('spam.spam'), 'imap2_folder_name: spam.spam [s,/,X,g]'); +ok('spam.spamXspam' eq imap2_folder_name('spam/spam.spam'), 'imap2_folder_name: spam/spam.spam [s,/,X,g]'); + +@regextrans2 = ('s, ,_,g'); +ok('blabla' eq imap2_folder_name('blabla'), 'imap2_folder_name: blabla [s, ,_,g]'); +ok('bla_bla' eq imap2_folder_name('bla bla'), 'imap2_folder_name: blabla [s, ,_,g]'); + +@regextrans2 = ('s,(.*),\U$1,'); +ok('BLABLA' eq imap2_folder_name('blabla'), 'imap2_folder_name: blabla [s,\U(.*)\E,$1,]'); + + +} + +sub imap2_folder_name { + my ($h2_fold); + my ($x_fold) = @_; + # first we remove the prefix + $x_fold =~ s/^\Q$h1_prefix\E//; + $debug and print "removed host1 prefix: [$x_fold]\n"; + $h2_fold = separator_invert($x_fold,$h1_sep, $h2_sep); + $debug and print "inverted separators: [$h2_fold]\n"; + # Adding the prefix supplied by namespace or the --prefix2 option + $h2_fold = $h2_prefix . $h2_fold + unless(($h2_prefix eq "INBOX" . $h2_sep) and ($h2_fold =~ m/^INBOX$/i)); + $debug and print "added host2 prefix: [$h2_fold]\n"; + + # Transforming the folder name by the --regextrans2 option(s) + foreach my $regextrans2 (@regextrans2) { + my $h2_fold_before = $h2_fold; + eval("\$h2_fold =~ $regextrans2"); + $debug and print "[$h2_fold_before] -> [$h2_fold] using re [$regextrans2]\n"; + die_clean("error: eval regextrans2 '$regextrans2': $@\n") if $@; + } + return($h2_fold); +} + + +sub foldersizes { + + my ($side, $imap, @folders) = @_; + my $tot = 0; + my $tmess = 0; + my $biggest = 0 ; + + print "++++ Calculating sizes\n"; + foreach my $folder (@folders) { + my $stot = 0; + my $smess = 0; + printf("$side folder %-35s", "[$folder]"); + unless($imap->exists($folder)) { + print("does not exist yet\n"); + next; + } + unless ($imap->examine($folder)) { + warn + "$side Folder $folder: Could not examine: ", + $imap->LastError, "\n"; + $nb_errors++; + next; + } + + my $hash_ref = {}; + my @msgs = select_msgs($imap); + $smess = scalar(@msgs); + my $smax = 0 ; + @$hash_ref{@msgs} = (undef); + unless ($smess == 0) { + $imap->fetch_hash_2("RFC822.SIZE",$hash_ref) or die_clean("$@"); + #print map {$hash_ref->{$_}->{"RFC822.SIZE"}, " "} keys %$hash_ref; + map {$stot += $hash_ref->{$_}->{"RFC822.SIZE"}} keys %$hash_ref ; + $smax = max( map {$hash_ref->{$_}->{"RFC822.SIZE"}} keys %$hash_ref ); + $biggest = max( $biggest, $smax ); + } + + printf(" Size: %9s", $stot); + printf(" Messages: %5s", $smess); + printf(" Biggest: %9s\n", $smax); + $tot += $stot; + $tmess += $smess; + } + printf ("Nb messages: %11s\n", $tmess ) ; + printf ("Total size: %11s bytes\n", $tot ) ; + printf ("Biggest message: %11s bytes\n", $biggest ) ; + printf ("Time: %11s secondes\n", timenext( ) ) ; +} + +sub timenext { + my ($timenow, $timerel); + # $timebefore is global, beurk ! + $timenow = time; + $timerel = $timenow - $timebefore; + $timebefore = $timenow; + return($timerel); +} + + +sub tests_flags_regex { + + my $string; + ok('' eq flags_regex(''), "flags_regex, null string ''"); + ok('\Seen NonJunk $Spam' eq flags_regex('\Seen NonJunk $Spam'), 'flags_regex, nothing to do'); + ok('\Seen NonJunk $Spam' eq flags_regex('\Seen NonJunk $Spam'), 'flags_regex,'); + @regexflag = ('s/NonJunk//g'); + ok('\Seen $Spam' eq flags_regex('\Seen NonJunk $Spam'), "flags_regex, remove NonJunk: 's/NonJunk//g'"); + @regexflag = ('s/\$Spam//g'); + ok('\Seen NonJunk ' eq flags_regex('\Seen NonJunk $Spam'), 'flags_regex, remove $Spam: '."'s/\$Spam//g'"); + + @regexflag = ('s/\\\\Seen//g'); + + ok(' NonJunk $Spam' eq flags_regex('\Seen NonJunk $Spam'), 'flags_regex, remove \Seen: '. "'s/\\\\\\\\Seen//g'"); + + @regexflag = ('s/(\s|^)[^\\\\]\w+//g'); + ok('\Seen \Middle \End' eq flags_regex('\Seen NonJunk \Middle $Spam \End'), 'flags_regex, only \word [' . flags_regex('\Seen NonJunk \Middle $Spam \End'.']')); + ok(' \Seen \Middle \End1' eq flags_regex('Begin \Seen NonJunk \Middle $Spam \End1 End'), 'flags_regex, only \word [' . flags_regex('Begin \Seen NonJunk \Middle $Spam \End1 End'.']')); + + @regexflag = ('s/.*?(Keep1|Keep2|Keep3)/$1 /g'); + ok('Keep1 Keep2 ReB' eq flags_regex('ReA Keep1 REM Keep2 ReB'), "Keep only regex"); + #ok('Keep1 Keep2' eq flags_regex('Keep1 Keep2 Remove1'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('REM REM Keep1 Keep2'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('Keep1 REM REM Keep2'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 REM REM Keep2'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('Keep1 Keep2'), "Keep only regex"); + ok('Keep1 ' eq flags_regex('REM Keep1'), "Keep only regex"); + + @regexflag = ('s/(Keep1|Keep2|Keep3) (?!(Keep1|Keep2|Keep3)).*/$1 /g'); + ok('Keep1 Keep2 ' eq flags_regex('Keep1 Keep2 ReB'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('Keep1 Keep2 REM REM REM'), "Keep only regex"); + ok('Keep2 ' eq flags_regex('Keep2 REM REM REM'), "Keep only regex"); + #ok('' eq flags_regex('REM REM'), "Keep only regex"); + + @regexflag = ('s/.*?(Keep1|Keep2|Keep3)/$1 /g', + 's/(Keep1|Keep2|Keep3) (?!(Keep1|Keep2|Keep3)).*/$1 /g'); + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 REM Keep2 REM'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('Keep1 REM Keep2 REM'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 Keep2 REM'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 REM Keep2'), "Keep only regex"); + ok('Keep1 Keep2 Keep3 ' eq flags_regex('REM Keep1 REM Keep2 REM REM Keep3 REM'), "Keep only regex"); + ok('Keep1 ' eq flags_regex('REM REM Keep1 REM REM REM '), "Keep only regex"); + ok('Keep1 Keep3 ' eq flags_regex('RE1 Keep1 RE2 Keep3 RE3 RE4 RE5 '), "Keep only regex"); + + @regexflag = ('s/(.*)/$1 jrdH8u/'); + ok('REM REM REM REM REM jrdH8u' eq flags_regex('REM REM REM REM REM'), "Keep only regex 's/(.*)/\$1 jrdH8u/'"); + @regexflag = ('s/jrdH8u *//'); + ok('REM REM REM REM REM ' eq flags_regex('REM REM REM REM REM jrdH8u'), "Keep only regex s/jrdH8u *//"); + + @regexflag = ( + 's/(.*)/$1 jrdH8u/', + 's/.*?(Keep1|Keep2|Keep3|jrdH8u)/$1 /g', + 's/(Keep1|Keep2|Keep3|jrdH8u) (?!(Keep1|Keep2|Keep3|jrdH8u)).*/$1 /g', + 's/jrdH8u *//' + ); + + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 REM Keep2 REM'), "Keep only regex 'REM Keep1 REM Keep2 REM'"); + ok('Keep1 Keep2 ' eq flags_regex('Keep1 REM Keep2 REM'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 Keep2 REM'), "Keep only regex"); + ok('Keep1 Keep2 ' eq flags_regex('REM Keep1 REM Keep2'), "Keep only regex"); + ok('Keep1 Keep2 Keep3 ' eq flags_regex('REM Keep1 REM Keep2 REM REM Keep3 REM'), "Keep only regex"); + ok('Keep1 ' eq flags_regex('REM REM Keep1 REM REM REM '), "Keep only regex"); + ok('Keep1 Keep3 ' eq flags_regex('RE1 Keep1 RE2 Keep3 RE3 RE4 RE5 '), "Keep only regex"); + ok('' eq flags_regex('REM REM REM REM REM'), "Keep only regex"); + + @regexflag = ( + 's/(.*)/$1 jrdH8u/', + 's/.*?(\\\\Seen|\\\\Answered|\\\\Flagged|\\\\Deleted|\\\\Draft|jrdH8u)/$1 /g', + 's/(\\\\Seen|\\\\Answered|\\\\Flagged|\\\\Deleted|\\\\Draft|jrdH8u) (?!(\\\\Seen|\\\\Answered|\\\\Flagged|\\\\Deleted|\\\\Draft|jrdH8u)).*/$1 /g', + 's/jrdH8u *//' + ); + + ok('\\Deleted \\Answered ' + eq flags_regex('Blabla $Junk \\Deleted machin \\Answered truc'), "Keep only regex: Exchange case"); + ok('' eq flags_regex(''), "Keep only regex: Exchange case, null string"); + ok('' + eq flags_regex('Blabla $Junk machin truc'), "Keep only regex: Exchange case, no accepted flags "); + ok('\\Deleted \\Answered \\Draft \\Flagged ' + eq flags_regex('\\Deleted \\Answered \\Draft \\Flagged '), "Keep only regex: Exchange case"); + + + @regexflag = ( + 's/.*?(?:(\\\\(?:Answered|Flagged|Deleted|Seen|Draft)\s?)|$)/defined($1)?$1:q()/eg' + ); + + ok('\\Deleted \\Answered ' + eq flags_regex('Blabla \$Junk \\Deleted machin \\Answered truc'), + "Keep only regex: Exchange case (Phil)"); + + ok('' eq flags_regex(''), "Keep only regex: Exchange case, null string (Phil)"); + + ok('' + eq flags_regex('Blabla $Junk machin truc'), + "Keep only regex: Exchange case, no accepted flags (Phil)"); + + ok('\\Deleted \\Answered \\Draft \\Flagged ' + eq flags_regex('\\Deleted \\Answered \\Draft \\Flagged '), + "Keep only regex: Exchange case (Phil)"); + + +} + +sub flags_regex { + my ($h1_flags) = @_; + foreach my $regexflag (@regexflag) { + my $h1_flags_orig = $h1_flags; + $debug and print "eval \$h1_flags =~ $regexflag\n"; + eval("\$h1_flags =~ $regexflag"); + die_clean("error: eval regexflag '$regexflag': $@\n") if $@; + $debug and print "regexflag $regexflag [$h1_flags_orig] -> [$h1_flags]\n"; + } + return($h1_flags); +} + +sub acls_sync { + my($h1_fold, $h2_fold) = @_; + if ($syncacls) { + my $h1_hash = $imap1->getacl($h1_fold) + or warn "Could not getacl for $h1_fold: $@\n"; + my $h2_hash = $imap2->getacl($h2_fold) + or warn "Could not getacl for $h2_fold: $@\n"; + my %users = map({ ($_, 1) } (keys(%$h1_hash), keys(%$h2_hash))); + foreach my $user (sort(keys(%users))) { + my $acl = $h1_hash->{$user} || "none"; + print "acl $user: [$acl]\n"; + next if ($h1_hash->{$user} && $h2_hash->{$user} && + $h1_hash->{$user} eq $h2_hash->{$user}); + unless ($dry) { + print "setting acl $h2_fold $user $acl\n"; + $imap2->setacl($h2_fold, $user, $acl) + or warn "Could not set acl: $@\n"; + } + } + } +} + + +sub tests_permanentflags { + + my $string; + ok('' eq permanentflags(' * OK [PERMANENTFLAGS (\* \Draft \Answered)] Limited'), + 'permanentflags \*'); + ok('\Draft \Answered' eq permanentflags(' * OK [PERMANENTFLAGS (\Draft \Answered)] Limited'), + 'permanentflags \Draft \Answered'); + ok('\Draft \Answered' + eq permanentflags('Blabla', + ' * OK [PERMANENTFLAGS (\Draft \Answered)] Limited', + 'Blabla'), + 'permanentflags \Draft \Answered' + ); + ok('' eq permanentflags('Blabla'), 'permanentflags nothing'); +} + +sub permanentflags { + my @lines = @_; + + foreach my $line (@lines) { + if ($line =~ m{\[PERMANENTFLAGS \(([^)]+?)\)\]}) { + #print "%%%$1%%%\n"; + my $permanentflags = $1; + if ($permanentflags =~ m{\\\*}) { + $permanentflags = ''; + } + return($permanentflags); + }; + } +} + +sub tests_flags_filter { + + ok( '\Seen' eq flags_filter('\Seen', '\Draft \Seen \Answered'), 'flags_filter ' ); + ok( '' eq flags_filter('\Seen', '\Draft \Answered'), 'flags_filter ' ); + ok( '\Seen' eq flags_filter('\Seen', '\Seen'), 'flags_filter ' ); + ok( '\Seen' eq flags_filter('\Seen', ' \Seen '), 'flags_filter ' ); + ok( '\Seen \Draft' + eq flags_filter('\Seen \Draft', '\Draft \Seen \Answered'), 'flags_filter ' ); + ok( '\Seen \Draft' + eq flags_filter('\Seen \Draft', ' \Draft \Seen \Answered '), 'flags_filter ' ); + +} + +sub flags_filter { + my($flags, $allowed_flags) = @_; + + my @flags = split(/\s+/, $flags); + my %allowed_flags = map { $_ => 1 } split(' ', $allowed_flags ); + my @flags_out = map { exists $allowed_flags{$_} ? $_ : () } @flags; + + my $flags_out = join(' ', @flags_out); + #print "%%%$flags_out%%%\n"; + return($flags_out); +} + + + +sub select_msgs { + my ($imap) = @_; + my (@msgs,@max,@min,@union,@inter); + + unless (defined($maxage) or defined($minage)) { + #@msgs = $imap->search("ALL"); + @msgs = $imap->messages(); + return(@msgs); + } + if (defined($maxage)) { + @max = $imap->sentsince(time - 86400 * $maxage); + } + if (defined($minage)) { + @min = $imap->sentbefore(time - 86400 * $minage); + } + SWITCH: { + unless(defined($minage)) {@msgs = @max; last SWITCH}; + unless(defined($maxage)) {@msgs = @min; last SWITCH}; + my (%union, %inter); + foreach my $m (@min, @max) {$union{$m}++ && $inter{$m}++} + @inter = keys(%inter); + @union = keys(%union); + # normal case + if ($minage <= $maxage) {@msgs = @inter; last SWITCH}; + # just exclude messages between + if ($minage > $maxage) {@msgs = @union; last SWITCH}; + + } + return(@msgs); +} + + +sub lastuid { + my $imap = shift ; + my $folder = shift ; + my $lastuid_guess = shift ; + my $lastuid ; + + # rfc3501: The only reliable way to identify recent messages is to + # look at message flags to see which have the \Recent flag + # set, or to do a SEARCH RECENT. + # SEARCH RECENT doesn't work this way on courrier. + + my @recent_messages ; + # SEARCH RECENT for each transfer can be expensive with a big folder + # Call commented for now + #@recent_messages = $imap->recent( ) ; + #print "Recent: @recent_messages\n"; + + my $max_recent ; + $max_recent = max( @recent_messages ) ; + + if ( defined( $max_recent ) and ($lastuid_guess <= $max_recent ) ) { + $lastuid = $max_recent ; + }else{ + $lastuid = $lastuid_guess + } + return( $lastuid ) ; +} + +sub copy_message { + # copy + + my ( $h1_msg, $h1_fold, $h2_fold, $h1_fir_ref, $permanentflags2, $cache_dir ) = @_ ; + $debug and print "msg $h1_fold/$h1_msg copying to $h2_fold\n"; + + my $h1_size = $h1_fir_ref->{$h1_msg}->{"RFC822.SIZE"}; + my $h1_flags = $h1_fir_ref->{$h1_msg}->{"FLAGS"}; + my $h1_idate = $h1_fir_ref->{$h1_msg}->{"INTERNALDATE"}; + + my $string; + $string = $imap1->message_string($h1_msg); + unless (defined($string)) { + warn + "- msg $h1_fold/$h1_msg could not be fetched: ", + $imap1->LastError, "\n"; + $nb_errors++; + $total_bytes_error += $h1_size; + return( ) ; + } + + if (@regexmess) { + $string = regexmess($string); + } + + $debug and print + "=" x80, "\n", + "F message content begin next line\n", + $string, + "F message content ended on previous line\n", "=" x 80, "\n"; + my $h1_date = ""; + if ($syncinternaldates) { + $h1_date = $h1_idate; + $debug and print "internal date from host1: [$h1_date]\n"; + $h1_date = good_date($h1_date); + $debug and print "internal date from host1: [$h1_date] (fixed)\n"; + } + + if ($idatefromheader) { + + $h1_date = $imap1->get_header($h1_msg,"Date"); + $debug and print "header date from host1: [$h1_date]\n"; + $h1_date = good_date($h1_date); + $debug and print "header date from host1: [$h1_date] (fixed)\n"; + } + + # RFC 2060: This flag can not be altered by any client + $h1_flags =~ s@\\Recent\s?@@gi; + $h1_flags = flags_regex($h1_flags) if @regexflag; + + $h1_flags = flags_filter($h1_flags, $permanentflags2) if ($permanentflags2); + + my $new_id; + $debug and print "msg $h1_fold/$h1_msg date [$h1_date] flags [$h1_flags] size [$h1_size]\n"; + $h1_date = undef if ($h1_date eq ""); + + unless ($dry) { + $max_msg_size_in_bytes = max($h1_size, $max_msg_size_in_bytes); + $new_id = $imap2->append_string($h2_fold, $string, $h1_flags, $h1_date); + unless($new_id){ + no warnings 'uninitialized'; + warn "- msg $h1_fold/$h1_msg couldn't append (Subject:[". + $imap1->subject($h1_msg)."]) to folder $h2_fold: ", + $imap2->LastError, "\n"; + $nb_errors++; + $total_bytes_error += $h1_size; + return( ) ; + } + else{ + # good + # $new_id is an id if the IMAP server has the + # UIDPLUS capability else just a ref + + + + + + + if ( $new_id !~ m{^\d+$} ) { + $new_id = lastuid( $imap2, $h2_fold, $h2_uidguess ) ; + } + printf( "msg %s/%-10s copied to %s/%-10s\n", $h1_fold, $h1_msg, $h2_fold, $new_id ); + $h2_uidguess++; + $total_bytes_transferred += $h1_size; + $nb_msg_transferred += 1; + $debugcache and print "touch $cache_dir/${h1_msg}_$new_id\n" if ( $usecache ) ; + touch( "$cache_dir/${h1_msg}_$new_id" ) if ( $usecache and $new_id =~ m{^\d+$} ); + if ( $delete ) { + print "msg $h1_fold/$h1_msg deleted on host1\n"; + unless($dry) { + $imap1->delete_message($h1_msg); + $h1_nb_msg_deleted += 1; + $imap1->expunge() if ($expunge); + } + } + } + } + else{ + $nb_msg_skipped_dry_mode += 1; + } + return( ); +} + + +sub cache_map { + my ( $cache_files_ref, $h1_msgs_ref, $h2_msgs_ref ) = @_; + my ( %map1_2, %map2_1, %done2 ) ; + + my $h1_msgs_hash_ref = { } ; + my $h2_msgs_hash_ref = { } ; + + @$h1_msgs_hash_ref{ @$h1_msgs_ref } = ( ) ; + @$h2_msgs_hash_ref{ @$h2_msgs_ref } = ( ) ; + + foreach my $file ( sort @$cache_files_ref ) { + $debugcache and print "C12: $file\n" ; + ( $uid1, $uid2 ) = match_a_cache_file( $file ) ; + + if ( exists( $h1_msgs_hash_ref->{ $uid1 } ) + and exists( $h2_msgs_hash_ref->{ $uid2 } ) ) { + # keep only the greatest uid2 + # 130_2301 and + # 130_231 => keep only 130 -> 2301 + + # keep only the greatest uid1 + # 1601_260 and + # 161_260 => keep only 1601 -> 260 + my $max_uid2 = max( $uid2, $map1_2{ $uid1 } || -1 ) ; + if ( exists( $done2{ $max_uid2 } ) ) { + if ( $done2{ $max_uid2 } < $uid1 ) { + $map1_2{ $uid1 } = $max_uid2 ; + delete( $map1_2{ $done2{ $max_uid2 } } ) ; + $done2{ $max_uid2 } = $uid1 ; + } + }else{ + $map1_2{ $uid1 } = $max_uid2 ; + $done2{ $max_uid2 } = $uid1 ; + } + }; + + } + %map2_1 = reverse( %map1_2 ) ; + return( \%map1_2, \%map2_1) ; +} + +sub tests_cache_map { + #$debugcache = 1 ; + my @cache_files = qw ( + 100_200 + 101_201 + 120_220 + 142_242 + 143_243 + 177_277 + 177_278 + 177_279 + 155_255 + 180_280 + 181_280 + 182_280 + 130_231 + 130_2301 + 161_260 + 1601_260 + ) ; + + my $msgs_1 = [120, 142, 143, 144, 161, 1601, 177, 182, 130 ]; + my $msgs_2 = [ 242, 243, 260, 299, 377, 279, 255, 280, 231, 2301 ]; + + my( $c12, $c21 ) ; + ok( ( $c12, $c21 ) = cache_map( \@cache_files, $msgs_1, $msgs_2 ), 'cache_map: 02' ); + my $a1 = [ sort { $a <=> $b } keys %$c12 ] ; + my $a2 = [ sort { $a <=> $b } keys %$c21 ] ; + ok( 0 == compare_lists( [ 130, 142, 143, 177, 182, 1601 ], $a1 ), 'cache_map: 03' ); + ok( 0 == compare_lists( [ 242, 243, 260, 279, 280, 2301 ], $a2 ), 'cache_map: 04' ); + ok( ! $c12->{161}, 'cache_map: ! 161 -> 260' ); + ok( 260 == $c12->{1601}, 'cache_map: 1601 -> 260' ); + ok( 2301 == $c12->{130}, 'cache_map: 130 -> 2301' ); + #print $c12->{1601}, "\n"; + +} + + +sub get_cache { + $debugcache and print "Entering get_cache\n"; + my ($cache_dir, $h1_msgs_ref, $h2_msgs_ref) = @_; + + -d $cache_dir or return( undef ); # exit if cache directory doesn't exist + $debugcache and print "cache_dir: $cache_dir\n"; + + $cache_dir =~ s{\\}{\\\\}g; + my @cache_files = bsd_glob( "$cache_dir/*" ) ; + #$debugcache and print "cache_files: [@cache_files]\n"; + + my( $cache_1_2_ref, $cache_2_1_ref ) + = cache_map( \@cache_files, $h1_msgs_ref, $h2_msgs_ref ) ; + + clean_cache( \@cache_files, $cache_1_2_ref ) + if ( ! ( defined( $maxsize ) + or defined( $minsize ) + or defined( $maxage ) + or defined( $minage ) ) ); + + #print "\n", map { "c12 $_ -> $cache_1_2_ref->{ $_ }\n" } keys %$cache_1_2_ref ; + #print "\n", map { "c21 $_ -> $cache_2_1_ref->{ $_ }\n" } keys %$cache_2_1_ref ; + + $debugcache and print "Exiting get_cache\n"; + return ( $cache_1_2_ref, $cache_2_1_ref ) ; +} + +sub tests_get_cache { + + ok( ! get_cache('/cache_no_exist'), 'get_cache: /cache_no_exist' ); + ok( ( ! -d 'tmp/cache/F1/F2' or rmtree( 'tmp/cache/F1/F2' )), 'get_cache: rmtree tmp/cache/F1/F2' ) ; + ok( mkpath( 'tmp/cache/F1/F2' ), 'get_cache: mkpath tmp/cache/F1/F2' ) ; + + my @test_files_cache = ( qw( + tmp/cache/F1/F2/100_200 + tmp/cache/F1/F2/101_201 + tmp/cache/F1/F2/120_220 + tmp/cache/F1/F2/142_242 + tmp/cache/F1/F2/143_243 + tmp/cache/F1/F2/177_277 + tmp/cache/F1/F2/177_377 + tmp/cache/F1/F2/177_777 + tmp/cache/F1/F2/155_255 + ) ) ; + ok( touch(@test_files_cache), 'get_cache: touch tmp/cache/F1/F2/...' ) ; + + + # on cache: 100_200 101_201 142_242 143_243 177_277 177_377 177_777 155_255 + # on live: + my $msgs_1 = [120, 142, 143, 144, 177 ]; + my $msgs_2 = [ 242, 243, 299, 377, 777, 255 ]; + + my( $c12, $c21 ) ; + ok( ( $c12, $c21 ) = get_cache('tmp/cache/F1/F2', $msgs_1, $msgs_2), 'get_cache: 02' ); + my $a1 = [ sort { $a <=> $b } keys %$c12 ] ; + my $a2 = [ sort { $a <=> $b } keys %$c21 ] ; + ok( 0 == compare_lists( [ 142, 143, 177 ], $a1 ), 'get_cache: 03' ); + ok( 0 == compare_lists( [ 242, 243, 777 ], $a2 ), 'get_cache: 04' ); + ok( -f 'tmp/cache/F1/F2/142_242', 'get_cache: file kept 142_242'); + ok( -f 'tmp/cache/F1/F2/142_242', 'get_cache: file kept 143_243'); + ok( ! -f 'tmp/cache/F1/F2/100_200', 'get_cache: file removed 100_200'); + ok( ! -f 'tmp/cache/F1/F2/101_201', 'get_cache: file removed 101_201'); + + # test clean_cache not executed + $maxage = 2 ; + ok( touch(@test_files_cache), 'get_cache: touch tmp/cache/F1/F2/...' ) ; + ok( ( $c12, $c21 ) = get_cache('tmp/cache/F1/F2', $msgs_1, $msgs_2), 'get_cache: 02' ); + ok( -f 'tmp/cache/F1/F2/142_242', 'get_cache: file kept 142_242'); + ok( -f 'tmp/cache/F1/F2/142_242', 'get_cache: file kept 143_243'); + ok( -f 'tmp/cache/F1/F2/100_200', 'get_cache: file NOT removed 100_200'); + ok( -f 'tmp/cache/F1/F2/101_201', 'get_cache: file NOT removed 101_201'); + + + # strange files + #$debugcache = 1 ; + $maxage = undef ; + ok( ( ! -d 'tmp/cache/rr\uee' or rmtree( 'tmp/cache/rr\uee' )), 'get_cache: rmtree tmp/cache/rr\uee' ) ; + ok( mkpath( 'tmp/cache/rr\uee' ), 'get_cache: mkpath tmp/cache/rr\uee' ) ; + + @test_files_cache = ( qw( + tmp/cache/rr\uee/100_200 + tmp/cache/rr\uee/101_201 + tmp/cache/rr\uee/120_220 + tmp/cache/rr\uee/142_242 + tmp/cache/rr\uee/143_243 + tmp/cache/rr\uee/177_277 + tmp/cache/rr\uee/177_377 + tmp/cache/rr\uee/177_777 + tmp/cache/rr\uee/155_255 + ) ) ; + ok( touch(@test_files_cache), 'get_cache: touch strange tmp/cache/...' ) ; + + # on cache: 100_200 101_201 142_242 143_243 177_277 177_377 177_777 155_255 + # on live: + $msgs_1 = [120, 142, 143, 144, 177 ]; + $msgs_2 = [ 242, 243, 299, 377, 777, 255 ]; + + ok( ( $c12, $c21 ) = get_cache('tmp/cache/rr\uee', $msgs_1, $msgs_2), 'get_cache: strange path 02' ); + $a1 = [ sort { $a <=> $b } keys %$c12 ] ; + $a2 = [ sort { $a <=> $b } keys %$c21 ] ; + ok( 0 == compare_lists( [ 142, 143, 177 ], $a1 ), 'get_cache: strange path 03' ); + ok( 0 == compare_lists( [ 242, 243, 777 ], $a2 ), 'get_cache: strange path 04' ); + ok( -f 'tmp/cache/rr\uee/142_242', 'get_cache: strange path file kept 142_242'); + ok( -f 'tmp/cache/rr\uee/142_242', 'get_cache: strange path file kept 143_243'); + ok( ! -f 'tmp/cache/rr\uee/100_200', 'get_cache: strange path file removed 100_200'); + ok( ! -f 'tmp/cache/rr\uee/101_201', 'get_cache: strange path file removed 101_201'); + + +} + +sub match_a_cache_file { + my $file = shift ; + my ( $uid1, $uid2 ) ; + + return( ( undef, undef ) ) if ( ! $file ) ; + if ( $file =~ m{(?:^|/)(\d+)_(\d+)$} ) { + $uid1 = $1 ; + $uid2 = $2 ; + } + return( $uid1, $uid2 ) ; +} + +sub tests_match_a_cache_file { + my ( $uid1, $uid2 ) ; + ok( ( $uid1, $uid2 ) = match_a_cache_file( ), 'match_a_cache_file: no arg' ) ; + ok( ! defined( $uid1 ), 'match_a_cache_file: no arg 1' ) ; + ok( ! defined( $uid2 ), 'match_a_cache_file: no arg 2' ) ; + + ok( ( $uid1, $uid2 ) = match_a_cache_file( '' ), 'match_a_cache_file: empty arg' ) ; + ok( ! defined( $uid1 ), 'match_a_cache_file: empty arg 1' ) ; + ok( ! defined( $uid2 ), 'match_a_cache_file: empty arg 2' ) ; + + ok( ( $uid1, $uid2 ) = match_a_cache_file( '000_000' ), 'match_a_cache_file: 000_000' ) ; + ok( '000' eq $uid1, 'match_a_cache_file: 000_000 1' ) ; + ok( '000' eq $uid2, 'match_a_cache_file: 000_000 2' ) ; + + ok( ( $uid1, $uid2 ) = match_a_cache_file( '123_456' ), 'match_a_cache_file: 123_456' ) ; + ok( '123' eq $uid1, 'match_a_cache_file: 123_456 1' ) ; + ok( '456' eq $uid2, 'match_a_cache_file: 123_456 2' ) ; + + ok( ( $uid1, $uid2 ) = match_a_cache_file( '/tmp/truc/123_456' ), 'match_a_cache_file: /tmp/truc/123_456' ) ; + ok( '123' eq $uid1, 'match_a_cache_file: /tmp/truc/123_456 1' ) ; + ok( '456' eq $uid2, 'match_a_cache_file: /tmp/truc/123_456 2' ) ; + + ok( ( $uid1, $uid2 ) = match_a_cache_file( '/lala123_456' ), 'match_a_cache_file: NO /lala123_456' ) ; + ok( ! $uid1, 'match_a_cache_file: /lala123_456 1' ) ; + ok( ! $uid2, 'match_a_cache_file: /lala123_456 2' ) ; + + ok( ( $uid1, $uid2 ) = match_a_cache_file( 'la123_456' ), 'match_a_cache_file: NO la123_456' ) ; + ok( ! $uid1, 'match_a_cache_file: la123_456 1' ) ; + ok( ! $uid2, 'match_a_cache_file: la123_456 2' ) ; + + +} + +sub clean_cache { + my $cache_files_ref = shift ; + my $cache_1_2_ref = shift ; + + $debugcache and print "Entering clean_cache\n"; + + $debugcache and print map { "$_ -> " . $cache_1_2_ref->{ $_ } . "\n" } keys %$cache_1_2_ref ; + foreach my $file ( @$cache_files_ref ) { + $debugcache and print "$file\n" ; + my ( $uid1, $uid2 ) = match_a_cache_file( $file ) ; + $debugcache and print "u1: $uid1 u2: $uid2 c12: ", $cache_1_2_ref->{ $uid1 } || '', "\n" ; + if ( ( ! defined( $uid1 ) ) + or ( ! defined( $uid2 ) ) + or ( ! exists( $cache_1_2_ref->{ $uid1 } ) ) + or ( ! ( $uid2 == $cache_1_2_ref->{ $uid1 } ) ) ) { + $debugcache and print "remove $file\n" ; + unlink( $file ) or warn "$!" ; + } + } + + $debugcache and print "Exiting clean_cache\n"; + return( 1 ) ; +} + +sub tests_clean_cache { + + ok( ( ! -d 'tmp/cache/G1/G2' or rmtree( 'tmp/cache/G1/G2' )), 'clean_cache: rmtree tmp/cache/G1/G2' ) ; + ok( mkpath( 'tmp/cache/G1/G2' ), 'clean_cache: mkpath tmp/cache/G1/G2' ) ; + + my @test_files_cache = ( qw( + tmp/cache/G1/G2/100_200 + tmp/cache/G1/G2/101_201 + tmp/cache/G1/G2/120_220 + tmp/cache/G1/G2/142_242 + tmp/cache/G1/G2/143_243 + tmp/cache/G1/G2/177_277 + tmp/cache/G1/G2/177_377 + tmp/cache/G1/G2/177_777 + tmp/cache/G1/G2/155_255 + ) ) ; + ok( touch(@test_files_cache), 'clean_cache: touch tmp/cache/G1/G2/...' ) ; + + ok( -f 'tmp/cache/G1/G2/100_200', 'clean_cache: 100_200 before' ); + ok( -f 'tmp/cache/G1/G2/142_242', 'clean_cache: 142_242 before' ); + ok( -f 'tmp/cache/G1/G2/177_277', 'clean_cache: 177_277 before' ); + ok( -f 'tmp/cache/G1/G2/177_377', 'clean_cache: 177_377 before' ); + ok( -f 'tmp/cache/G1/G2/177_777', 'clean_cache: 177_777 before' ); + ok( -f 'tmp/cache/G1/G2/155_255', 'clean_cache: 155_255 before' ); + + my $cache = { + 142 => 242, + 177 => 777, + } ; + + ok( clean_cache( \@test_files_cache, $cache ), 'clean_cache: ' ) ; + + ok( ! -f 'tmp/cache/G1/G2/100_200', 'clean_cache: 100_200 after' ); + ok( -f 'tmp/cache/G1/G2/142_242', 'clean_cache: 142_242 after' ); + ok( ! -f 'tmp/cache/G1/G2/177_277', 'clean_cache: 177_277 after' ); + ok( ! -f 'tmp/cache/G1/G2/177_377', 'clean_cache: 177_377 after' ); + ok( -f 'tmp/cache/G1/G2/177_777', 'clean_cache: 177_777 after' ); + ok( ! -f 'tmp/cache/G1/G2/155_255', 'clean_cache: 155_255 after' ); +} + + +sub tests_touch { + + ok( (-d 'tmp/tests/' or mkpath( 'tmp/tests/' )), 'tests_touch: mkpath tmp/tests/' ) ; + ok( 1 == touch( 'tmp/tests/lala'), 'tests_touch: tmp/tests/lala') ; + ok( 1 == touch( 'tmp/tests/\y'), 'tests_touch: tmp/tests/\y') ; + ok( 0 == touch( '/aaa'), 'tests_touch: not /aaa') ; + ok( 2 == touch( 'tmp/tests/lili', 'tmp/tests/lolo'), 'tests_touch: 2 files') ; + ok( 1 == touch( 'tmp/tests/\y', '/aaa'), 'tests_touch: 2 files, 1 fails' ) ; + +} + +sub touch { + my @files = @_ ; + my @result; + + foreach my $file ( @files ) { + my $fh = new IO::File ; + if ($fh->open(">> $file")) { + $fh->close ; + push(@result, $file) ; + } + } + return(@result); +} + +sub cache_folder { + my( $cache_dir, $h1_fold, $h2_fold ) = @_ ; + + #print "sep1 $h1_sep sep2 $h2_sep\n"; + my $sep1 = $h1_sep || '/'; + my $sep2 = $h2_sep || '/'; + + my $h1_fold_slash = convert_sep_to_slash( $h1_fold, $sep1 ); + my $h2_fold_slash = convert_sep_to_slash( $h2_fold, $sep2 ); + + return( "$cache_dir/$h1_fold_slash/$h2_fold_slash" ) ; +} + +sub convert_sep_to_slash { + my ($folder, $sep) = @_; + + $folder =~ s{\Q$sep\E}{/}g; + return($folder); +} + +sub tests_convert_sep_to_slash { + + ok('' eq convert_sep_to_slash('', '/'), 'convert_sep_to_slash: no folder'); + ok('INBOX' eq convert_sep_to_slash('INBOX', '/'), 'convert_sep_to_slash: INBOX'); + ok('INBOX/foo' eq convert_sep_to_slash('INBOX/foo', '/'), 'convert_sep_to_slash: INBOX/foo'); + ok('INBOX/foo' eq convert_sep_to_slash('INBOX_foo', '_'), 'convert_sep_to_slash: INBOX_foo'); + ok('INBOX/foo/zob' eq convert_sep_to_slash('INBOX_foo_zob', '_'), 'convert_sep_to_slash: INBOX_foo_zob'); + ok('INBOX/foo' eq convert_sep_to_slash('INBOX.foo', '.'), 'convert_sep_to_slash: INBOX.foo'); + ok('INBOX/foo/hi' eq convert_sep_to_slash('INBOX.foo.hi', '.'), 'convert_sep_to_slash: INBOX.foo.hi'); +} + + +sub tests_regexmess { + + ok("blabla" eq regexmess("blabla"), "regexmess, no regexmess, nothing to do"); + + @regexmess = ('s/p/Z/g'); + ok("ZoZoZo" eq regexmess("popopo"), "regexmess, s/p/Z/g"); + + @regexmess = 's{c}{C}gxms'; + ok("H1: abC\nH2: Cde\n\nBody abC" + eq regexmess("H1: abc\nH2: cde\n\nBody abc"), + "regexmess, c->C"); + + @regexmess = 's{\AFrom\ }{From:}gxms'; + ok( '' + eq regexmess(''), + 'From mbox 1 add colon blank'); + + ok( 'From:' + eq regexmess('From '), + 'From mbox 2 add colo'); + + ok( "\n" . 'From ' + eq regexmess("\n" . 'From '), + 'From mbox 3 add colo'); + + ok( "From: zzz\n" . 'From ' + eq regexmess("From zzz\n" . 'From '), + 'From mbox 4 add colo'); + + @regexmess = 's{\AFrom\ [^\n]*(\n)?}{}gxms'; + ok( '' + eq regexmess(''), + 'From mbox 1 remove, blank'); + + ok( '' + eq regexmess('From '), + 'From mbox 2 remove'); + + ok( "\n" . 'From ' + eq regexmess("\n" . 'From '), + 'From mbox 3 remove'); + + #print "[", regexmess("From zzz\n" . 'From '), "]"; + ok( "" . 'From ' + eq regexmess("From zzz\n" . 'From '), + 'From mbox 4 remove'); + + + ok( +'Date: Sat, 10 Jul 2010 05:34:45 -0700 +From: + +Hello, +Bye.' + eq regexmess( +'From zzz +Date: Sat, 10 Jul 2010 05:34:45 -0700 +From: + +Hello, +Bye.' + ), + 'From mbox 5 remove'); +} + +sub regexmess { + my ($string) = @_; + foreach my $regexmess (@regexmess) { + $debug and print "eval \$string =~ $regexmess\n"; + eval("\$string =~ $regexmess"); + die_clean("error: eval regexmess '$regexmess': $@\n") if $@; + } + return($string); +} + +sub stats { + $timeend = time(); + $timediff = $timeend - $timestart; + + my $memory_consumption = memory_consumption(); + my $memory_ratio = ($max_msg_size_in_bytes) ? + sprintf('%.1f', $memory_consumption / $max_msg_size_in_bytes) : "NA"; + + my $host1_reconnect_count = $imap1->Reconnect_counter() || 0; + my $host2_reconnect_count = $imap2->Reconnect_counter() || 0; + + print "++++ Statistics\n"; + print "Transfer time : $timediff sec\n"; + print "Messages transferred : $nb_msg_transferred "; + print "(could be $nb_msg_skipped_dry_mode without dry mode)" if ($dry); + print "\n"; + print "Messages skipped : $nb_msg_skipped\n"; + print "Messages found duplicate on host1 : $h1_nb_msg_duplicate\n"; + print "Messages found duplicate on host2 : $h2_nb_msg_duplicate\n"; + print "Messages void (noheader) on host1 : $h1_nb_msg_noheader\n"; + print "Messages void (noheader) on host2 : $h2_nb_msg_noheader\n"; + print "Messages deleted on host1 : $h1_nb_msg_deleted\n"; + print "Messages deleted on host2 : $h2_nb_msg_deleted\n"; + print "Total bytes transferred : $total_bytes_transferred\n"; + print "Total bytes duplicate host1 : $h1_total_bytes_duplicate\n"; + print "Total bytes duplicate host2 : $h2_total_bytes_duplicate\n"; + print "Total bytes skipped : $total_bytes_skipped\n"; + print "Total bytes error : $total_bytes_error\n"; + $timediff ||= 1; # No division per 0 + printf ("Message rate : %.1f messages/s\n", $nb_msg_transferred / $timediff); + printf ("Average bandwidth rate : %.1f KiB/s\n", $total_bytes_transferred / 1024 / $timediff); + print "Reconnections to host1 : $host1_reconnect_count\n"; + print "Reconnections to host2 : $host2_reconnect_count\n"; + printf ("Memory consumption : %.1f MB\n", $memory_consumption / 1024 / 1024); + print "Biggest message : $max_msg_size_in_bytes bytes\n"; + print "Memory/biggest message ratio : $memory_ratio\n"; + print "Detected $nb_errors errors\n\n"; + + print $warn_release, "\n"; + print thank_author(); +} + +sub thank_author { + + return("Homepage: http://www.linux-france.org/prj/imapsync/\n"); + + my $basename = imapsync_basename(); + $debug and print "[$basename]\n"; + return("Homepage: http://www.linux-france.org/prj/imapsync/\n") + if ( $basename =~ /\.exe$|\.bin$/ ); + + return(join("", "Happy with this free, open and gratis DWTFPL software?\n", + "Encourage the author (Gilles LAMIRAL) by giving him a book\n", + "or just money via paypal:\n", + "http://www.linux-france.org/prj/imapsync/\n")); +} + +sub get_options { + my $numopt = scalar(@ARGV); + my $argv = join("¤", @ARGV); + + $test_builder = Test::More->builder; + $test_builder->no_ending(1); + + if($argv =~ m/-delete¤2/) { + print "May be you mean --delete2 instead of --delete 2\n"; + exit 1; + } + my $opt_ret = GetOptions( + "debug!" => \$debug, + "debugimap!" => \$debugimap, + "debugimap1!" => \$debugimap1, + "debugimap2!" => \$debugimap2, + "host1=s" => \$host1, + "host2=s" => \$host2, + "port1=i" => \$port1, + "port2=i" => \$port2, + "user1=s" => \$user1, + "user2=s" => \$user2, + "domain1=s" => \$domain1, + "domain2=s" => \$domain2, + "password1=s" => \$password1, + "password2=s" => \$password2, + "passfile1=s" => \$passfile1, + "passfile2=s" => \$passfile2, + "authmd5!" => \$authmd5, + "authmd51!" => \$authmd51, + "authmd52!" => \$authmd52, + "sep1=s" => \$sep1, + "sep2=s" => \$sep2, + "folder=s" => \@folder, + "folderrec=s" => \@folderrec, + "include=s" => \@include, + "exclude=s" => \@exclude, + "prefix1=s" => \$prefix1, + "prefix2=s" => \$prefix2, + "regextrans2=s" => \@regextrans2, + "regexmess=s" => \@regexmess, + "regexflag=s" => \@regexflag, + "delete!" => \$delete, + "delete2!" => \$delete2, + "delete2folders!" => \$delete2folders, + "delete2foldersonly=s" => \$delete2foldersonly, + "delete2foldersbutnot=s" => \$delete2foldersbutnot, + "syncinternaldates!" => \$syncinternaldates, + "idatefromheader!" => \$idatefromheader, + "syncacls!" => \$syncacls, + "maxsize=i" => \$maxsize, + "minsize=i" => \$minsize, + "maxage=i" => \$maxage, + "minage=i" => \$minage, + "foldersizes!" => \$foldersizes, + "dry!" => \$dry, + "expunge!" => \$expunge, + "expunge1!" => \$expunge1, + "expunge2!" => \$expunge2, + "uidexpunge2!" => \$uidexpunge2, + "subscribed!" => \$subscribed, + "subscribe!" => \$subscribe, + "subscribe_all!" => \$subscribe_all, + "justbanner!" => \$justbanner, + "justconnect!"=> \$justconnect, + "justfolders!"=> \$justfolders, + "justfoldersizes!" => \$justfoldersizes, + "fast!" => \$fast, + "version" => \$version, + "help" => \$help, + "timeout=i" => \$timeout, + "skipheader=s" => \$skipheader, + "useheader=s" => \@useheader, + "skipsize!" => \$skipsize, + "allowsizemismatch!" => \$allowsizemismatch, + "fastio1!" => \$fastio1, + "fastio2!" => \$fastio2, + "ssl1!" => \$ssl1, + "ssl2!" => \$ssl2, + "tls1!" => \$tls1, + "tls2!" => \$tls2, + "uid1!" => \$uid1, + "uid2!" => \$uid2, + "authmech1=s" => \$authmech1, + "authmech2=s" => \$authmech2, + "authuser1=s" => \$authuser1, + "authuser2=s" => \$authuser2, + "proxyauth1" => \$proxyauth1, + "proxyauth2" => \$proxyauth1, + "split1=i" => \$split1, + "split2=i" => \$split2, + "buffersize=i" => \$buffersize, + "reconnectretry1=i" => \$reconnectretry1, + "reconnectretry2=i" => \$reconnectretry2, + "tests" => \$tests, + "tests_debug" => \$tests_debug, + "allow3xx!" => \$allow3xx, + "justlogin!" => \$justlogin, + "tmpdir=s" => \$tmpdir, + "pidfile=s" => \$pidfile, + "releasecheck!" => \$releasecheck, + "modules_version!" => \$modules_version, + "usecache!" => \$usecache, + "debugcache!" => \$debugcache, + "useuid!" => \$useuid, + ); + + $debug and print "get options: [$opt_ret]\n"; + + # just the version + print imapsync_version(), "\n" and exit if ($version) ; + + if ($tests) { + $test_builder->no_ending(0); + tests(); + exit; + } + if ($tests_debug) { + $test_builder->no_ending(0); + tests_debug(); + exit; + } + + $help = 1 if ! $numopt; + load_modules(); + + # exit with --help option or no option at all + usage() and exit if ($help or ! $numopt) ; + + # don't go on if options are not all known. + exit(EX_USAGE()) unless ($opt_ret) ; + +} + + +sub load_modules { + + require IO::Socket::SSL if ($ssl1 or $ssl2 or $tls1 or $tls2); + + require Term::ReadKey if ( + ((not($password1 or $passfile1)) + or (not($password2 or $passfile2))) + and (not $help)); + + #require Data::Dumper if ($debug); +} + + + +sub parse_header_msg { + my ($imap, $m_uid, $s_heads, $s_fir, $s, $s_hash) = @_; + + my $head = $s_heads->{$m_uid}; + my $headnum = scalar(keys(%$head)); + $debug and print "Head NUM:", $headnum, "\n"; + unless($headnum) { print "Warning: no header used or found for message $m_uid\n"; } + my $headstr; + + foreach my $h (sort keys(%$head)){ + foreach my $val (sort @{$head->{$h}}) { + # no 8-bit data in headers ! + $val =~ s/[\x80-\xff]/X/g; + + # remove the first blanks (dbmail bug ?) + $val =~ s/^\s*(.+)$/$1/; + + # and uppercase header line + # (dbmail and dovecot) + + my $H = uc("$h: $val"); + # show stuff in debug mode + $debug and print "${s}H $H", "\n"; + + if ($skipheader and $H =~ m/$skipheader/i) { + $debug and print "Skipping header $H\n"; + next; + } + $headstr .= "$H"; + } + } + + if ( ( ! $headstr) and ( $takebody ) ){ + print "no header so taking body first 2Ko\n"; + $imap->fetch($m_uid, "BODY.PEEK[TEXT]<0.2048>"); + $headstr = $imap->_transaction_literals; + + if ( 4048 <= length( $headstr ) ) { + # the imap server might reply the whole message + # this is bad for memory on huge mailboxes + $takebody = 0 ; + $headstr = '' ; + $h1_msgs_copy_by_uid{ $m_uid } = 1 ; + } + } + return() if ( ! $headstr ); + + my $size = $s_fir->{$m_uid}->{"RFC822.SIZE"}; + my $flags = $s_fir->{$m_uid}->{"FLAGS"}; + my $idate = $s_fir->{$m_uid}->{"INTERNALDATE"}; + $size = length($headstr) unless ($size); + my $m_md5 = md5_base64($headstr); + $debug and print "$s msg $m_uid:$m_md5:$size\n"; + my $key; + if ($skipsize) { + $key = "$m_md5"; + } + else { + $key = "$m_md5:$size"; + } + # 0 return code is used to identify duplicate message hash + return 0 if exists $s_hash->{"$key"}; + $s_hash->{"$key"}{'5'} = $m_md5; + $s_hash->{"$key"}{'s'} = $size; + $s_hash->{"$key"}{'D'} = $idate; + $s_hash->{"$key"}{'F'} = $flags; + $s_hash->{"$key"}{'m'} = $m_uid; +} + + +sub firstline { + # extract the first line of a file (without \n) + + my($file) = @_; + my $line = ""; + + open FILE, $file or die_clean("error [$file]: $! "); + chomp($line = ); + close FILE; + $line = ($line) ? $line: "error !EMPTY! [$file]"; + return $line; +} + + +sub file_to_string { + my($file) = @_; + my @string; + open FILE, $file or die_clean("error [$file]: $! "); + @string = ; + close FILE; + return join("", @string); +} + + +sub string_to_file { + my($string, $file) = @_; + sysopen(FILE, $file,O_WRONLY|O_TRUNC|O_CREAT, 0600) or die_clean("$! $file"); + print FILE $string; + close FILE; +} + +sub tests_is_a_release_number { + ok(is_a_release_number(1.351), 'is_a_release_number 1.351'); + ok(is_a_release_number(42.4242), 'is_a_release_number 42.4242'); + ok(is_a_release_number(imapsync_version()), 'is_a_release_number imapsync_version()'); + ok(! is_a_release_number('blabla' ), '! is_a_release_number blabla'); + +} + +sub is_a_release_number { + my $number = shift; + + $number =~ m{\d\.\d+}; +} + +sub check_last_release { + + my $public_release = not_long('imapsync_version_lfo'); + #print "check_last_release: [$public_release]\n" ; + return('unknown') if ($public_release eq 'unknown'); + return('timeout') if ($public_release eq 'timeout'); + return('unknown') if (! is_a_release_number($public_release)); + + my $imapsync_here = imapsync_version(); + + if ($public_release > $imapsync_here) { + return("New imapsync release $public_release available"); + }else{ + return("This current imapsync is up to date"); + } +} + +sub imapsync_version { + my $rcs = '$Id: imapsync,v 1.404 2011/02/21 03:35:39 gilles Exp $ '; + $rcs =~ m/,v (\d+\.\d+)/; + my $VERSION = ($1) ? $1: "UNKNOWN"; + return($VERSION); +} + +sub tests_imapsync_basename { + + ok('imapsync' eq imapsync_basename(), 'imapsync_basename: imapsync'); + ok('blabla' ne imapsync_basename(), '! imapsync_basename: blabla'); +} + +sub imapsync_basename { + + return basename($0); + +} + +sub imapsync_version_lfo { + + my $local_version = imapsync_version(); + my $imapsync_basename = imapsync_basename(); + my $agent_info = "$OSNAME system, perl " + . sprintf("%vd", $PERL_VERSION) + . ", Mail::IMAPClient $Mail::IMAPClient::VERSION" + . " $imapsync_basename"; + my $sock = new IO::Socket::INET ( + PeerAddr => 'imapsync.lamiral.info', + PeerPort => '80', + Proto => 'tcp'); + return('unknown') if not $sock; + print $sock + "GET /prj/imapsync/VERSION HTTP/1.0\n", + "User-Agent: imapsync/$local_version ($agent_info)\n", + "Host: www.linux-france.org\n\n"; + my @line = <$sock>; + close($sock); + my $last_release = $line[-1]; + chomp($last_release); + return($last_release); +} + +sub not_long { + #print "Entering not_long\n"; + my ($func) = @_; + my $val; + + # Doesn't work with gethostbyname (see perlipc) + #local $SIG{ALRM} = sub { die "alarm\n" }; + + if ('MSWin32' eq $OSNAME) { + local $SIG{ALRM} = sub { die "alarm\n" }; + }else{ + + POSIX::sigaction(SIGALRM, + POSIX::SigAction->new(sub { die "alarm" })) + or warn "Error setting SIGALRM handler: $!\n"; + } + + eval { + + alarm(3); + #print $func, "\n"; + { + no strict "refs"; + #print "Calling $func\n"; + $val = &$func(); + #print "End of $func\n"; + } + alarm(0); + }; + if ($@) { + #print "$@"; + if ($@ =~ /alarm/) { + # timed out + return('timeout'); + }else{ + alarm(0); + return('unknown'); # propagate unexpected errors + } + }else { + # didn't + return($val); + } +} + +sub localhost_info { + + my($infos) = join("", + "Here is a [$OSNAME] system (", + join(" ", + uname(), + ), + ")\n", + "With perl ", + sprintf("%vd", $PERL_VERSION), + " Mail::IMAPClient $Mail::IMAPClient::VERSION", + ); + return($infos); + +} + +sub usage { + my $localhost_info = localhost_info(); + my $thank = thank_author(); + my $warn_release =''; + $warn_release = check_last_release() if (not defined($releasecheck)); + print < : "from" imap server. Mandatory. +--port1 : port to connect on host1. Default is 143. +--user1 : user to login on host1. Mandatory. +--domain1 : domain on host1 (NTLM authentication). +--authuser1 : user to auth with on host1 (admin user). + Avoid using --authmech1 SOMETHING with --authuser1. +--proxyauth1 : Use proxyauth on host1. Requires --authuser1. + Required by Sun/iPlanet/Netscape IMAP servers to + be able to use an administrative user +--password1 : password for the user1. Dangerous, use --passfile1 +--passfile1 : password file for the user1. Contains the password. +--host2 : "destination" imap server. Mandatory. +--port2 : port to connect on host2. Default is 143. +--user2 : user to login on host2. Mandatory. +--domain2 : domain on host2 (NTLM authentication). +--authuser2 : user to auth with on host2 (admin user). +--proxyauth2 : Use proxyauth on host2. Requires --authuser2. + Required by Sun/iPlanet/Netscape IMAP servers to + be able to use an administrative user +--password2 : password for the user2. Dangerous, use --passfile2 +--passfile2 : password file for the user2. Contains the password. +--authmd51 : Use MD5 authentification for host1. +--authmd52 : Use MD5 authentification for host2. +--authmech1 : auth mechanism to use with host1: + PLAIN, LOGIN, CRAM-MD5 etc. Use UPPERCASE. +--authmech2 : auth mechanism to use with host2. See --authmech1 +--ssl1 : use an SSL connection on host1. +--ssl2 : use an SSL connection on host2. +--tls1 : use an TLS connection on host1. +--tls2 : use an TLS connection on host2. +--folder : sync this folder. +--folder : and this one, etc. +--folderrec : sync this folder recursively. +--folderrec : and this one, etc. +--include : sync folders matching this regular expression +--include : or this one, etc. + in case both --include --exclude options are + use, include is done before. +--exclude : skips folders matching this regular expression + Several folders to avoid: + --exclude 'fold1|fold2|f3' skips fold1, fold2 and f3. +--exclude : or this one, etc. +--tmpdir : where to store temporary files and subdirectories. + Will be created if it doesn't exist. + Default is system specific and should be ok. +--pidfile : the file where imapsync pid is written. +--prefix1 : remove prefix to all destination folders + (usually INBOX. for cyrus imap servers) + you can use --prefix1 if your source imap server + does not have NAMESPACE capability. +--prefix2 : add prefix to all destination folders + (usually INBOX. for cyrus imap servers) + use --prefix2 if your target imap server does not + have NAMESPACE capability. +--regextrans2 : Apply the whole regex to each destination folders. +--regextrans2 : and this one. etc. + When you play with the --regextrans2 option, first + add also the safe options --dry --justfolders + Then, when happy, remove --dry, remove --justfolders +--regexmess : Apply the whole regex to each message before transfer. + Example: 's/\\000/ /g' # to replace null by space. +--regexmess : and this one. +--regexmess : and this one, etc. +--regexflag : Apply the whole regex to each flags list. + Example: 's/\"Junk"//g' # to remove "Junk" flag. +--regexflag : and this one, etc. +--sep1 : separator in case namespace is not supported. +--sep2 : idem. +--delete : delete messages on host1 server after + a successful transfer. Useful in case you + want to migrate from one server to another one. + With imapsync, --delete tags messages as deleted and they + are really deleted unless --noexpunge is used. +--delete2 : delete messages in host2 that are not in + host1 server. +--delete2folders : delete folders in host2 that are not in + host1 server. For safety, please try it like this (safe): + --delete2folders --dry --justfolders --nofoldersizes +--delete2foldersonly : delete only folders matching regex. +--delete2foldersbutnot : do not delete folders matching regex. +--noexpunge : Do not expunge messages on host1. + Expunge really deletes messages marked deleted. + Expunge is made at the beginning, on host1 only. + Newly transferred messages are also expunged if + option --delete is given. + No expunge is done on host2 account (unless --expunge2) +--expunge1 : expunge messages on host1 after the transfer of messages. +--expunge2 : expunge messages on host2 after the transfer of messages. +--uidexpunge2 : uidexpunge messages on the host2 account + that are not on the host1 account, requires --delete2 +--syncinternaldates : sets the internal dates on host2 same as host1. + Turned on by default. Internal date is the date + a message arrived on a host (mtime). +--idatefromheader : sets the internal dates on host2 same as the + "Date:" headers. +--maxsize : skip messages larger (or equal) than bytes +--minsize : skip messages smaller (or equal) than bytes +--maxage : skip messages older than days. + final stats (skipped) don't count older messages + see also --minage +--minage : skip messages newer than days. + final stats (skipped) don't count newer messages + You can do (+ are the messages selected): + past|----maxage+++++++++++++++>now + past|+++++++++++++++minage---->now + past|----maxage+++++minage---->now (intersection) + past|++++minage-----maxage++++>now (union) +--skipheader : Don't take into account header keyword + matching ex: --skipheader 'X.*' +--useheader : Use this header to compare messages on both sides. + Ex: Message-ID or Subject or Date. +--useheader and this one, etc. +--skipsize : Don't take message size into account to compare + messages on both sides. On by default. + Use --no-skipsize for using size comparaison. +--allowsizemismatch : allow RFC822.SIZE != fetched msg size + consider also --skipsize to avoid duplicate messages + when running syncs more than one time per mailbox +--dry : do nothing, just print what would be done. +--subscribed : transfers subscribed folders. +--subscribe : subscribe to the folders transferred on the + host2 that are subscribed on host1. +--subscribe_all : subscribe to the folders transferred on the + host2 even if they are not subscribed on host1. +--nofoldersizes : Do not calculate the size of each folder in bytes + and message counts. Default is to calculate them. +--justfoldersizes : exit after printed the folder sizes. +--syncacls : synchronises acls (Access Control Lists). +--nosyncacls : does not synchronise acls. This is the default. +--usecache : Use cache to speedup. +--nousecache : Do not use cache. +--useuid : Use uid instead of header as a criterium to sync. + --usecache is then implied unless --nousecache +--debug : debug mode. +--debugimap1 : imap debug mode for host1. imap debug is very verbose. +--debugimap2 : imap debug mode for host2. +--debugimap : imap debug mode for host1 and host2. +--version : print software version. +--noreleasecheck : do not check for new imapsync release (a http request). +--justconnect : just connect to both servers and print useful + information. Need only --host1 and --host2 options. +--justlogin : just login to both host1 and host2 with users + credentials, then exit. +--justfolders : just do things about folders (ignore messages). +--fast : be faster, equivalent to --useuid --nofoldersizes +--reconnectretry1 : reconnect to host1 if connection is lost up to + times per imap command (default is 3) +--reconnectretry2 : same as --reconnectretry1 but for host2 +--split1 : split the requests in several parts on host1. + is the number of messages handled per request. + default is like --split1 1000. +--split2 : same thing on host2. +--timeout : imap connect timeout. +--help : print this help. + +Example: to synchronise imap account "foo" on "imap.truc.org" + to imap account "bar" on "imap.trac.org" + with foo password "secret1" + and bar password "secret2" + +$0 \\ + --host1 imap.truc.org --user1 foo --password1 secret1 \\ + --host2 imap.trac.org --user2 bar --password2 secret2 + +$localhost_info +$rcs +$warn_release + +$thank +EOF +} + + +sub good_date { + # two incoming formats: + # header Tue, 24 Aug 2010 16:00:00 +0200 + # internal 24-Aug-2010 16:00:00 +0200 + + # outgoing format: internal date format + # 24-Aug-2010 16:00:00 +0200 + + my ($d) = @_; + return ('') if not defined($d); + + if ( $d =~ m{(\d?)(\d-...-\d{4})( \d{2}:\d{2}:\d{2})( (?:\+|-)\d{4})?}o ) { + #print "internal: [$1][$2][$3][$4]\n"; + my ($day_1, $date_rest, $hour, $zone) = ($1,$2,$3,$4); + $day_1 = '0' if ($day_1 eq ''); + $zone = '' if not defined($zone); + $d = $day_1 . $date_rest . $hour . $zone; + + + }elsif ($d =~ m{(?:.{3}, )(\d?)(\d) (...) (\d{4})( \d{2}:\d{2}:\d{2})( (?:\+|-)\d{4})?}o ) { + #print "header: [$1][$2][$3][$4][$5][$6]\n"; + my ($day_1, $day_rest, $month, $year, $hour, $zone) = ($1,$2,$3,$4,$5,$6); + $day_1 = '0' if ($day_1 eq ''); + $zone = '' if not defined($zone); + $d = $day_1 . "$day_rest-$month-$year" . $hour . $zone; + + }else{ + # unknown/unmatch => return same string + return($d); + } + + $d = qq("$d"); + return($d); +} + +sub memory_consumption { + # memory consumed by imapsync until now in bytes + return((memory_consumption_of_pids())[0]); +} + +sub memory_consumption_of_pids { + + my @PID = (@_) ? @_ : ($PROCESS_ID); + + #print "PIDs: @PID\n"; + my @val; + if ('MSWin32' eq $OSNAME) { + @val = memory_consumption_of_pids_win32(@PID); + }else{ + # Unix + my @ps = qx{ ps -o vsz @PID }; + shift @ps; # First line is column name "VSZ" + chomp @ps; + # convert to + @val = map { $_ * 1024 } @ps; + return(@val); + } +} + +sub memory_consumption_of_pids_win32 { + # Windows + my @PID = @_; + my %PID; + # hash of pids as key values + map { $PID{$_}++ } @PID; + + # Does not work but should reading the tasklist documentation + #@ps = qx{ tasklist /FI "PID eq @PID" }; + + my @ps = qx{ tasklist /NH /FO CSV }; + #print "-" x 80, "\n", @ps, "-" x 80, "\n"; + my @val; + foreach my $line (@ps) { + my($name, $pid, $mem) = (split(',', $line))[0,1,4]; + next if (! $pid); + #print "[$name][$pid][$mem]"; + if ($PID{remove_qq($pid)}) { + #print "MATCH !\n"; + chomp($mem); + $mem = remove_qq($mem); + $mem = remove_Ko($mem); + $mem = remove_not_num($mem); + #print "[$mem]\n"; + push(@val, $mem * 1024); + } + } + return(@val); +} + +sub remove_not_num { + + my $string = shift; + $string =~ tr/0-9//cd; + #print "tr [$string]\n"; + return($string); +} + +sub tests_remove_not_num { + + ok('123' eq remove_not_num(123), 'remove_not_num( 123 )'); + ok('123' eq remove_not_num('123'), "remove_not_num( '123' )"); + ok('123' eq remove_not_num('12 3'), "remove_not_num( '12 3' )"); + ok('123' eq remove_not_num('a 12 3 Ko'), "remove_not_num( 'a 12 3 Ko' )"); +} + +sub remove_Ko { + my $string = shift; + if ($string =~ /^(.*) Ko$/) { + return($1); + }else{ + return($string); + } +} + +sub remove_qq { + my $string = shift; + if ($string =~ /^"(.*)"$/) { + return($1); + }else{ + return($string); + } +} + +sub memory_consumption_ratio { + + my ($base) = @_; + $base ||= 1; + my $consu = memory_consumption(); + return($consu / $base); +} + +sub tests_memory_consumption { + + ok(print join("\n", memory_consumption_of_pids()), "\n"); + ok(print join("\n", memory_consumption_of_pids('1')), "\n"); + ok(print join("\n", memory_consumption_of_pids('1', $$)), "\n"); + + ok(print memory_consumption_ratio(), "\n"); + ok(print memory_consumption_ratio(1), "\n"); + ok(print memory_consumption_ratio(10), "\n"); + + ok(print memory_consumption(), "\n"); +} + +sub tests_good_date { + + ok('' eq good_date(), 'good_date no arg'); + ok('"24-Aug-2010 16:00:00 +0200"' eq good_date('24-Aug-2010 16:00:00 +0200'), 'good_date internal 2digit zone'); + ok('"24-Aug-2010 16:00:00"' eq good_date('24-Aug-2010 16:00:00'), 'good_date internal 2digit no zone'); + ok('"01-Sep-2010 16:00:00 +0200"' eq good_date( '1-Sep-2010 16:00:00 +0200'), 'good_date internal SP 1digit'); + ok('"24-Aug-2010 16:00:00 +0200"' eq good_date('Tue, 24 Aug 2010 16:00:00 +0200'), 'good_date header 2digit zone'); + ok('"01-Sep-2010 16:00:00"' eq good_date('Wed, 1 Sep 2010 16:00:00'), 'good_date header SP 1digit zone'); + ok('"01-Sep-2010 16:00:00 +0200"' eq good_date('Wed, 1 Sep 2010 16:00:00 +0200'), 'good_date header SP 1digit zone'); + ok('"01-Sep-2010 16:00:00 +0200"' eq good_date('Wed, 1 Sep 2010 16:00:00 +0200 (CEST)'), 'good_date header SP 1digit zone'); + +} + + +sub tests_list_keys_in_2_not_in_1 { + + my @list; + ok( ! list_keys_in_2_not_in_1( {}, {}), 'list_keys_in_2_not_in_1: {} {}'); + ok( 0 == compare_lists( [], [ list_keys_in_2_not_in_1( {}, {} ) ] ), 'list_keys_in_2_not_in_1: {} {}'); + ok( 0 == compare_lists( ['a','b'], [ list_keys_in_2_not_in_1( {}, {'a' => 1, 'b' => 1}) ]), 'list_keys_in_2_not_in_1: {} {a, b}'); + ok( 0 == compare_lists( ['b'], [ list_keys_in_2_not_in_1( {'a' => 1}, {'a' => 1, 'b' => 1}) ]), 'list_keys_in_2_not_in_1: {a} {a, b}'); + ok( 0 == compare_lists( [], [ list_keys_in_2_not_in_1( {'a' => 1, 'b' => 1}, {'a' => 1, 'b' => 1}) ]), 'list_keys_in_2_not_in_1: {a, b} {a, b}'); + ok( 0 == compare_lists( [], [ list_keys_in_2_not_in_1( {'a' => 1, 'b' => 1, 'c' => 1}, {'a' => 1, 'b' => 1}) ]), 'list_keys_in_2_not_in_1: {a, b, c} {a, b}'); + ok( 0 == compare_lists( ['b'], [ list_keys_in_2_not_in_1( {'a' => 1, 'c' => 1}, {'a' => 1, 'b' => 1}) ]), 'list_keys_in_2_not_in_1: {a, b, c} {a, b}'); + +} + +sub list_keys_in_2_not_in_1 { + + my $folders1_ref = shift; + my $folders2_ref = shift; + my @list; + + foreach my $folder ( sort keys %$folders2_ref ) { + next if exists($folders1_ref->{$folder}); + push(@list, $folder); + } + return(@list); +} + + +sub list_folders_in_2_not_in_1 { + + my (@h2_folders_not_in_1, %h2_folders_not_in_1); + @h2_folders_not_in_1 = list_keys_in_2_not_in_1( \%h1_folders_all, \%h2_folders_all); + map { $h2_folders_not_in_1{$_} = 1} @h2_folders_not_in_1; + @h2_folders_not_in_1 = list_keys_in_2_not_in_1( \%h2_folders_from_1, \%h2_folders_not_in_1); + + return( reverse @h2_folders_not_in_1 ); +} + +sub delete_folders_in_2_not_in_1 { + + my $dry_message = ''; + $dry_message = "\t(not really since --dry mode)" if $dry; + foreach my $folder (@h2_folders_not_in_1) { + if ( defined($delete2foldersonly) and eval("\$folder !~ $delete2foldersonly" ) ) { + print "Not deleting $folder because of --delete2foldersonly $delete2foldersonly\n"; + next; + } + if ( defined($delete2foldersbutnot) and eval("\$folder =~ $delete2foldersbutnot" ) ) { + print "Not deleting $folder because of --delete2foldersbutnot $delete2foldersbutnot\n"; + next; + } + my $res = $dry; # always success in dry mode! + $res = $imap2->delete($folder) if ( ! $dry ) ; + if ($res) { + print "Delete $folder", "$dry_message", "\n"; + }else{ + print "Delete $folder failure", "\n"; + } + } +} + +sub tests_debug { + + SKIP: { + skip "No test in normal run" if ( not $tests_debug ); + tests_clean_cache( ) ; + tests_match_a_cache_file( ) ; + tests_touch( ) ; + tests_cache_map( ) ; + tests_get_cache( ) ; + } +} + +sub tests { + + SKIP: { + skip "No test in normal run" if (not $tests); + tests_folder_routines(); + tests_compare_lists(); + tests_regexmess(); + tests_flags_regex(); + tests_permanentflags(); + tests_flags_filter(); + tests_imap2_folder_name(); + tests_command_line_nopassword(); + tests_good_date(); + tests_max(); + tests_remove_not_num(); + tests_memory_consumption(); + tests_is_a_release_number(); + tests_imapsync_basename(); + tests_list_keys_in_2_not_in_1(); + tests_convert_sep_to_slash( ) ; + tests_cache_map( ) ; + tests_get_cache( ) ; + tests_clean_cache( ) ; + tests_match_a_cache_file( ) ; + tests_touch( ) ; + } +} + +# IMAPClient 2.2.9 overrides + +sub override_imapclient { +no warnings 'redefine'; +no strict 'subs'; + +use constant Unconnected => 0; +use constant Connected => 1; # connected; not logged in +use constant Authenticated => 2; # logged in; no mailbox selected +use constant Selected => 3; # mailbox selected +use constant INDEX => 0; # Array index for output line number +use constant TYPE => 1; # Array index for line type + # (either OUTPUT, INPUT, or LITERAL) +use constant DATA => 2; # Array index for output line data +use constant NonFolderArg => 1; # Value to pass to Massage to + # indicate non-folder argument + + +*Mail::IMAPClient::_transaction_literals = sub { + my $self = shift; + my $string = ""; + + foreach my $result (@{$self->{"History"}{$self->Transaction}}) { + $string .= $result->[DATA] + if defined($result) and $self->_is_literal($result) ; + } + return $string; +}; + +# Got from 3.25 +*Mail::IMAPClient::append_string = sub { + my $self = shift; + my $folder = $self->Massage(shift); + my ( $text, $flags, $date ) = @_; + defined $text or $text = ''; + + if ( defined $flags ) { + $flags =~ s/^\s+//g; + $flags =~ s/\s+$//g; + $flags = "($flags)" if $flags !~ /^\(.*\)$/; + } + + if ( defined $date ) { + $date =~ s/^\s+//g; + $date =~ s/\s+$//g; + $date = qq("$date") if $date !~ /^"/; + } + + $text =~ s/\r?\n/$CRLF/og; + + my $command = + "APPEND $folder " + . ( $flags ? "$flags " : "" ) + . ( $date ? "$date " : "" ) . "{" + . length($text) + . "}$CRLF"; + + $command .= $text . $CRLF; + $self->_imap_command( $command ) or return undef; + + my $data = join '', $self->Results; + #print "ZZZ|$data|ZZZ\n"; + # look for something like return size or self if no size found: + # OK [APPENDUID ] APPEND completed + # 18 OK [APPENDUID 1286144680 1539] APPEND Ok. + my $ret = $data =~ m#^\d+ OK \[APPEND.*\s+(\d+)\].*\Z#m ? $1 : $self; + + return $ret; +}; + + + +*Mail::IMAPClient::fetch_hash = sub { + # taken from original lib, + # just added split code. + my $self = shift; + my $hash = ref($_[-1]) ? pop @_ : {}; + my @words = @_; + for (@words) { + s/([\( ])FAST([\) ])/${1}FLAGS INTERNALDATE RFC822\.SIZE$2/i ; + s/([\( ])FULL([\) ])/${1}FLAGS INTERNALDATE RFC822\.SIZE ENVELOPE BODY$2/i ; + } + my $msgs_ref_all = scalar($self->messages); + my $split = $self->Split() || scalar(@$msgs_ref_all); + while(my @msgs = splice(@$msgs_ref_all, 0, $split)) { + #print "SPLIT: @msgs\n"; + my $msgs_ref = \@msgs; + my $output = scalar($self->fetch($msgs_ref,"(" . join(" ",@_) . ")")) + ; # unless grep(/\b(?:FAST|FULL)\b/i,@words); + my $x; + for ($x = 0; $x <= $#$output ; $x++) { + my $entry = {}; + my $l = $output->[$x]; + if ($self->Uid) { + my($uid) = $l =~ /\((?:.* )?UID (\d+).*\)/i; + next unless $uid; + if ( exists $hash->{$uid} ) { + $entry = $hash->{$uid} ; + } + else { + $hash->{$uid} ||= $entry; + } + } + else { + my($mid) = $l =~ /^\* (\d+) FETCH/i; + next unless $mid; + if ( exists $hash->{$mid} ) { + $entry = $hash->{$mid} ; + } + else { + $hash->{$mid} ||= $entry; + } + } + + foreach my $w (@words) { + if ( $l =~ /\Q$w\E\s*$/i ) { + $entry->{$w} = $output->[$x+1]; + $entry->{$w} =~ s/(?:\x0a?\x0d)+$//g; + chomp $entry->{$w}; + } + else { + $l =~ /\( # open paren followed by ... + (?:.*\s)? # ...optional stuff and a space + \Q$w\E\s # escaped fetch field + (?:" # then: a dbl-quote + (\\.| # then bslashed anychar(s) or ... + [^"]+) # ... nonquote char(s) + "| # then closing quote; or ... + \( # ...an open paren + (\\.| # then bslashed anychar or ... + [^\)]*) # ... non-close-paren char + \)| # then closing paren; or ... + (\S+)) # unquoted string + (?:\s.*)? # possibly followed by space-stuff + \) # close paren + /xi; + $entry->{$w}=defined($1)?$1:defined($2)?$2:$3; + } + } + } +} + return wantarray ? %$hash : $hash; +}; + + + +*Mail::IMAPClient::login = sub { + my $self = shift; + return $self->authenticate($self->Authmechanism,$self->Authcallback) + if $self->{Authmechanism}; + + my $id = $self->User; + my $has_quotes = $id =~ /^".*"$/ ? 1 : 0; + my $string = "Login " . ( $has_quotes ? $id : qq("$id") ) . + " " . $self->Password . "\r\n"; + $self->_imap_command($string) + and $self->State(Authenticated); + # $self->folders and $self->separator unless $self->NoAutoList; + unless ( $self->IsAuthenticated) { + my($carp) = $self->LastError; + $carp =~ s/^[\S]+ ([^\x0d\x0a]*)\x0d?\x0a/$1/; + carp $carp unless defined wantarray; + return undef; + }; + return $self; +}; + + +*Mail::IMAPClient::get_header = sub { + my($self , $msg, $header ) = @_; + my $val; + + #eval { $val = $self->parse_headers([$msg],$header)->{$header}[0] }; + my $h = $self->parse_headers([$msg],$header); + #require Data::Dumper; + #print Data::Dumper->Dump([$h]); + #$val = $self->parse_headers([$msg],$header)->{$header}[0]; + + $val = $h->{$msg}{$header}[0]; + return defined($val)? $val : undef; +}; + + +*Mail::IMAPClient::parse_headers = sub { + my($self,$msgspec_all,@fields) = @_; + my(%fieldmap) = map { ( lc($_),$_ ) } @fields; + my $msg; my $string; my $field; + #print ref($msgspec_all), "\n"; + #if(ref($msgspec_all) eq 'HASH') { + # print ref($msgspec_all), "\n"; + #$msgspec_all = [$msgspec_all]; + #} + + unless(ref($msgspec_all) eq 'ARRAY') { + print "parse_headers want an ARRAY ref\n"; + #exit 1; + return undef; + } + + my $headers = {}; # hash from message ids to header hash + my $split = $self->Split() || scalar(@$msgspec_all); + while(my @msgs = splice(@$msgspec_all, 0, $split)) { + $debug and print "SPLIT: @msgs\n"; + my $msgspec = \@msgs; + + # Make $msg a comma separated list, of messages we want + $msg = $self->Range($msgspec); + + if ($fields[0] =~ /^[Aa][Ll]{2}$/ ) { + + $string = "$msg body" . + # use ".peek" if Peek parameter is a) defined and true, + # or b) undefined, but not if it's defined and untrue: + + ( defined($self->Peek) ? + ( $self->Peek ? ".peek" : "" ) : + ".peek" + ) . "[header]" ; + + }else { + $string = "$msg body" . + # use ".peek" if Peek parameter is a) defined and true, or + # b) undefined, but not if it's defined and untrue: + + ( defined($self->Peek) ? + ( $self->Peek ? ".peek" : "" ) : + ".peek" + ) . "[header.fields (" . join(" ",@fields) . ')]' ; + } + + my @raw=$self->fetch( $string ) or return undef; + + + my $h = 0; # reference to hash of current msgid, or 0 between msgs + + for my $header (map { split(/(?:\x0d\x0a)/,$_) } @raw) { + + no warnings; + if ( $header =~ /^\*\s+\d+\s+FETCH\s+\(.*BODY\[HEADER(?:\]|\.FIELDS)/i) { + if ($self->Uid) { + if ( my($msgid) = $header =~ /UID\s+(\d+)/ ) { + $h = {}; + $headers->{$msgid} = $h; + } + else { + $h = {}; + } + } + else { + if ( my($msgid) = $header =~ /^\*\s+(\d+)/ ) { + #start of new message header: + $h = {}; + $headers->{$msgid} = $h; + } + } + } + next if $header =~ /^\s+$/; + + # ( for vi + if ($header =~ /^\)/) { # end of this message + $h = 0; # set to be between messages + next; + } + # check for 'UID)' + # when parsing headers by UID. + if ($self->Uid and my($msgid) = $header =~ /^\s*UID\s+(\d+)\s*\)/) { + $headers->{$msgid} = $h; # store in results against this message + $h = 0; # set to be between messages + next; + } + + if ($h != 0) { # do we expect this to be a header? + my $hdr = $header; + chomp $hdr; + $hdr =~ s/\r$//; + #print "W[$hdr]", ref($hdr), "!\n"; + #next if ( ! defined($hdr)); + #print "X[$hdr]\n"; + + if (defined($hdr) and ($hdr =~ s/^(\S+):\s*//)) { + # if ($hdr =~ s/^(\S+):\s*//) { + #print "X1\n"; + $field = exists $fieldmap{lc($1)} ? $fieldmap{lc($1)} : $1 ; + push @{$h->{$field}} , $hdr ; + } elsif ($hdr =~ s/^.*FETCH\s\(.*BODY\[HEADER\.FIELDS.*\)\]\s(\S+):\s*//) { + #print "X2\n"; + $field = exists $fieldmap{lc($1)} ? $fieldmap{lc($1)} : $1 ; + push @{$h->{$field}} , $hdr ; + } elsif ( ref($h->{$field}) eq 'ARRAY') { + #print "X3\n"; + + $hdr =~ s/^\s+/ /; + $h->{$field}[-1] .= $hdr ; + } + } + } + use warnings; +# my $candump = 0; +# if ($self->Debug) { +# eval { +# require Data::Dumper; +# Data::Dumper->import; +# }; +# $candump++ unless $@; +# } + + } + # if we asked for one message, just return its hash, + # otherwise, return hash of numbers => header hash + # if (ref($msgspec) eq 'ARRAY') { + + return $headers; + +}; + + +*Mail::IMAPClient::authenticate = sub { + + my $self = shift; + my $scheme = shift; + my $response = shift; + + $scheme ||= $self->Authmechanism; + $response ||= $self->Authcallback; + my $clear = $self->Clear; + + $self->Clear($clear) + if $self->Count >= $clear and $clear > 0; + + my $count = $self->Count($self->Count+1); + + + my $string = "$count AUTHENTICATE $scheme"; + + $self->_record($count,[ $self->_next_index($self->Transaction), + "INPUT", "$string\x0d\x0a"] ); + + my $feedback = $self->_send_line("$string"); + + unless ($feedback) { + $self->LastError("Error sending '$string' to IMAP: $!\n"); + return undef; + } + + my ($code, $output); + + until ($code) { + $output = $self->_read_line or return undef; + + foreach my $o (@$output) { + $self->_record($count,$o); # $o is a ref + ($code) = $o->[DATA] =~ /^\+(.*)$/ ; + if ($o->[DATA] =~ /^\*\s+BYE/) { + $self->State(Unconnected); + return undef ; + } + if ($o->[DATA]=~ /^\d+\s+(NO|BAD)/i) { + return undef ; + } + } + } + + if ('CRAM-MD5' eq $scheme && ! $response) { + if ($Mail::IMAPClient::_CRAM_MD5_ERR) { + $self->LastError($Mail::IMAPClient::_CRAM_MD5_ERR); + carp $Mail::IMAPClient::_CRAM_MD5_ERR; + } + else { + $response = \&Mail::IMAPClient::_cram_md5; + } + } + + $feedback = $self->_send_line($response->($code, $self)); + + unless ($feedback) { + $self->LastError("Error sending append msg text to IMAP: $!\n"); + return undef; + } + + $code = ""; # clear code + until ($code) { + $output = $self->_read_line or return undef; + foreach my $o (@$output) { + $self->_record($count,$o); # $o is a ref + if ( ($code) = $o->[DATA] =~ /^\+ (.*)$/ ) { + $feedback = $self->_send_line($response->($code,$self)); + unless ($feedback) { + $self->LastError("Error sending append msg text to IMAP: $!\n"); + return undef; + } + $code = "" ; # Clear code; we're still not finished + } else { + $o->[DATA] =~ /^$count (OK|NO|BAD)/ and $code = $1; + if ($o->[DATA] =~ /^\*\s+BYE/) { + $self->State(Unconnected); + return undef ; + } + } + } + } + + $code =~ /^OK/ and $self->State(Authenticated) ; + return $code =~ /^OK/ ? $self : undef ; + +}; + + + +*Mail::IMAPClient::_cram_md5 = sub { + my ($code, $client) = @_; + my $hmac = Digest::HMAC_MD5::hmac_md5_hex(MIME::Base64::decode($code), + $client->Password()); + return MIME::Base64::encode($client->User() . " $hmac", ""); +}; + +*Mail::IMAPClient::message_string = sub { + my $self = shift; + my $msg = shift; + my $expected_size = $self->size($msg); + return undef unless(defined $expected_size); # unable to get size + my $cmd = $self->has_capability('IMAP4REV1') ? + "BODY" . ( $self->Peek ? '.PEEK[]' : '[]' ) : + "RFC822" . ( $self->Peek ? '.PEEK' : '' ) ; + + #print "Message_string Beg fetch:\n", memory_consumption(); + $self->fetch($msg,$cmd) or return undef; + #print "Message_string End fetch:\n", memory_consumption(); + + my $string = ""; + + + foreach my $result (@{$self->{"History"}{$self->Transaction}}) { + $string .= $result->[DATA] + if defined($result) and $self->_is_literal($result) ; + } + #print "Message_string End string:\n", memory_consumption(); + + # BUG? should probably return undef if length != expected + # No bug, somme servers are buggy. + + if (! $self->Ignoresizeerrors ) { + if ( length($string) != $expected_size ) { + warn "message_string: " . + "expected $expected_size bytes but received " . + length($string) . "\n"; + $self->LastError("message_string: expected ". + "$expected_size bytes but received " . + length($string)."\n"); + } + } + return $string; +}; + + + +{ +no warnings 'once'; + +*Mail::IMAPClient::Ssl = sub { + my $self = shift; + + if (@_) { $self->{SSL} = shift } + return $self->{SSL}; +}; + +*Mail::IMAPClient::exists = sub { + my ( $self, $folder ) = @_; + $self->status($folder) ? $self : undef; +}; + + + +*Mail::IMAPClient::Authuser = sub { + my $self = shift; + + if (@_) { $self->{AUTHUSER} = shift } + return $self->{AUTHUSER}; +}; + + +*Mail::IMAPClient::Ignoresizeerrors = sub { + my $self = shift; + + if (@_) { $self->{IGNORESIZEERRORS} = shift } + return $self->{IGNORESIZEERRORS}; +}; + +*Mail::IMAPClient::Reconnectretry = sub { + my $self = shift; + + if (@_) { $self->{RECONNECTRETRY} = shift } + return $self->{RECONNECTRETRY}; +}; + + +*Mail::IMAPClient::reconnect = sub { + my $self = shift; + + if ( $self->IsAuthenticated ) { + $self->_debug("reconnect called but already authenticated"); + return $self; + } + + my $einfo = $self->LastError || ""; + $self->_debug( "reconnecting to ", $self->Server, ", last error: $einfo" ); + + # reconnect and select appropriate folder + $self->connect or return undef; + + return ( defined $self->Folder ) ? $self->select( $self->Folder ) : $self; +}; + + +# wrapper for _imap_command_do to enable retrying on lost connections +*Mail::IMAPClient::_imap_command = sub { + my $self = shift; + + my $tries = 0; + my $retry = $self->Reconnectretry || 0; + my ( $rc, @err ); + + #print "@_ Beg _imap_command:\n", memory_consumption(); + + # LastError (if set) will be overwritten masking any earlier errors + while ( $tries++ <= $retry ) { + # do command on the first try or if Connected (reconnect ongoing) + if ( $tries == 1 or $self->IsConnected ) { + #print "call @_\n"; + $rc = $self->_imap_command_do(@_); + push( @err, $self->LastError ) if $self->LastError; + #print "call @_ done [", $rc || '', "] [$tries/$retry][" . $self->IsUnconnected . "]\n"; + } + + if ( !defined($rc) + and $retry and $self->IsUnconnected + and ( $self->LastIMAPCommand !~ /LOGOUT/ ) + + ) { + print "\nWarning: disconnected. "; + if ( $self->reconnect ) { + print "Reconnect successful on try #$tries\n"; + $self->Reconnect_counter($self->Reconnect_counter() + 1); + } + else { + print "Reconnect failed on try #$tries\n"; + push( @err, $self->LastError ) if $self->LastError; + } + } + else { + last; + } + } + + unless ($rc) { + my ( %seen, @keep, @info ); + + foreach my $str (@err) { + my ( $sz, $len ) = ( 96, length($str) ); + $str =~ s/$CR?$LF$/\\n/omg; + if ( !$self->Debug and $len > $sz * 2 ) { + my $beg = substr( $str, 0, $sz ); + my $end = substr( $str, -$sz, $sz ); + $str = $beg . "..." . $end; + } + next if $seen{$str}++; + push( @keep, $str ); + } + foreach my $msg (@keep) { + push( @info, $msg . ( $seen{$msg} > 1 ? " ($seen{$msg}x)" : "" ) ); + } + $self->LastError( join( "; ", @info ) ); + } + #print "@_ End _imap_command:\n", memory_consumption(); + return $rc; +}; + + +*Mail::IMAPClient::_imap_command_do = sub { + + my $self = shift; + my $string = shift or return undef; + my $good = shift || 'GOOD'; + + my $qgood = quotemeta($good); + + my $clear = ""; + $clear = $self->Clear; + + $self->Clear($clear) + if $self->Count >= $clear and $clear > 0; + + my $count = $self->Count($self->Count+1); + + $string = "$count $string" ; + + #print "$string\n", memory_consumption(); + $self->_record($count,[ 0, "INPUT", "$string\x0d\x0a"] ); + #print "\n2 $count\n", memory_consumption(); + my $feedback = $self->_send_line("$string"); + + unless ($feedback) { + $self->LastError( "Error sending '$string' to IMAP: $!\n"); + $@ = "Error sending '$string' to IMAP: $!"; + carp "Error sending '$string' to IMAP: $!"; + return undef; + } + + my ($code, $output); + $output = ""; + + READ: until ( $code) { + # escape infinite loop if read_line never returns any data: + $output = $self->_read_line or return undef; + + for my $o (@$output) { + + $self->_record($count,$o); # $o is a ref + # $self->_debug("Received from readline: ${\($o->[DATA])}<>\n"); + next unless $self->_is_output($o); + if ( $good eq '+' ) { + $o->[DATA] =~ /^$count (OK|BAD|NO|$qgood)|^($qgood)/mi ; + $code = $1||$2 ; + } else { + ($code) = $o->[DATA] =~ /^$count (OK|BAD|NO|$qgood)/mi ; + } + if ($o->[DATA] =~ /^\*\s+BYE/im) { + $self->State(Unconnected); + return undef ; + } + } + } + #print "$string: returned $code\n", memory_consumption(); + # $self->_debug("Command $string: returned $code\n"); + return $code =~ /^OK|$qgood/im ? $self : undef ; + +}; + +# capability 2.2.9 is stupid: it caches and return first imap CAPABILITY call +# but call imap CAPABILITY each time. +# Copy/paste from 3.25 +*Mail::IMAPClient::capability = sub { + my $self = shift; + + if ( $self->{CAPABILITY} ) { + my @caps = keys %{ $self->{CAPABILITY} }; + return wantarray ? @caps : \@caps; + } + + $self->_imap_command('CAPABILITY') + or return undef; + + my @caps = map { split } grep s/^\*\s+CAPABILITY\s+//, $self->History; + foreach (@caps) { + $self->{CAPABILITY}{ uc $_ }++; + $self->{ uc $1 } = uc $2 if /(.*?)\=(.*)/; + } + + return wantarray ? @caps : \@caps; +}; + +*Mail::IMAPClient::_read_line = sub { + my $self = shift; + my $sh = $self->Socket; + my $literal_callback = shift; + my $output_callback = shift; + + unless ($self->IsConnected and $self->Socket) { + $self->LastError("NO Not connected.\n"); + carp "Not connected" if $^W; + return undef; + } + + my $iBuffer = ""; + my $oBuffer = []; + my $count = 0; + my $index = $self->_next_index($self->Transaction); + my $rvec = my $ready = my $errors = 0; + my $timeout = $self->Timeout; + + my $readlen = 1; + my $fast_io = $self->Fast_io; # Remember setting to reduce future method calls + + if ( $fast_io ) { + + # set fcntl if necessary: + exists $self->{_fcntl} or $self->Fast_io($fast_io); + $readlen = $self->{Buffer}||4096; + } + until ( + # there's stuff in output buffer: + scalar(@$oBuffer) and + + # the last thing there has cr-lf: + $oBuffer->[-1][DATA] =~ /\x0d\x0a$/ and + + # that thing is an output line: + $oBuffer->[-1][TYPE] eq "OUTPUT" and + + # and the input buffer has been MT'ed: + $iBuffer eq "" + + ) { + #print memory_consumption(); + my $transno = $self->Transaction; # used below in several places + if ($timeout) { + vec($rvec, fileno($self->Socket), 1) = 1; + my @ready = $self->{_select}->can_read($timeout) ; + unless ( @ready ) { + $self->LastError("Tag $transno: " . + "Timeout after $timeout seconds " . + "waiting for data from server\n"); + $self->_record($transno, + [ $self->_next_index($transno), + "ERROR", + "$transno * NO Timeout after ". + "$timeout seconds " . + "during read from " . + "server\x0d\x0a" + ] + ); + $self->LastError( + "Timeout after $timeout seconds " . + "during read from server\x0d\x0a" + ); + return undef; + } + } + + #local($^W) = undef; # Now quiet down warnings + + # read "$readlen" bytes (or less): + # need to check return code from $self->_sysread + # in case other end has shut down!!! + my $ret = $self->_sysread( $sh, \$iBuffer, $readlen, length($iBuffer)) ; + # $self->_debug("Read so far: $iBuffer<>\n"); + redo if(! defined($ret)) ; + if(($timeout and ! defined($ret))) { # Blocking read error... + my $msg = "Error while reading data from server: $!\x0d\x0a"; + $self->LastError('Error while reading data from server'); + $self->State(Unconnected); + print $msg; + $self->_record($transno, + [ $self->_next_index($transno), + "ERROR", "$transno * NO $msg " + ]); + $@ = "$msg"; + + return undef; + } + elsif(defined($ret) and $ret == 0) { # Caught EOF... + my $msg="Socket closed while reading data from server [$!]\x0d\x0a"; + print "$msg"; + $self->LastError('Socket closed while reading data from server'); + $self->State(Unconnected); + $self->_record($transno, + [ $self->_next_index($transno), + "ERROR", "$transno * NO $msg " + ]); + $@ = "$msg"; + return undef; + } + + # successfully wrote to other end, keep going... + $count += $ret; + LINES: while ( $iBuffer =~ s/^(.*?\x0d?\x0a)// ) { + my $current_line = $1; + #print memory_consumption(); + + # $self->_debug("BUFFER: pulled from buffer: ${current_line}\n" . + # "and left with buffer contents of: ${iBuffer}\n"); + + LITERAL: if ($current_line =~ s/\{(\d+)\}\x0d\x0a$//) { + # This part handles IMAP "Literals", + # which according to rfc2060 look something like this: + # [tag]|* BLAH BLAH {nnn}\r\n + # [nnn bytes of literally transmitted stuff] + # [part of line that follows literal data]\r\n + + # Set $len to be length of impending literal: + my $len = $1 ; + + $self->_debug("LITERAL: received literal in line ". + "$current_line of length $len; ". + "attempting to ". + "retrieve from the " . length($iBuffer) . + " bytes in: $iBuffer\n"); + + # Xfer up to $len bytes from front of $iBuffer to $litstring: + my $litstring = substr($iBuffer, 0, $len); + $iBuffer = substr($iBuffer, length($litstring), + length($iBuffer) - length($litstring) ) ; + + # Figure out what's left to read (i.e. what part of + # literal wasn't in buffer): + my $remainder_count = $len - length($litstring); + my $callback_value = ""; + + if ( defined($literal_callback) ) { + if ( $literal_callback =~ /GLOB/) { + print $literal_callback $litstring ; + $litstring = ""; + } elsif ($literal_callback =~ /CODE/ ) { + # Don't do a thing + + } else { + $self->LastError( + ref($literal_callback) . + " is an invalid callback type; " . + "must be a filehandle or coderef\n" + ); + } + + + } + if ($remainder_count > 0 and $timeout) { + # If we're doing timeouts then here we set up select + # and wait for data from the the IMAP socket. + vec($rvec, fileno($self->Socket), 1) = 1; + unless ( CORE::select( $ready = $rvec, + undef, + $errors = $rvec, + $timeout) + ) { + # Select failed; that means bad news. + # Better tell someone. + $self->LastError("Tag " . $transno . + ": Timeout waiting for literal data " . + "from server\n"); + carp "Tag " . $transno . + ": Timeout waiting for literal data " . + "from server\n" + if $self->Debug or $^W; + return undef; + } + } + + fcntl($sh, F_SETFL, $self->{_fcntl}) + if $fast_io and defined($self->{_fcntl}); + while ( $remainder_count > 0 ) { # As long as not done, + $self->_debug("Still need $remainder_count to " . + "complete literal string\n"); + my $ret = $self->_sysread( # bytes read + $sh, # IMAP handle + \$litstring, # place to read into + $remainder_count, # bytes left to read + length($litstring) # offset to read into + ) ; + $self->_debug("Received ret=$ret and buffer = " . + "\n$litstring\nwhile processing LITERAL\n"); + if ( $timeout and !defined($ret)) { # possible timeout + $self->_record($transno, [ + $self->_next_index($transno), + "ERROR", + "$transno * NO Error reading data " . + "from server: $!\n" + ] + ); + return undef; + } elsif ( $ret == 0 and eof($sh) ) { + $self->_record($transno, [ + $self->_next_index($transno), + "ERROR", + "$transno * ". + "BYE Server unexpectedly " . + "closed connection: $!\n" + ] + ); + $self->State(Unconnected); + return undef; + } + # decrement remaining bytes by amt read: + $remainder_count -= $ret; + + if ( length($litstring) > $len ) { + # copy the extra struff into the iBuffer: + $iBuffer = substr( + $litstring, + $len, + length($litstring) - $len + ); + $litstring = substr($litstring, 0, $len) ; + } + + if ( defined($literal_callback) ) { + if ( $literal_callback =~ /GLOB/ ) { + print $literal_callback $litstring; + $litstring = ""; + } + } + + } + $literal_callback->($litstring) + if defined($litstring) and + defined($literal_callback) and $literal_callback =~ /CODE/; + + $self->Fast_io($fast_io) if $fast_io; + + # Now let's make sure there are no IMAP server output lines + # (i.e. [tag|*] BAD|NO|OK Text) embedded in the literal string + # (There shouldn't be but I've seen it done!), but only if + # EnableServerResponseInLiteral is set to true + + my $embedded_output = 0; + my $lastline = ( split(/\x0d?\x0a/,$litstring))[-1] + if $litstring; + + if ( $self->EnableServerResponseInLiteral and + $lastline and + $lastline =~ /^(?:\*|(\d+))\s(BAD|NO|OK)/i + ) { + $litstring =~ s/\Q$lastline\E\x0d?\x0a//; + $embedded_output++; + + $self->_debug("Got server output mixed in " . + "with literal: $lastline\n" + ) if $self->Debug; + + } + # Finally, we need to stuff the literal onto the + # end of the oBuffer: + push @$oBuffer, [ $index++, "OUTPUT" , $current_line], + [ $index++, "LITERAL", $litstring ]; + push @$oBuffer, [ $index++, "OUTPUT", $lastline ] + if $embedded_output; + + } else { + push @$oBuffer, [ $index++, "OUTPUT" , $current_line ]; + } + + } + #$self->_debug("iBuffer is now: $iBuffer<>\n"); + } + # _debug $self, "Buffer is now $buffer\n"; + _debug $self, "Read: " . join("",map {$_->[DATA]} @$oBuffer) ."\n" + if $self->Debug; + return scalar(@$oBuffer) ? $oBuffer : undef ; +}; + + + +} + +# End of sub override_imapclient (yes, very bad indentation) +} + +# IMAPClient 2.2.9 3.xx ads + +package Mail::IMAPClient; + +sub Split { + my $self = shift; + + if (@_) { + $self->{SPLIT} = shift; + $self->{Maxcommandlength} = 10 * $self->{SPLIT}; + } + return $self->{SPLIT}; +} + +sub Tls { + my $self = shift; + + if (@_) { $self->{TLS} = shift } + return $self->{TLS}; +} + +sub Reconnect_counter { + my $self = shift; + $self->{Reconnect_counter} = 0 if ( not defined( $self->{Reconnect_counter} ) ) ; + if (@_) { $self->{Reconnect_counter} = shift } + return $self->{Reconnect_counter}; + +} + + +sub Banner { + my $self = shift; + + if (@_) { $self->{BANNER} = shift } + return $self->{BANNER}; +} + + +sub RawSocket2 { + my ( $self, $sock ) = @_; + defined $sock + or return $self->{Socket}; + + $self->{Socket} = $sock; + $self->{_select} = IO::Select->new($sock); + delete $self->{_fcntl}; + #$self->Fast_io( $self->Fast_io ); + $sock; +} + +sub capability_update { + my $self = shift; + + delete $self->{CAPABILITY}; + $self->capability; +} + +sub fetch_hash_2 { + # taken from above *Mail::IMAPClient::fetch_hash + # if last arg is a ref then the fetch is done only + # on the messages listed as the keys of this hash. + # Init an "empty" $hash_ref by value can be done this way: + # @$hash_ref{2, 3, 4, 55} = (undef); + + my $self = shift; + my $hash_ref = ref($_[-1]) ? pop @_ : {}; + my @words = @_; + for (@words) { + s/([\( ])FAST([\) ])/${1}FLAGS INTERNALDATE RFC822\.SIZE$2/i ; + s/([\( ])FULL([\) ])/${1}FLAGS INTERNALDATE RFC822\.SIZE ENVELOPE BODY$2/i ; + } + + my $msgs_ref_all; + if (scalar %$hash_ref) { + $msgs_ref_all = [ sort { $a <=> $b } keys (%$hash_ref) ]; + #print "ZZZZ 1 [@$msgs_ref_all]\n"; + }else{ + $msgs_ref_all = scalar($self->messages); + #print "ZZZZ 2 [@$msgs_ref_all]\n"; + } + + my $split = $self->Split() || scalar(@$msgs_ref_all); + while(my @msgs = splice(@$msgs_ref_all, 0, $split)) { + #print "SPLIT: @msgs\n"; + my $msgs_ref = \@msgs; + my $output = scalar($self->fetch($msgs_ref,"(" . join(" ",@_) . ")")) + ; # unless grep(/\b(?:FAST|FULL)\b/i,@words); + my $x; + for ($x = 0; $x <= $#$output ; $x++) { + my $entry = {}; + my $l = $output->[$x]; + if ($self->Uid) { + my($uid) = $l =~ /\((?:.* )?UID (\d+).*\)/i; + next unless $uid; + if ( defined $hash_ref->{$uid} ) { + $entry = $hash_ref->{$uid} ; + } + else { + $hash_ref->{$uid} ||= $entry; + } + } + else { + my($mid) = $l =~ /^\* (\d+) FETCH/i; + next unless $mid; + if ( defined $hash_ref->{$mid} ) { + $entry = $hash_ref->{$mid} ; + } + else { + $hash_ref->{$mid} ||= $entry; + } + } + + foreach my $w (@words) { + if ( $l =~ /\Q$w\E\s*$/i ) { + $entry->{$w} = $output->[$x+1]; + $entry->{$w} =~ s/(?:\x0a?\x0d)+$//g; + chomp $entry->{$w}; + } + else { + $l =~ /\( # open paren followed by ... + (?:.*\s)? # ...optional stuff and a space + \Q$w\E\s # escaped fetch field + (?:" # then: a dbl-quote + (\\.| # then bslashed anychar(s) or ... + [^"]+) # ... nonquote char(s) + "| # then closing quote; or ... + \( # ...an open paren + (\\.| # then bslashed anychar or ... + [^\)]*) # ... non-close-paren char + \)| # then closing paren; or ... + (\S+)) # unquoted string + (?:\s.*)? # possibly followed by space-stuff + \) # close paren + /xi; + $entry->{$w}=defined($1)?$1:defined($2)?$2:$3; + } + } + } +} + return wantarray ? %$hash_ref : $hash_ref; +} diff --git a/imapsync.exe b/imapsync.exe index c6ed57f6a751fc245f9ba7eb727bb1ab624f8088..f5b8ec32be71154fb06e2f4c77272b8a1a5e44d7 100755 GIT binary patch delta 235553 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𝔢q7dS+{XpB)@Lp|&!@HfneomYoW` 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𝔴Nu1zK+OO} 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%0Aj+N(aeW5o{^+_t2`8)SSOvcYN@ylw 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%0D)CdnY@Z@Ry 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 diff --git a/index.shtml b/index.shtml index a709048..784dd31 100644 --- a/index.shtml +++ b/index.shtml @@ -2,10 +2,10 @@ -imapsync <!--#exec cmd="cat VERSION" --> +Imapsync: an IMAP migration tool ( release <!--#exec cmd="cat VERSION"--> ) - + @@ -33,6 +33,7 @@ @@ -59,6 +60,27 @@ where the user plays independently on both sides. Use offlineimap

+

Latest release is imapsync + +

+ +

Written on

+ +

See ChangeLog to know what's new in details.

+ +

New features since previous releases 1.404:

+ +
    +
  • Updated imapsync.exe to last Mail-IMAPClient 3.28 (thanks to Phil Pearl Lobbes)
  • +
  • Option --useuid now works also with --delete2 option.
  • +
+ + +

The next imapsync release should see:

+
    +
  • An option to sync to and from files (local backup)
  • +
+

Who is the author?

Gilles LAMIRAL
@@ -72,32 +94,6 @@ where the user plays independently on both sides. Use offlineimap imapsync mailing-list (see below section Mailing-List).

-

Latest release is imapsync - -

- -

Written on

- -

See ChangeLog to know what's new.

- - - -

New features since previous release 1.383:

- -
    -
  • new option --usecache to speedup transfers when using multiple runs.
  • -
  • new option --delete2foldersonly to select which host2 folder hierarchy can be removed if it is away from host1.
  • -
  • new option --delete2foldersbutnot to avoid removing host2 folder hierarchy even if it is away from host1.
  • -
  • Added info about the biggest messages (imapsync uses about 18 times in RAM the size of the biggest transfered message)
  • -
- - -

The next imapsync release should see:

-
    -
  • An option to sync to and from files (local backup)
  • -
- -

Buy imapsync source code

@@ -107,22 +103,28 @@ The Perl imapsync source code will run anywhere a Perl interpreter can

Buy latest imapsync Perl source code for 30 EUR

-30 EUR is about 40 USD, no problem to pay in USD with paypal: +30 EUR is equal to around 45 USD, no problem to pay in USD (or any currency) with paypal:

-imapsync usage +
+ +

-

You will receive a download link in few minutes (contact me if the delay is over a couple of hours).
-30 days money-back guarantee.

+

You will receive a download link just after the payment.
+30 days money-back guarantee!

Standalone imapsync.exe for win32

@@ -130,30 +132,61 @@ The Perl imapsync source code will run anywhere a Perl interpreter can buying the latest win32 standalone imapsync.exe for 30 EUR

-30 EUR is about 40 USD, no problem to pay in USD with paypal: +30 EUR is equal to around 45 USD, no problem to pay in USD (or any currency) with paypal:

+

-imapsync usage +
+ - +

- -

You will receive a download link in few minutes (contact me if the delay is over a couple of hours).
-30 days money-back guarantee.

+

You will receive a download link just after the payment.
+30 days money-back guarantee!

+

Support for imapsync

+ +

For 90 EUR buy imapsync support by the developper who wrote and maintains imapsync. +

+

+90 EUR is equal to around 125 USD, no problem to pay in USD (or any currency) with paypal: +

+ +
+

+ + + + + +

+
+ + +

Then you will be able to expose your issues by email or phone and to converse until your issues are solved. +

+

Documentation

Read the INSTALL file to know how to install imapsync on your system. @@ -231,7 +264,7 @@ If you really want a feature or a fix you can donate money and my next developme will be to code it or fix it.

-

On february 2011: 1 EUR ~ 1.3 USD.

+

On april 2011: 1 EUR ~ 1.48 USD.

@@ -251,6 +284,7 @@ will be to code it or fix it.
DONEFeature Time guessedTime spentMoney receivedMoney needed NoBackup to files 20 hours 60 min 0 $ 800 $ NoEfficient Gmail backup 20 hours 80 min 0 $ 800 $ + NoBetter error reporting 5 hours 0 min 0 $ 200 $ YesAdd cache 10 hours 1310 min 400 $ 400 $ YesSpeedup 50% 10 hours 80 min 10 $ 400 $ Yes--delete2folders 3 hours 270 min 90 $ 0 $ @@ -270,14 +304,13 @@ will be to code it or fix it.

    -
  • DBMail 0.9, 2.0.7 (GPL). But most other DBMail releases work (see below)
  • +
  • DBMail 0.9, 2.0.7 (GPL). But most other DBMail releases are supported (see below)
  • Imail 7.04 (maybe).
  • -
  • MailEnable 1.54 (Proprietary) http://www.mailenable.com/
  • +
  • MailEnable 1.54 (Proprietary) but MailEnable 4.23 is supported.
-

Now the long reported success stories list -([host1] means "source server", -[host2] means "destination server"): +

Now the long reported success stories list (41 different imap server softwares) +([host1] means "source server", [host2] means "destination server"):

    @@ -309,11 +342,14 @@ will be to code it or fix it.
  • Dovecot 0.99.10.4, 0.99.14, 0.99.14-8.fc4, 1.0-0.beta2.7, 1.0.0 [dest/source] (LGPL) (http://www.dovecot.org/)
  • Eudora WorldMail v2
  • +
  • Gimap (Gmail imap) [host1] [host2]
  • GMX IMAP4 StreamProxy.
  • +
  • Goddy IMAP (since Goddy runs Courier)
  • Groupwise IMAP (Novell) 6.x and 7.0. Buggy so see the FAQ.
  • hMailServer 5.3.3 [host2], 4.4.1 [host1], HMAILSERVER 5.3.2-B1769 on windows 2003 [hsot2]
  • iPlanet Messaging server 4.15, 5.1, 5.2
  • -
  • IMail 7.15 (Ipswitch/Win2003), 8.12
  • +
  • IMail 7.15 (Ipswitch/Win2003), 8.12, 11.03 [host1]
  • +
  • MailEnable 4.23 [host1] [host2]
  • MDaemon 7.0.1, 8.0.2, 8.1, 9.5.4 (Windows server 2003 R2 platform)
  • Mercury 4.1 (Windows server 2000 platform)
  • Microsoft Exchange Server 5.5, 6.0.6249.0[host1], 6.0.6487.0[host1], @@ -368,7 +404,7 @@ alt="Viewable With Any Browser" /> This document last modified on -($Id: index.shtml,v 1.55 2011/02/21 02:16:36 gilles Exp gilles $) +($Id: index.shtml,v 1.63 2011/04/19 23:51:09 gilles Exp gilles $)

    diff --git a/memo b/memo index 077a5cf..d261ed7 100644 --- a/memo +++ b/memo @@ -1,6 +1,6 @@ #!/bin/sh -# $Id: memo,v 1.29 2010/12/14 15:14:46 gilles Exp gilles $ +# $Id: memo,v 1.30 2011/03/23 19:14:37 gilles Exp gilles $ software_version() { @@ -13,11 +13,11 @@ statistics_lfo() { #grep prj/imapsync/VERSION /usr/local/apache/logs/access_log | sort -n | cut -d ' ' -f 1,12,13|uniq -c | sort -n # list ip cat < "$f1" + + /g/public_html/imapsync/paypal_reply/paypal_bilan \ + --bnc --debug --debug_csv "$f" \ + > "$f2" + + echo diff "$f1" "$f2" + diff "$f1" "$f2" +done + +for f in /g/paypal/paypal_201?_??_complet.csv; do + fb=`basename "$f"` + f1=/g/var/paypal_bilan/tests/${fb}_tva.out1 + f2=/g/var/paypal_bilan/tests/${fb}_tva.out2 + rm "$f2" + /g/public_html/imapsync/paypal_reply/paypal_bilan_1.22 \ + "$f" \ + > "$f1" + + /g/public_html/imapsync/paypal_reply/paypal_bilan \ + "$f" \ + > "$f2" + + echo diff "$f1" "$f2" + diff "$f1" "$f2" +done + + + +) +} + + + +#echo paypal_bilan_tests_refact_1 +paypal_bilan_tests_refact_1() { +# DID output no diff between paypal_bilan_1.11 and 1.13 +( +#set -x +for f in /g/paypal/paypal_201?_??.csv; do + fb=`basename "$f"` + f1=/g/var/paypal_bilan/tests/$fb.out1 + f2=/g/var/paypal_bilan/tests/$fb.out2 + rm "$f2" + /g/public_html/imapsync/paypal_reply/paypal_bilan_1.11 \ + --bnc --debug "$f" \ + > "$f1" + + /g/public_html/imapsync/paypal_reply/paypal_bilan \ + --bnc --debug "$f" \ + > "$f2" + + echo diff "$f1" "$f2" + diff "$f1" "$f2" +done + +for f in /g/paypal/paypal_201?_??.csv; do + fb=`basename "$f"` + f1=/g/var/paypal_bilan/tests/$fb.out1 + f2=/g/var/paypal_bilan/tests/$fb.out2_usd_eur + rm "$f2" + /g/public_html/imapsync/paypal_reply/paypal_bilan_1.11 \ + --bnc --debug "$f" \ + > "$f1" + + /g/public_html/imapsync/paypal_reply/paypal_bilan \ + --bnc --debug --usdeur 1.2981 "$f" \ + > "$f2" + + echo diff "$f1" "$f2" + diff "$f1" "$f2" +done + +for f in /g/paypal/paypal_201?_??.csv; do + fb=`basename "$f" .csv` + + #echo $fb + + f1i=/g/paypal/$fb.csv + f2i=/g/paypal/${fb}_complet.csv + + f1o=/g/var/paypal_bilan/tests/t03_$fb.out1 + f2o=/g/var/paypal_bilan/tests/t03_$fb.out2 + + #echo $f1i + #echo $f2i + #echo $f1o + #echo $f2o + + rm -f "$f1o" "$f2o" + /g/public_html/imapsync/paypal_reply/paypal_bilan \ + --bnc --debug "$f1i" \ + > "$f1o" + + /g/public_html/imapsync/paypal_reply/paypal_bilan \ + --bnc --debug "$f2i" \ + > "$f2o" + + echo diff "$f1o" "$f2o" + diff "$f1o" "$f2o" +done +) +} + +#echo paypal_bilan_tests_dev +paypal_bilan_tests_dev() { + +/g/public_html/imapsync/paypal_reply/paypal_bilan \ + /g/paypal/paypal_201?_??_complet.csv --invoices '1 50 200' + +# Strange characters +/g/public_html/imapsync/paypal_reply/paypal_bilan \ + /g/paypal/paypal_201?_??_complet.csv --invoices '389 234 96' + +# France +/g/public_html/imapsync/paypal_reply/paypal_bilan \ + /g/paypal/paypal_201?_??_complet.csv --invoices '9 392' + +# individual +/g/public_html/imapsync/paypal_reply/paypal_bilan \ + /g/paypal/paypal_201?_??_complet.csv --invoices '313 415' + +# /g/public_html/imapsync/paypal_reply/paypal_bilan /g/paypal/paypal_2011_03_complet.csv +# pb with latex +# Ok 10 # character +# 65 clientAdrB Keyboard character used is undefined YOSHITO YONEI +# Ok 84 Missing $ inserted. clientEmail victor_su@yahoo.com +# 92 Dr. Westernacher & Partner GmbH + +# /g/public_html/imapsync/paypal_reply/paypal_bilan --first_in 147 --invoices '242' /g/paypal/paypal_2010_1?_complet.csv +} diff --git a/paypal_reply/paypal_bilan b/paypal_reply/paypal_bilan index 059a628..e679737 100755 --- a/paypal_reply/paypal_bilan +++ b/paypal_reply/paypal_bilan @@ -1,70 +1,98 @@ #!/usr/bin/perl +# $Id: paypal_bilan,v 1.23 2011/04/19 14:59:43 gilles Exp gilles $ + use strict; use warnings; +use Getopt::Long; +use Text::CSV_XS ; +use IO::Handle ; +use Data::Dumper ; +use Unicode::MapUTF8 qw(to_utf8 from_utf8 utf8_supported_charset); -my $total_usd_received ; -my $total_usd_invoice ; +die unless (utf8_supported_charset('ISO-8859-1')); -my $total_eur_received ; -my $total_eur_invoice ; -my $nb_invoice ; -my $line ; +my $total_usd_received = 0 ; +my $total_usd_invoice = 0 ; +my $total_HT_EUR_exo = 0 ; +my $total_HT_EUR_ass = 0 ; +my $total_TVA_EUR = 0 ; +my $total_eur_received = 0 ; +my $total_eur_invoice = 0 ; +my $nb_invoice = 0 ; +my $nb_invoice_refund = 0 ; -while( $line = <> ) { - next if ( $line =~ /^Date, Heure, Fuseau horaire, Nom, Type, Etat, Devise, Montant, Numéro d'avis de réception, Solde,/ ) ; - #print( "A1 $line" ) ; - chomp( $line ) ; - #print ("A2 $line\n" ); +my $debug ; +my $debug_csv ; +my $debug_dev ; +my $first_invoice = 1 ; +my $print_details = '' ; +my $bnc = ''; +my $usdeur = 1.2981 ; +my $invoices ; +my %invoice_refund ; +my $write_invoices = 0; + +my $dir_invoices = '/g/var/paypal_invoices' ; + +my $option_ret = GetOptions ( + 'debug' => \$debug, + 'debug_csv' => \$debug_csv, + 'debug_dev' => \$debug_dev, + 'first_invoice=i' => \$first_invoice, + 'print_details|details' => \$print_details, + 'bnc' => \$bnc, + 'usdeur=f' => \$usdeur, + 'invoices=s' => \$invoices, + 'write_invoices!' => \$write_invoices, +); + +my @files = @ARGV ; +my %action_of_invoice ; + +my @invoices = split( /\s+/, $invoices ) if $invoices ; + +#print "@invoices\n" ; + +foreach my $file ( @files ) { + + my @actions = parse_file( $file ) ; - my $line2 = '",' . $line . '"' ; - my( $Nothing, $Date, $Heure, $Fuseau_horaire, $Nom, $Type, $Etat, $Devise, $Montant, $Numero_davis_de_reception, $Solde ) - = split( '","', $line2 ) ; - #print ( "[$Date] [$Heure] [$Fuseau_horaire] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [$Numero_davis_de_reception] [$Solde]\n" ) ; - - - if ( - 'Paiement sur site marchand reçu' eq $Type - and 'USD' eq $Devise - and 'Terminé' eq $Etat - ) { - $Montant =~tr/,/./; - #print "$Montant\n" ; - my $Montant2_usd; - $Montant2_usd = 15 if ( 14.11 == $Montant or 14.19 == $Montant ) ; - $Montant2_usd = 25 if ( 23.72 == $Montant or 23.85 == $Montant ) ; - $Montant2_usd = 35 if ( 33.33 == $Montant or 33.51 == $Montant ) ; - $Montant2_usd = 50 if ( 47.75 == $Montant or 14.19 == $Montant ) ; - $Montant2_usd = 125 if ( 119.82 == $Montant or 119.82 == $Montant ) ; - $Montant2_usd = 135 if ( 129.43 == $Montant or 129.43 == $Montant ) ; - #print "$Montant $Montant2_usd\n" ; - $total_usd_received += $Montant ; - $total_usd_invoice += $Montant2_usd ; - $nb_invoice++ ; - } - if ( - 'Paiement sur site marchand reçu' eq $Type - and 'EUR' eq $Devise - and 'Terminé' eq $Etat - ) { - $Montant =~tr/,/./; - #print "$Montant\n" ; - my $Montant2_eur; - $Montant2_eur = 22 if ( 20.88 == $Montant or 20.99 == $Montant ) ; - $Montant2_eur = 30 if ( 28.58 == $Montant or 28.73 == $Montant ) ; - $Montant2_eur = 110 if ( 105.46 == $Montant ) ; - #print "$Montant $Montant2_eur\n" ; - $total_eur_received += $Montant ; - $total_eur_invoice += $Montant2_eur ; - $nb_invoice++ ; + foreach my $action (@actions) { + my %action = %$action ; + #print $action->{ Nom }, "\n" ; + my( $Date, $Heure, $Fuseau_horaire, $Nom, $Type, $Etat, + $Devise, $Montant, $Numero_davis_de_reception, $Solde, + $Pays, $Nom_Option_1, $Valeur_Option_1, $Hors_taxe ) + = @action{ ( 'Date', 'Heure', 'Fuseau horaire', 'Nom', 'Type', 'Etat', + 'Devise', 'Montant', "Numéro d'avis de réception", 'Solde', + 'Pays', 'Nom Option 1', 'Valeur Option 1', 'Hors taxe') } ; + #print "$Nom\n" ; + my $invoice = 'NONE' ; + $Montant = $action->{ Net } if not defined $Montant; + compute_line($action, $invoice, $Date, $Heure, $Fuseau_horaire, $Nom, $Type, $Etat, + $Devise, $Montant, $Numero_davis_de_reception, $Solde, + $Pays, $Nom_Option_1, $Valeur_Option_1, $Hors_taxe ) ; + + # index by invoice number + $action_of_invoice{ $action->{ 'invoice' } } = $action ; } + delete $action_of_invoice{ 'NONE' } ; } +@invoices = ( $first_invoice .. $first_invoice + $nb_invoice -1 ) if ( ! @invoices ) ; + +foreach my $invoice ( @invoices ) { + build_invoice( $invoice ) ; +} + + + print "USD banque $total_usd_received\n" ; print "USD invoice $total_usd_invoice\n" ; my $total_eur_from_usd ; -$total_eur_from_usd = int( ( $total_usd_invoice / 1.2981 ) + 0.5 ) ; # au 30 nov 2010 http://fr.finance.yahoo.com/devises/convertisseur/#from=EUR;to=USD;amt=1 +$total_eur_from_usd = int( ( $total_usd_invoice / $usdeur ) + 0.5 ) ; # au 30 nov 2010 http://fr.finance.yahoo.com/devises/convertisseur/#from=EUR;to=USD;amt=1 print "EUR from USD $total_eur_from_usd\n" ; #$total_eur = int( ( $total_eur_invoice / 1.3 ) + 0.5 ) ; #print "EUR $total_eur_from_usd\n" ; @@ -72,10 +100,674 @@ print "EUR banque $total_eur_received\n" ; print "EUR invoice $total_eur_invoice\n" ; my $total_eur = $total_eur_from_usd + $total_eur_invoice ; -print "EUR total $total_eur\n" ; -print "Nb invoice $nb_invoice\n" ; + +$total_HT_EUR_exo = sprintf('%2.f', $total_HT_EUR_exo) ; +$total_HT_EUR_ass = sprintf('%2.f', $total_HT_EUR_ass) ; +$total_TVA_EUR = sprintf('%2.f', $total_TVA_EUR) ; + +$total_eur = sprintf('%2.f', $total_eur) ; + +print "EUR total $total_eur\n" ; +print "EUR total HT exo $total_HT_EUR_exo\n" ; +print "EUR total HT assuj $total_HT_EUR_ass\n" ; +print "EUR total TVA $total_TVA_EUR\n" ; +print "Nb invoice $nb_invoice\n" ; +print "Nb invoice refund $nb_invoice_refund\n" ; + +print "$total_eur != $total_HT_EUR_exo + $total_HT_EUR_ass + $total_TVA_EUR\n" +if ( $total_eur != $total_HT_EUR_exo + $total_HT_EUR_ass + $total_TVA_EUR ) ; + +sub parse_one_line_io { + my $csv = shift ; + my $io = shift ; + + my $line = $csv->getline($io) ; + + return if ( $csv->eof( ) ) ; + if ( not defined( $line ) ) { + my($cde, $str, $pos) = $csv->error_diag () ; + print "[$cde] [$str] [$pos]\n" ; + + } + return( $line ) ; +} + +sub hash_and_count_dupplicate { + my @columns = @_ ; + my %columns ; + + #@columns_def{ @columns_def } = ( ) ; + foreach my $col ( @columns ) { + $columns{ $col } += 1 ; + } + $debug_csv and print "Nb columns: ", scalar( keys %columns ), " ", scalar( @columns ), "\n" ; + # debug how many time a title is defined + foreach my $col (1 .. scalar( @columns )) { + $debug_csv and print "$col | ", + deci_to_AA( $col ) , " | ", + $columns{ $columns[ $col - 1 ] }, " | ", + $columns[ $col - 1 ], "\n" ; + } + + # exit in case two columns have the same name + die "Erreur : doublons dans les titres\n" if ( scalar( keys %columns ) != scalar( @columns ) ) ; + + return( %columns ) ; +} + +sub deci_to_AA { + my $deci = shift ; + my $AA = ''; + + while ( $deci > 0 ) { + my $quot = int( ( $deci - 1 ) / 26 ) ; + my $rest = $deci - 1 - ( 26 * $quot ) ; + my $char = chr ( ord('A') + $rest ) ; + $AA = $char . $AA ; + $deci = $quot ; + } + #print "col=$AA\n" ; + return( $AA ) ; +} + +sub remove_first_blank { + my $string = shift ; + + $string =~ s/^ +// ; + return( $string ) ; + +} + +sub parse_file { + my $file = shift ; + + open my $io, "<", $file or die "$file: $!" ; + + my $csv = Text::CSV_XS->new( { + sep_char => ',', + binary => 1, + keep_meta_info => 1, + eol => $/, + } ) ; + + my $line_1 = parse_one_line_io( $csv, $io ) ; + die if ( not defined $line_1 ) ; # first line must have no problem + + my @columns_def_orig = @$line_1 ; + my @columns_def = map { remove_first_blank( $_ ) } @columns_def_orig ; + $debug_csv and print "columns_def = ", map( { "[$_]" } @columns_def ), "\n"; + + my %columns_def = hash_and_count_dupplicate( @columns_def ) ; + my $nb_columns_def = scalar @columns_def ; + + my $line_counter = 2 ; + my @actions ; + while ( 1 ) { + $debug_csv and print "ligne $line_counter ", $csv->eof( ), "\n" ; + my $line = parse_one_line_io( $csv, $io ) ; + last if ( $csv->eof( ) ) ; + if ( not defined $line ) { + print "Erreur ligne $line_counter : ", $csv->error_diag, "\n\n"; + ++$line_counter ; + next ; + } + my @columns = @$line ; + + if ( $nb_columns_def != scalar @columns ) { + print "Erreur ligne $line_counter : nombre de colonnes = ", scalar @columns, " != $nb_columns_def\n" ; + ++$line_counter ; + next ; + } + my %columns ; + @columns{ @columns_def } = @columns ; + $columns{ 'file_csv' } = $file ; + $columns{ 'line_number' } = $line_counter ; + $csv->combine( @columns ) ; + my $line_csv = $csv->string(); + $columns{ 'line_csv' } = $line_csv ; + $debug_csv and print map( { "[$_] = [" . $columns{$_} . "]\n" } + @columns_def, 'line_number', 'line_csv', 'file_csv' ), + "\n"; + ++$line_counter ; + push( @actions, \%columns ) ; + } + close( $io ); + return( reverse @actions ) ; +} + +sub compute_line { + my( $action, $invoice, $Date, $Heure, $Fuseau_horaire, $Nom, $Type, $Etat, + $Devise, $Montant, $Numero_davis_de_reception, $Solde, + $Pays, $Nom_Option_1, $Valeur_Option_1, $Hors_taxe_paypal ) = @_ ; + + $debug and print( "[$Date] [$Heure] [$Fuseau_horaire] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [$Numero_davis_de_reception] [$Solde]\n", + "[$Pays] [$Nom_Option_1] [$Valeur_Option_1]\n" ) ; + #$debug_dev and print "$Hors_taxe_paypal\n" ; + + $Montant =~ s/[^0-9-,.]//g ; + $Montant =~ s/,/./g ; + #$debug and print "MM[$Montant]\n" ; + $Hors_taxe_paypal =~ s/,/./g ; + + my $MontantEUR; + my( $montant_HT_EUR_exo, $montant_HT_EUR_ass, $montant_TVA_EUR ) ; + if ( $bnc ) { + $MontantEUR = $Montant ; + $MontantEUR = sprintf( "%.4f", $Montant/$usdeur ) if ($Devise eq 'USD') ; + print( "\n", "=" x 60, "\n" ) ; + print( "[$Date] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [EUR $MontantEUR]\n", + "[$Pays] [$Nom_Option_1] [$Valeur_Option_1]\n" ) ; + } + + if ( + 'Paiement sur site marchand reçu' eq $Type + and 'USD' eq $Devise + and ( 'Terminé' eq $Etat or 'Compensé' eq $Etat ) + ) { + $Montant =~tr/,/./; + #print "$Montant\n" ; + my $Montant2_usd; + $Montant2_usd = $Hors_taxe_paypal ; + $total_usd_received += $Montant ; + $total_usd_invoice += $Montant2_usd ; + ( $montant_HT_EUR_exo, $montant_HT_EUR_ass, $montant_TVA_EUR ) = tva_line( $Devise, $Montant2_usd, $Pays, $Nom_Option_1, $Valeur_Option_1 ) ; + $total_HT_EUR_exo += $montant_HT_EUR_exo ; + $total_HT_EUR_ass += $montant_HT_EUR_ass ; + $total_TVA_EUR += $montant_TVA_EUR ; + $invoice = $first_invoice + $nb_invoice ; + $nb_invoice++ ; + $print_details and print ( "[$invoice] [$Date] [$Heure] [$Fuseau_horaire] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [$Numero_davis_de_reception] [$Solde]\n" ) ; + + } + if ( + 'Paiement sur site marchand reçu' eq $Type + and 'EUR' eq $Devise + and ( 'Terminé' eq $Etat or 'Compensé' eq $Etat ) + ) { + $Montant =~tr/,/./; + #print "$Montant\n" ; + my $Montant2_eur; + $Montant2_eur = $Hors_taxe_paypal ; + $total_eur_received += $Montant ; + $total_eur_invoice += $Montant2_eur ; + ( $montant_HT_EUR_exo, $montant_HT_EUR_ass, $montant_TVA_EUR ) = tva_line( $Devise, $Montant2_eur, $Pays, $Nom_Option_1, $Valeur_Option_1 ) ; + $total_HT_EUR_exo += $montant_HT_EUR_exo ; + $total_HT_EUR_ass += $montant_HT_EUR_ass ; + $total_TVA_EUR += $montant_TVA_EUR ; + $invoice = $first_invoice + $nb_invoice ; + $nb_invoice++ ; + $print_details and print ( "[$invoice] [$Date] [$Heure] [$Fuseau_horaire] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [$Numero_davis_de_reception] [$Solde]\n" ) ; + } + if ( + 'Paiement sur site marchand reçu' eq $Type + and 'EUR' eq $Devise + and 'Remboursé' eq $Etat + ) { + $invoice = $first_invoice + $nb_invoice ; + $nb_invoice++ ; + $nb_invoice_refund++; + $invoice_refund{ $invoice }++ ; + + $print_details and print ( "[$invoice] [$Date] [$Heure] [$Fuseau_horaire] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [$Numero_davis_de_reception] [$Solde]\n" ) ; + } + if ( + 'Paiement sur site marchand reçu' eq $Type + and 'EUR' eq $Devise + and 'Non compensé' eq $Etat + ) { + $invoice = $first_invoice + $nb_invoice ; + $nb_invoice++ ; + $print_details and print ( "[$invoice] [$Date] [$Heure] [$Fuseau_horaire] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [$Numero_davis_de_reception] [$Solde]\n" ) ; + } + + $action->{ 'invoice' } = $invoice ; + if ( $bnc ) { + my $FR_flag = '' ; + $FR_flag = ' FR' if $Pays eq 'France' ; + my $IND_flag = '' ; + $IND_flag = ' IND' if ('imapsync usage' eq $Nom_Option_1 and 'individual' eq $Valeur_Option_1 ) ; + print "FE $invoice$FR_flag$IND_flag\n" ; + print "Facture $invoice imapsync$FR_flag $Nom\n" ; + printf( "%.2f [EUR %.2f]\n", $Montant, $MontantEUR ) ; + } +} + +sub build_invoice { + my $invoice = shift ; + + return if ! $invoice ; + + my $action = $action_of_invoice{ $invoice } ; + my $refund = '' ; + $refund = 'REFUND ' if $invoice_refund{ $invoice } ; + my %action = %$action if $action ; + #print Data::Dumper->Dump( [$action] ) ; + + my( $Date, $Heure, $Nom, $Type, $Etat, $Devise, $Hors_taxe, $Commission, $Net, + $De_l_adresse_email, $A_l_adresse_email, $N_de_transaction, $Titre_de_l_objet, + $TVA, $Nom_Option_1, $Valeur_Option_1, $N_de_transaction_de_reference, + $Adresse_1, $Adresse_2_district_quartier, $Ville, + $Etat_Province, $Code_postal, $Pays, $line_number, $line_csv, $file_csv ) + = @action{ ( 'Date', 'Heure', 'Nom', 'Type', 'Etat', 'Devise', 'Hors taxe', 'Commission', 'Net', + "De l'adresse email", "A l'adresse email", 'N° de transaction', "Titre de l'objet", + 'TVA', 'Nom Option 1', 'Valeur Option 1', 'Nº de transaction de référence', + 'Adresse 1', 'Adresse 2/district/quartier', 'Ville', + 'Etat/Province/Région/Comté/Territoire/Préfecture/République', 'Code postal', 'Pays', 'line_number', 'line_csv', 'file_csv' ) } ; + + #print "$Hors_taxe $Devise\n" ; + my $Hors_taxe_num = $Hors_taxe ; + $Hors_taxe_num =~ s{,}{.} ; + if ($Hors_taxe_num > 100) { + print "invoice $invoice $Hors_taxe_num > 100\n" ; + #return() ; + } + + my ( $email_message_header, $email_message_body ) + = build_email_message( $Date, $Nom, $De_l_adresse_email, $invoice ) ; + if ( $write_invoices ) { + write_email_message( $dir_invoices, $invoice, + $email_message_header, $email_message_body, + $De_l_adresse_email) ; + write_csv_info( $dir_invoices, $invoice, $file_csv, $line_number, $line_csv ) ; + } + + + + #print "==== $invoice $refund=================================================" ; + #print $email_message ; + + my( + $clientAdrA, + $clientAdrB, + $clientAdrC, + $clientAdrD, + $clientAdrE, + $clientAdrF, + ) + = build_adress( + $Nom, + $Adresse_1, + $Adresse_2_district_quartier, + $Ville, + $Code_postal, + $Etat_Province, + $Pays, + ) ; + + foreach my $str ( + $De_l_adresse_email, + $Nom, + $clientAdrA, + $clientAdrB, + $clientAdrC, + $clientAdrD, + $clientAdrE, + $clientAdrF, + ) { + $str =~ s{#}{\\#}g ; + $str =~ s{_}{\\_}g ; + $str =~ s{&}{\\&}g ; + } + + my ( $clientTypeEN, $clientTypeFR ) = client_type( $Nom_Option_1, $Valeur_Option_1 ) ; + + my ( + $priceHT, + $tvaFR, + $tvaEN, + $priceTVA, + $priceTTC, + $messageTVAFR, + $messageTVAEN, + $priceTTCusd + ) + = tva_stuff( $clientTypeEN, $Pays, $Hors_taxe, $Devise ) ; + + my ( $urlSrc, $urlExe ) = download_urls( $Date ) ; + my $tex_variables = qq{ +%% Begin input from $0 +\\providecommand{\\invoiceNumber}{$invoice} +\\providecommand{\\clientName}{$Nom} +\\providecommand{\\clientEmail}{$De_l_adresse_email} +\\providecommand{\\clientTypeEN}{$clientTypeEN} +\\providecommand{\\clientTypeFR}{$clientTypeFR} +\\providecommand{\\clientAdrA}{$clientAdrA} +\\providecommand{\\clientAdrB}{$clientAdrB} +\\providecommand{\\clientAdrC}{$clientAdrC} +\\providecommand{\\clientAdrD}{$clientAdrD} +\\providecommand{\\clientAdrE}{$clientAdrE} +\\providecommand{\\clientAdrF}{$clientAdrF} +\\providecommand{\\invoiceDate}{$Date} +\\providecommand{\\invoiceHour}{$Heure} +\\providecommand{\\priceHT}{$priceHT} +\\providecommand{\\tvaFR}{$tvaFR} +\\providecommand{\\tvaEN}{$tvaEN} +\\providecommand{\\priceTVA}{$priceTVA} +\\providecommand{\\priceTTC}{$priceTTC} +\\providecommand{\\priceTTCusd}{$priceTTCusd} +\\providecommand{\\messageTVAFR}{$messageTVAFR} +\\providecommand{\\messageTVAEN}{$messageTVAEN} +\\providecommand{\\urlSrc}{\\url{$urlSrc}} +\\providecommand{\\urlExe}{\\url{$urlExe}} +%% End input from $0 +} ; + + + #print $tex_variables ; + + write_tex_variables_file( $dir_invoices, + $invoice, $Date, $tex_variables ) if $write_invoices ; + +} + +sub build_email_message { + + my ( $date, $name, $email, $invoice ) = @_ ; + + my $message_header = qq{X-imapsync: invoice $invoice +From: Gilles LAMIRAL +Bcc: gilles\@lamiral.info +Subject: [imapsync invoice] $invoice ($date) +Disposition-Notification-To: Gilles LAMIRAL +} ; + + +my $message_body = qq{ +Hello $name, + +First I'm sorry for the delay to prepare and send you this message. + +Attached is the invoice of imapsync software you bought ($date). +The invoice file is named facture_imapsync-${invoice}.pdf +This invoice is in PDF format, ready to be print. + +If you need this invoice on paper, just ask me then +I will send it to you by postal mail. + +In order to respect the law, this numeric invoice PDF +file is signed with my private gpg key. + +The resulting gpg signature is in the file named +facture_imapsync-${invoice}.pdf.asc +also attached in this email message. + +You can verify I (Gilles LAMIRAL) really generated +this invoice with the following command line + + gpg --verify facture_imapsync-${invoice}.pdf.asc facture_imapsync-${invoice}.pdf + +or any other gpg graphical tool. + +I thank you again for buying and using imapsync. + +Any feedback is welcome. + +-- +Au revoir, 09 51 84 42 42 +Gilles Lamiral. France, Baulon (35580) 06 20 79 76 06 +} ; + +my $message_body_blabla = qq{ +Here is the fingerprint of my public key +pub 1024D/FDA2B3DC 2002-05-08 + Key fingerprint = 7906 F53D 0D62 0C67 304A 4CF0 6928 869B FDA2 B3DC +uid Gilles LAMIRAL +sub 1024g/A2C4CB42 2002-05-08 + +Of course the verification doesn't prove anything until +all the following conditions are met: +- you met me, +- I agree that the fingerprint above is really mine +- I prove I'm Gilles LAMIRAL with an official paper. + +Normally we won't have to verify anything unless +I disagree with this invoice and the payment +you made for imapsync. +} ; + +return( $message_header, $message_body ) ; + +} + +sub write_csv_info { + + my( $dir_invoices, $invoice, $file_csv, $line_number, $line_csv ) = @_ ; + + open( CSVINFO, "> $dir_invoices/$invoice/csv_info.txt") or die ; + print CSVINFO join( "\n", $file_csv, $line_number, $line_csv ) ; + close( CSVINFO ) ; + +} + +sub write_email_message { + my ( $dir_invoices, $invoice, $message_header, $message_body, $email_address ) = @_ ; + + my $message_body_utf8 = to_utf8({ -string => $message_body, -charset => 'ISO-8859-1' }); + + mkdir( "$dir_invoices/$invoice" ) or die if ! -d "$dir_invoices/$invoice" ; + + open( HEADER, "> $dir_invoices/$invoice/facture_message_header.txt") or die ; + print HEADER $message_header ; + close( HEADER ) ; + + open( BODY, "> $dir_invoices/$invoice/facture_message_body.txt") or die ; + print BODY $message_body_utf8 ; + close( BODY ) ; + + open( ADDRESS, "> $dir_invoices/$invoice/email_address.txt") or die ; + print ADDRESS "$email_address\n" ; + close( ADDRESS ) ; +} + + +sub write_tex_variables_file { + my ( $dir_invoices, $invoice, $date_jjSmmSaaaa, $tex_variables ) = @_ ; + + my $tex_variables_utf8 = to_utf8({ -string => $tex_variables, -charset => 'ISO-8859-1' }); + mkdir( "$dir_invoices/$invoice" ) or die if ! -d "$dir_invoices/$invoice" ; + open( FILE, "> $dir_invoices/$invoice/imapsync_var.tex") or die ; + print FILE $tex_variables_utf8 ; + close( FILE ) ; + +} + +sub download_urls { + my $date_jjSmmSaaaa = shift ; + + my $date_aaaa_mm_jj = date_aaaa_mm_jj( $date_jjSmmSaaaa ) ; + # print "$date_aaaa_mm_jj $date_jjSmmSaaaa\n" ; + my ( $urlSrc, $urlExe ) ; + + if ('2011_03_24' le $date_aaaa_mm_jj) { + $urlSrc = 'http://www.linux-france.org/prj/imapsync/paypal_return.shtml' ; + $urlExe = '' ; + return( $urlSrc, $urlExe ) ; + } + if ('2011_02_21' le $date_aaaa_mm_jj) { + $urlSrc = 'http://www.linux-france.org/depot/2011_02_21/OUMbo7/' ; + $urlExe = 'http://www.linux-france.org/depot/2011_02_21/rHSVNs/' ; + return( $urlSrc, $urlExe ) ; + } + if ('2011_01_18' le $date_aaaa_mm_jj) { + $urlSrc = 'http://www.linux-france.org/depot/2011_01_18/zPRRNt/' ; + $urlExe = 'http://www.linux-france.org/depot/2011_01_18/FO1QzG/' ; + return( $urlSrc, $urlExe ) ; + } + if ('2011_01_18' le $date_aaaa_mm_jj) { + $urlSrc = 'http://www.linux-france.org/depot/2010_11_28/SiNdlZ/' ; + $urlExe = 'http://www.linux-france.org/depot/2010_11_28/R3ZAyr/' ; + return( $urlSrc, $urlExe ) ; + } + $urlSrc = 'http://www.linux-france.org/depot/2010_11_08/X2PWMe/' ; + $urlExe = 'http://www.linux-france.org/depot/2010_11_08/ZZ7zSc/' ; + return( $urlSrc, $urlExe ) ; +} + +sub date_aaaa_mm_jj { + my $date_jjSmmSaaaa = shift ; + + if ( $date_jjSmmSaaaa =~ m{(\d\d)/(\d\d)/(\d\d\d\d)} ) { + my( $jj, $mm, $aaaa ) = ( $1, $2, $3 ) ; + return( join( '_', $aaaa, $mm, $jj ) ) ; + }else{ + return( '9999_12_31' ) ; + } +} + + +sub tva_line { + my( $Devise, $Montant2, $Pays, $Nom_Option_1, $Valeur_Option_1 ) = @_ ; + my( $montant_HT_EUR_exo, $montant_HT_EUR_ass, $montant_TVA_EUR ) ; + + $Montant2 = $Montant2/$usdeur if 'USD' eq $Devise ; + + if ( + ( 'imapsync usage' eq $Nom_Option_1 and 'individual' eq $Valeur_Option_1 ) + or + ( 'France' eq $Pays ) + ) { + $montant_HT_EUR_exo = 0 ; + $montant_HT_EUR_ass = $Montant2 / 1.196 ; + $montant_TVA_EUR = $Montant2 / 1.196 * 0.196 ; + $debug_dev and print "$Montant2 $Pays $Valeur_Option_1\n" ; + }else{ + $montant_HT_EUR_exo = $Montant2 ; + $montant_HT_EUR_ass = 0 ; + $montant_TVA_EUR = 0 ; + } + return( $montant_HT_EUR_exo, $montant_HT_EUR_ass, $montant_TVA_EUR ) ; +} +sub tva_stuff { + my( $clientTypeEN, $Pays, $Hors_taxe, $Devise ) = @_ ; + + my $priceTTCusd = '' ; + $Hors_taxe =~ s{,}{.} ; + + if ( $Devise eq 'USD' ) { + $priceTTCusd = "(USD $Hors_taxe)" ; + $Hors_taxe = ( $Hors_taxe/$usdeur ) ; + } + + my ( + $priceHT, + $tvaFR, + $tvaEN, + $priceTVA, + $priceTTC, + $messageTVAFR, + $messageTVAEN, + ) ; + + if ( ( 'individual' eq $clientTypeEN) + or + ( 'France' eq $Pays ) + ) { + $priceHT = sprintf('%2.2f', $Hors_taxe/1.196) ; + $tvaFR = '19,60\%'; + $tvaEN = ''; + $priceTVA = sprintf('%2.2f', $Hors_taxe/1.196*0.196) ; + $priceTTC = sprintf('%2.2f', $Hors_taxe) ; + $messageTVAFR = ''; + $messageTVAEN = ''; + }else{ + $priceHT = sprintf('%2.2f', $Hors_taxe) ; + $tvaFR = 'néant'; + $tvaEN = '(none)'; + $priceTVA = 0 ; + $priceTTC = $priceHT; + $messageTVAFR = 'Exonération de TVA, article 259 B-1 du Code Général des Impôts'; + $messageTVAEN = '(VAT tax-exempt, article 259 B-1 French General Tax Code)'; + } + foreach my $price ( $priceHT, $priceTVA, $priceTTC, $priceTTCusd ) { + #print "[$price]\n" ; + $price =~ s{\.}{, } ; + } + return( + $priceHT, + $tvaFR, + $tvaEN, + $priceTVA, + $priceTTC, + $messageTVAFR, + $messageTVAEN, + $priceTTCusd + ) ; +} + +sub client_type { + my ( $Nom_Option_1, $Valeur_Option_1 ) = @_ ; + + my ( $clientTypeEN, $clientTypeFR ) = ( 'professional', 'professionnel' ) ; + + if ('imapsync usage' eq $Nom_Option_1 and 'individual' eq $Valeur_Option_1 ) { + $clientTypeEN = 'individual' ; + $clientTypeFR = 'individuel' ; + }elsif ('imapsync usage' eq $Nom_Option_1 and 'professional' eq $Valeur_Option_1 ) { + $clientTypeEN = 'professional' ; + $clientTypeFR = 'professionnel' ; + } + + return( $clientTypeEN, $clientTypeFR ) ; +} + +sub build_adress { + my( + $Nom, + $Adresse_1, + $Adresse_2_district_quartier, + $Ville, + $Code_postal, + $Etat_Province, + $Pays, + ) = @_ ; + + my $addr = " +=========================================================== +Nom $Nom +Adresse_1 $Adresse_1 +Adresse_2_district_quartier $Adresse_2_district_quartier +Ville Code_postal $Ville $Code_postal +Etat_Province $Etat_Province +Pays $Pays +" ; + #print $addr ; + + my @address ; + $Nom = '' if ( $Nom =~ m/^\s+$/ ) ; + push( @address, $Nom ) if $Nom ; + push( @address, $Adresse_1 ) if $Adresse_1 ; + push( @address, $Adresse_2_district_quartier ) if $Adresse_2_district_quartier ; + push( @address, "$Ville $Code_postal" ) if ( $Ville or $Code_postal ); + push( @address, $Etat_Province ) if $Etat_Province ; + push( @address, $Pays, ) if $Pays ; + my $clientAdrA = shift( @address ) || '' ; + my $clientAdrB = shift( @address ) || '' ; + my $clientAdrC = shift( @address ) || '' ; + my $clientAdrD = shift( @address ) || '' ; + my $clientAdrE = shift( @address ) || '' ; + my $clientAdrF = shift( @address ) || '' ; + +$addr = " +[$clientAdrA] +[$clientAdrB] +[$clientAdrC] +[$clientAdrD] +[$clientAdrE] +[$clientAdrF] +"; + #print $addr ; + + return( + $clientAdrA, + $clientAdrB, + $clientAdrC, + $clientAdrD, + $clientAdrE, + $clientAdrF, + ) ; +} diff --git a/paypal_reply/paypal_bilan_1.22 b/paypal_reply/paypal_bilan_1.22 new file mode 100755 index 0000000..b0a9070 --- /dev/null +++ b/paypal_reply/paypal_bilan_1.22 @@ -0,0 +1,756 @@ +#!/usr/bin/perl + +# $Id: paypal_bilan,v 1.22 2011/04/19 12:52:27 gilles Exp gilles $ + +use strict; +use warnings; +use Getopt::Long; +use Text::CSV_XS ; +use IO::Handle ; +use Data::Dumper ; +use Unicode::MapUTF8 qw(to_utf8 from_utf8 utf8_supported_charset); + +die unless (utf8_supported_charset('ISO-8859-1')); + +my $total_usd_received = 0 ; +my $total_usd_invoice = 0 ; + +my $total_eur_received = 0 ; +my $total_eur_invoice = 0 ; +my $nb_invoice = 0 ; +my $nb_invoice_refund = 0 ; + +my $debug ; +my $debug_csv ; +my $debug_dev ; +my $first_invoice = 1 ; +my $print_details = '' ; +my $bnc = ''; +my $usdeur = 1.2981 ; +my $invoices ; +my %invoice_refund ; +my $write_invoices = 0; + +my $dir_invoices = '/g/var/paypal_invoices' ; + +my $option_ret = GetOptions ( + 'debug' => \$debug, + 'debug_csv' => \$debug_csv, + 'debug_dev' => \$debug_dev, + 'first_invoice=i' => \$first_invoice, + 'print_details|details' => \$print_details, + 'bnc' => \$bnc, + 'usdeur=f' => \$usdeur, + 'invoices=s' => \$invoices, + 'write_invoices!' => \$write_invoices, +); + +my @files = @ARGV ; +my %action_of_invoice ; + +my @invoices = split( /\s+/, $invoices ) if $invoices ; + +#print "@invoices\n" ; + +foreach my $file ( @files ) { + + my @actions = parse_file( $file ) ; + + foreach my $action (@actions) { + my %action = %$action ; + #print $action->{ Nom }, "\n" ; + my( $Date, $Heure, $Fuseau_horaire, $Nom, $Type, $Etat, + $Devise, $Montant, $Numero_davis_de_reception, $Solde, + $Pays, $Nom_Option_1, $Valeur_Option_1, $Hors_taxe ) + = @action{ ( 'Date', 'Heure', 'Fuseau horaire', 'Nom', 'Type', 'Etat', + 'Devise', 'Montant', "Numéro d'avis de réception", 'Solde', + 'Pays', 'Nom Option 1', 'Valeur Option 1', 'Hors taxe') } ; + #print "$Nom\n" ; + my $invoice = 'NONE' ; + $Montant = $action->{ Net } if not defined $Montant; + compute_line($action, $invoice, $Date, $Heure, $Fuseau_horaire, $Nom, $Type, $Etat, + $Devise, $Montant, $Numero_davis_de_reception, $Solde, + $Pays, $Nom_Option_1, $Valeur_Option_1, $Hors_taxe ) ; + + # index by invoice number + $action_of_invoice{ $action->{ 'invoice' } } = $action ; + } + delete $action_of_invoice{ 'NONE' } ; +} + +@invoices = ( $first_invoice .. $first_invoice + $nb_invoice -1 ) if ( ! @invoices ) ; + +foreach my $invoice ( @invoices ) { + build_invoice( $invoice ) ; +} + + + +print "USD banque $total_usd_received\n" ; +print "USD invoice $total_usd_invoice\n" ; +my $total_eur_from_usd ; +$total_eur_from_usd = int( ( $total_usd_invoice / $usdeur ) + 0.5 ) ; # au 30 nov 2010 http://fr.finance.yahoo.com/devises/convertisseur/#from=EUR;to=USD;amt=1 +print "EUR from USD $total_eur_from_usd\n" ; +#$total_eur = int( ( $total_eur_invoice / 1.3 ) + 0.5 ) ; +#print "EUR $total_eur_from_usd\n" ; +print "EUR banque $total_eur_received\n" ; +print "EUR invoice $total_eur_invoice\n" ; + +my $total_eur = $total_eur_from_usd + $total_eur_invoice ; +print "EUR total $total_eur\n" ; +print "Nb invoice $nb_invoice\n" ; +print "Nb invoice refund $nb_invoice_refund\n" ; + + +sub parse_one_line_io { + my $csv = shift ; + my $io = shift ; + + my $line = $csv->getline($io) ; + + return if ( $csv->eof( ) ) ; + if ( not defined( $line ) ) { + my($cde, $str, $pos) = $csv->error_diag () ; + print "[$cde] [$str] [$pos]\n" ; + + } + return( $line ) ; +} + +sub hash_and_count_dupplicate { + my @columns = @_ ; + my %columns ; + + #@columns_def{ @columns_def } = ( ) ; + foreach my $col ( @columns ) { + $columns{ $col } += 1 ; + } + $debug_csv and print "Nb columns: ", scalar( keys %columns ), " ", scalar( @columns ), "\n" ; + # debug how many time a title is defined + foreach my $col (1 .. scalar( @columns )) { + $debug_csv and print "$col | ", + deci_to_AA( $col ) , " | ", + $columns{ $columns[ $col - 1 ] }, " | ", + $columns[ $col - 1 ], "\n" ; + } + + # exit in case two columns have the same name + die "Erreur : doublons dans les titres\n" if ( scalar( keys %columns ) != scalar( @columns ) ) ; + + return( %columns ) ; +} + +sub deci_to_AA { + my $deci = shift ; + my $AA = ''; + + while ( $deci > 0 ) { + my $quot = int( ( $deci - 1 ) / 26 ) ; + my $rest = $deci - 1 - ( 26 * $quot ) ; + my $char = chr ( ord('A') + $rest ) ; + $AA = $char . $AA ; + $deci = $quot ; + } + #print "col=$AA\n" ; + return( $AA ) ; +} + +sub remove_first_blank { + my $string = shift ; + + $string =~ s/^ +// ; + return( $string ) ; + +} + +sub parse_file { + my $file = shift ; + + open my $io, "<", $file or die "$file: $!" ; + + my $csv = Text::CSV_XS->new( { + sep_char => ',', + binary => 1, + keep_meta_info => 1, + eol => $/, + } ) ; + + my $line_1 = parse_one_line_io( $csv, $io ) ; + die if ( not defined $line_1 ) ; # first line must have no problem + + my @columns_def_orig = @$line_1 ; + my @columns_def = map { remove_first_blank( $_ ) } @columns_def_orig ; + $debug_csv and print "columns_def = ", map( { "[$_]" } @columns_def ), "\n"; + + my %columns_def = hash_and_count_dupplicate( @columns_def ) ; + my $nb_columns_def = scalar @columns_def ; + + my $line_counter = 2 ; + my @actions ; + while ( 1 ) { + $debug_csv and print "ligne $line_counter ", $csv->eof( ), "\n" ; + my $line = parse_one_line_io( $csv, $io ) ; + last if ( $csv->eof( ) ) ; + if ( not defined $line ) { + print "Erreur ligne $line_counter : ", $csv->error_diag, "\n\n"; + ++$line_counter ; + next ; + } + my @columns = @$line ; + + if ( $nb_columns_def != scalar @columns ) { + print "Erreur ligne $line_counter : nombre de colonnes = ", scalar @columns, " != $nb_columns_def\n" ; + ++$line_counter ; + next ; + } + my %columns ; + @columns{ @columns_def } = @columns ; + $columns{ 'file_csv' } = $file ; + $columns{ 'line_number' } = $line_counter ; + $csv->combine( @columns ) ; + my $line_csv = $csv->string(); + $columns{ 'line_csv' } = $line_csv ; + $debug_csv and print map( { "[$_] = [" . $columns{$_} . "]\n" } + @columns_def, 'line_number', 'line_csv', 'file_csv' ), + "\n"; + ++$line_counter ; + push( @actions, \%columns ) ; + } + close( $io ); + return( reverse @actions ) ; +} + +sub compute_line { + my( $action, $invoice, $Date, $Heure, $Fuseau_horaire, $Nom, $Type, $Etat, + $Devise, $Montant, $Numero_davis_de_reception, $Solde, + $Pays, $Nom_Option_1, $Valeur_Option_1, $Hors_taxe_paypal ) = @_ ; + + $debug and print( "[$Date] [$Heure] [$Fuseau_horaire] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [$Numero_davis_de_reception] [$Solde]\n", + "[$Pays] [$Nom_Option_1] [$Valeur_Option_1]\n" ) ; + #$debug_dev and print "$Hors_taxe_paypal\n" ; + + $Montant =~ s/[^0-9-,.]//g ; + $Montant =~ s/,/./g ; + #$debug and print "MM[$Montant]\n" ; + $Hors_taxe_paypal =~ s/,/./g ; + + my $MontantEUR; + if ( $bnc ) { + $MontantEUR = $Montant ; + $MontantEUR = sprintf( "%.4f", $Montant/$usdeur ) if ($Devise eq 'USD') ; + print( "\n", "=" x 60, "\n" ) ; + print( "[$Date] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [EUR $MontantEUR]\n", + "[$Pays] [$Nom_Option_1] [$Valeur_Option_1]\n" ) ; + } + + if ( + 'Paiement sur site marchand reçu' eq $Type + and 'USD' eq $Devise + and 'Terminé' eq $Etat + ) { + $Montant =~tr/,/./; + #print "$Montant\n" ; + my $Montant2_usd; + $Montant2_usd = $Hors_taxe_paypal ; + $total_usd_received += $Montant ; + $total_usd_invoice += $Montant2_usd ; + $invoice = $first_invoice + $nb_invoice ; + $nb_invoice++ ; + $print_details and print ( "[$invoice] [$Date] [$Heure] [$Fuseau_horaire] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [$Numero_davis_de_reception] [$Solde]\n" ) ; + + } + if ( + 'Paiement sur site marchand reçu' eq $Type + and 'USD' eq $Devise + and 'Compensé' eq $Etat + ) { + $Montant =~tr/,/./; + #print "$Montant\n" ; + my $Montant2_usd; + $Montant2_usd = $Hors_taxe_paypal ; + $total_usd_received += $Montant ; + $total_usd_invoice += $Montant2_usd ; + $invoice = $first_invoice + $nb_invoice ; + $nb_invoice++ ; + $print_details and print ( "[$invoice] [$Date] [$Heure] [$Fuseau_horaire] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [$Numero_davis_de_reception] [$Solde]\n" ) ; + } + if ( + 'Paiement sur site marchand reçu' eq $Type + and 'EUR' eq $Devise + and 'Terminé' eq $Etat + ) { + $Montant =~tr/,/./; + #print "$Montant\n" ; + my $Montant2_eur; + $Montant2_eur = $Hors_taxe_paypal ; + $total_eur_received += $Montant ; + $total_eur_invoice += $Montant2_eur ; + $invoice = $first_invoice + $nb_invoice ; + $nb_invoice++ ; + $print_details and print ( "[$invoice] [$Date] [$Heure] [$Fuseau_horaire] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [$Numero_davis_de_reception] [$Solde]\n" ) ; + } + if ( + 'Paiement sur site marchand reçu' eq $Type + and 'EUR' eq $Devise + and 'Remboursé' eq $Etat + ) { + $invoice = $first_invoice + $nb_invoice ; + $nb_invoice++ ; + $nb_invoice_refund++; + $invoice_refund{ $invoice }++ ; + + $print_details and print ( "[$invoice] [$Date] [$Heure] [$Fuseau_horaire] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [$Numero_davis_de_reception] [$Solde]\n" ) ; + } + if ( + 'Paiement sur site marchand reçu' eq $Type + and 'EUR' eq $Devise + and 'Compensé' eq $Etat + ) { + $Montant =~tr/,/./; + #print "$Montant\n" ; + my $Montant2_eur; + $Montant2_eur = 21.99 if ( 20.88 == $Montant or 20.99 == $Montant ) ; + $Montant2_eur = 30 if ( 28.58 == $Montant or 28.73 == $Montant ) ; + $Montant2_eur = 110 if ( 105.46 == $Montant ) ; + #print "$Montant $Montant2_eur\n" ; + $total_eur_received += $Montant ; + $total_eur_invoice += $Montant2_eur ; + $invoice = $first_invoice + $nb_invoice ; + $nb_invoice++ ; + $print_details and print ( "[$invoice] [$Date] [$Heure] [$Fuseau_horaire] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [$Numero_davis_de_reception] [$Solde]\n" ) ; + } + if ( + 'Paiement sur site marchand reçu' eq $Type + and 'EUR' eq $Devise + and 'Non compensé' eq $Etat + ) { + $invoice = $first_invoice + $nb_invoice ; + $nb_invoice++ ; + $print_details and print ( "[$invoice] [$Date] [$Heure] [$Fuseau_horaire] [$Nom] [$Type] [$Etat] [$Devise] [$Montant] [$Numero_davis_de_reception] [$Solde]\n" ) ; + } + + $action->{ 'invoice' } = $invoice ; + if ( $bnc ) { + my $FR_flag = '' ; + $FR_flag = ' FR' if $Pays eq 'France' ; + my $IND_flag = '' ; + $IND_flag = ' IND' if ('imapsync usage' eq $Nom_Option_1 and 'individual' eq $Valeur_Option_1 ) ; + print "FE $invoice$FR_flag$IND_flag\n" ; + print "Facture $invoice imapsync$FR_flag $Nom\n" ; + printf( "%.2f [EUR %.2f]\n", $Montant, $MontantEUR ) ; + } +} + +sub build_invoice { + my $invoice = shift ; + + return if ! $invoice ; + + my $action = $action_of_invoice{ $invoice } ; + my $refund = '' ; + $refund = 'REFUND ' if $invoice_refund{ $invoice } ; + my %action = %$action if $action ; + #print Data::Dumper->Dump( [$action] ) ; + + my( $Date, $Heure, $Nom, $Type, $Etat, $Devise, $Hors_taxe, $Commission, $Net, + $De_l_adresse_email, $A_l_adresse_email, $N_de_transaction, $Titre_de_l_objet, + $TVA, $Nom_Option_1, $Valeur_Option_1, $N_de_transaction_de_reference, + $Adresse_1, $Adresse_2_district_quartier, $Ville, + $Etat_Province, $Code_postal, $Pays, $line_number, $line_csv, $file_csv ) + = @action{ ( 'Date', 'Heure', 'Nom', 'Type', 'Etat', 'Devise', 'Hors taxe', 'Commission', 'Net', + "De l'adresse email", "A l'adresse email", 'N° de transaction', "Titre de l'objet", + 'TVA', 'Nom Option 1', 'Valeur Option 1', 'Nº de transaction de référence', + 'Adresse 1', 'Adresse 2/district/quartier', 'Ville', + 'Etat/Province/Région/Comté/Territoire/Préfecture/République', 'Code postal', 'Pays', 'line_number', 'line_csv', 'file_csv' ) } ; + + #print "$Hors_taxe $Devise\n" ; + my $Hors_taxe_num = $Hors_taxe ; + $Hors_taxe_num =~ s{,}{.} ; + if ($Hors_taxe_num > 100) { + print "invoice $invoice $Hors_taxe_num > 100\n" ; + #return() ; + } + + my ( $email_message_header, $email_message_body ) + = build_email_message( $Date, $Nom, $De_l_adresse_email, $invoice ) ; + if ( $write_invoices ) { + write_email_message( $dir_invoices, $invoice, + $email_message_header, $email_message_body, + $De_l_adresse_email) ; + write_csv_info( $dir_invoices, $invoice, $file_csv, $line_number, $line_csv ) ; + } + + + + #print "==== $invoice $refund=================================================" ; + #print $email_message ; + + my( + $clientAdrA, + $clientAdrB, + $clientAdrC, + $clientAdrD, + $clientAdrE, + $clientAdrF, + ) + = build_adress( + $Nom, + $Adresse_1, + $Adresse_2_district_quartier, + $Ville, + $Code_postal, + $Etat_Province, + $Pays, + ) ; + + foreach my $str ( + $De_l_adresse_email, + $Nom, + $clientAdrA, + $clientAdrB, + $clientAdrC, + $clientAdrD, + $clientAdrE, + $clientAdrF, + ) { + $str =~ s{#}{\\#}g ; + $str =~ s{_}{\\_}g ; + $str =~ s{&}{\\&}g ; + } + + my ( $clientTypeEN, $clientTypeFR ) = client_type( $Nom_Option_1, $Valeur_Option_1 ) ; + + my ( + $priceHT, + $tvaFR, + $tvaEN, + $priceTVA, + $priceTTC, + $messageTVAFR, + $messageTVAEN, + $priceTTCusd + ) + = tva_stuff( $clientTypeEN, $Pays, $Hors_taxe, $Devise ) ; + + my ( $urlSrc, $urlExe ) = download_urls( $Date ) ; + my $tex_variables = qq{ +%% Begin input from $0 +\\providecommand{\\invoiceNumber}{$invoice} +\\providecommand{\\clientName}{$Nom} +\\providecommand{\\clientEmail}{$De_l_adresse_email} +\\providecommand{\\clientTypeEN}{$clientTypeEN} +\\providecommand{\\clientTypeFR}{$clientTypeFR} +\\providecommand{\\clientAdrA}{$clientAdrA} +\\providecommand{\\clientAdrB}{$clientAdrB} +\\providecommand{\\clientAdrC}{$clientAdrC} +\\providecommand{\\clientAdrD}{$clientAdrD} +\\providecommand{\\clientAdrE}{$clientAdrE} +\\providecommand{\\clientAdrF}{$clientAdrF} +\\providecommand{\\invoiceDate}{$Date} +\\providecommand{\\invoiceHour}{$Heure} +\\providecommand{\\priceHT}{$priceHT} +\\providecommand{\\tvaFR}{$tvaFR} +\\providecommand{\\tvaEN}{$tvaEN} +\\providecommand{\\priceTVA}{$priceTVA} +\\providecommand{\\priceTTC}{$priceTTC} +\\providecommand{\\priceTTCusd}{$priceTTCusd} +\\providecommand{\\messageTVAFR}{$messageTVAFR} +\\providecommand{\\messageTVAEN}{$messageTVAEN} +\\providecommand{\\urlSrc}{\\url{$urlSrc}} +\\providecommand{\\urlExe}{\\url{$urlExe}} +%% End input from $0 +} ; + + + #print $tex_variables ; + + write_tex_variables_file( $dir_invoices, + $invoice, $Date, $tex_variables ) if $write_invoices ; + +} + +sub build_email_message { + + my ( $date, $name, $email, $invoice ) = @_ ; + + my $message_header = qq{X-imapsync: invoice $invoice +From: Gilles LAMIRAL +Bcc: gilles\@lamiral.info +Subject: [imapsync invoice] $invoice ($date) +Disposition-Notification-To: Gilles LAMIRAL +} ; + + +my $message_body = qq{ +Hello $name, + +First I'm sorry for the delay to prepare and send you this message. + +Attached is the invoice of imapsync software you bought ($date). +The invoice file is named facture_imapsync-${invoice}.pdf +This invoice is in PDF format, ready to be print. + +If you need this invoice on paper, just ask me then +I will send it to you by postal mail. + +In order to respect the law, this numeric invoice PDF +file is signed with my private gpg key. + +The resulting gpg signature is in the file named +facture_imapsync-${invoice}.pdf.asc +also attached in this email message. + +You can verify I (Gilles LAMIRAL) really generated +this invoice with the following command line + + gpg --verify facture_imapsync-${invoice}.pdf.asc facture_imapsync-${invoice}.pdf + +or any other gpg graphical tool. + +I thank you again for buying and using imapsync. + +Any feedback is welcome. + +-- +Au revoir, 09 51 84 42 42 +Gilles Lamiral. France, Baulon (35580) 06 20 79 76 06 +} ; + +my $message_body_blabla = qq{ +Here is the fingerprint of my public key +pub 1024D/FDA2B3DC 2002-05-08 + Key fingerprint = 7906 F53D 0D62 0C67 304A 4CF0 6928 869B FDA2 B3DC +uid Gilles LAMIRAL +sub 1024g/A2C4CB42 2002-05-08 + +Of course the verification doesn't prove anything until +all the following conditions are met: +- you met me, +- I agree that the fingerprint above is really mine +- I prove I'm Gilles LAMIRAL with an official paper. + +Normally we won't have to verify anything unless +I disagree with this invoice and the payment +you made for imapsync. +} ; + +return( $message_header, $message_body ) ; + +} + +sub write_csv_info { + + my( $dir_invoices, $invoice, $file_csv, $line_number, $line_csv ) = @_ ; + + open( CSVINFO, "> $dir_invoices/$invoice/csv_info.txt") or die ; + print CSVINFO join( "\n", $file_csv, $line_number, $line_csv ) ; + close( CSVINFO ) ; + +} + +sub write_email_message { + my ( $dir_invoices, $invoice, $message_header, $message_body, $email_address ) = @_ ; + + my $message_body_utf8 = to_utf8({ -string => $message_body, -charset => 'ISO-8859-1' }); + + mkdir( "$dir_invoices/$invoice" ) or die if ! -d "$dir_invoices/$invoice" ; + + open( HEADER, "> $dir_invoices/$invoice/facture_message_header.txt") or die ; + print HEADER $message_header ; + close( HEADER ) ; + + open( BODY, "> $dir_invoices/$invoice/facture_message_body.txt") or die ; + print BODY $message_body_utf8 ; + close( BODY ) ; + + open( ADDRESS, "> $dir_invoices/$invoice/email_address.txt") or die ; + print ADDRESS "$email_address\n" ; + close( ADDRESS ) ; +} + + +sub write_tex_variables_file { + my ( $dir_invoices, $invoice, $date_jjSmmSaaaa, $tex_variables ) = @_ ; + + my $tex_variables_utf8 = to_utf8({ -string => $tex_variables, -charset => 'ISO-8859-1' }); + mkdir( "$dir_invoices/$invoice" ) or die if ! -d "$dir_invoices/$invoice" ; + open( FILE, "> $dir_invoices/$invoice/imapsync_var.tex") or die ; + print FILE $tex_variables_utf8 ; + close( FILE ) ; + +} + +sub download_urls { + my $date_jjSmmSaaaa = shift ; + + my $date_aaaa_mm_jj = date_aaaa_mm_jj( $date_jjSmmSaaaa ) ; + # print "$date_aaaa_mm_jj $date_jjSmmSaaaa\n" ; + my ( $urlSrc, $urlExe ) ; + + if ('2011_03_24' le $date_aaaa_mm_jj) { + $urlSrc = 'http://www.linux-france.org/prj/imapsync/paypal_return.shtml' ; + $urlExe = '' ; + return( $urlSrc, $urlExe ) ; + } + if ('2011_02_21' le $date_aaaa_mm_jj) { + $urlSrc = 'http://www.linux-france.org/depot/2011_02_21/OUMbo7/' ; + $urlExe = 'http://www.linux-france.org/depot/2011_02_21/rHSVNs/' ; + return( $urlSrc, $urlExe ) ; + } + if ('2011_01_18' le $date_aaaa_mm_jj) { + $urlSrc = 'http://www.linux-france.org/depot/2011_01_18/zPRRNt/' ; + $urlExe = 'http://www.linux-france.org/depot/2011_01_18/FO1QzG/' ; + return( $urlSrc, $urlExe ) ; + } + if ('2011_01_18' le $date_aaaa_mm_jj) { + $urlSrc = 'http://www.linux-france.org/depot/2010_11_28/SiNdlZ/' ; + $urlExe = 'http://www.linux-france.org/depot/2010_11_28/R3ZAyr/' ; + return( $urlSrc, $urlExe ) ; + } + $urlSrc = 'http://www.linux-france.org/depot/2010_11_08/X2PWMe/' ; + $urlExe = 'http://www.linux-france.org/depot/2010_11_08/ZZ7zSc/' ; + return( $urlSrc, $urlExe ) ; +} + +sub date_aaaa_mm_jj { + my $date_jjSmmSaaaa = shift ; + + if ( $date_jjSmmSaaaa =~ m{(\d\d)/(\d\d)/(\d\d\d\d)} ) { + my( $jj, $mm, $aaaa ) = ( $1, $2, $3 ) ; + return( join( '_', $aaaa, $mm, $jj ) ) ; + }else{ + return( '9999_12_31' ) ; + } +} + +sub tva_stuff { + my( $clientTypeEN, $Pays, $Hors_taxe, $Devise ) = @_ ; + + my $priceTTCusd = '' ; + $Hors_taxe =~ s{,}{.} ; + + if ( $Devise eq 'USD' ) { + $priceTTCusd = "(USD $Hors_taxe)" ; + $Hors_taxe = ( $Hors_taxe/$usdeur ) ; + } + + my ( + $priceHT, + $tvaFR, + $tvaEN, + $priceTVA, + $priceTTC, + $messageTVAFR, + $messageTVAEN, + ) ; + + if ( ( 'individual' eq $clientTypeEN) + or + ( 'France' eq $Pays ) + ) { + $priceHT = sprintf('%2.2f', $Hors_taxe/1.196) ; + $tvaFR = '19,60\%'; + $tvaEN = ''; + $priceTVA = sprintf('%2.2f', $Hors_taxe/1.196*0.196) ; + $priceTTC = sprintf('%2.2f', $Hors_taxe) ; + $messageTVAFR = ''; + $messageTVAEN = ''; + }else{ + $priceHT = sprintf('%2.2f', $Hors_taxe) ; + $tvaFR = 'néant'; + $tvaEN = '(none)'; + $priceTVA = 0 ; + $priceTTC = $priceHT; + $messageTVAFR = 'Exonération de TVA, article 259 B-1 du Code Général des Impôts'; + $messageTVAEN = '(VAT tax-exempt, article 259 B-1 French General Tax Code)'; + } + foreach my $price ( $priceHT, $priceTVA, $priceTTC, $priceTTCusd ) { + #print "[$price]\n" ; + $price =~ s{\.}{, } ; + } + return( + $priceHT, + $tvaFR, + $tvaEN, + $priceTVA, + $priceTTC, + $messageTVAFR, + $messageTVAEN, + $priceTTCusd + ) ; +} + +sub client_type { + my ( $Nom_Option_1, $Valeur_Option_1 ) = @_ ; + + my ( $clientTypeEN, $clientTypeFR ) = ( 'professional', 'professionnel' ) ; + + if ('imapsync usage' eq $Nom_Option_1 and 'individual' eq $Valeur_Option_1 ) { + $clientTypeEN = 'individual' ; + $clientTypeFR = 'individuel' ; + }elsif ('imapsync usage' eq $Nom_Option_1 and 'professional' eq $Valeur_Option_1 ) { + $clientTypeEN = 'professional' ; + $clientTypeFR = 'professionnel' ; + } + + return( $clientTypeEN, $clientTypeFR ) ; +} + +sub build_adress { + my( + $Nom, + $Adresse_1, + $Adresse_2_district_quartier, + $Ville, + $Code_postal, + $Etat_Province, + $Pays, + ) = @_ ; + + my $addr = " +=========================================================== +Nom $Nom +Adresse_1 $Adresse_1 +Adresse_2_district_quartier $Adresse_2_district_quartier +Ville Code_postal $Ville $Code_postal +Etat_Province $Etat_Province +Pays $Pays +" ; + #print $addr ; + + my @address ; + $Nom = '' if ( $Nom =~ m/^\s+$/ ) ; + push( @address, $Nom ) if $Nom ; + push( @address, $Adresse_1 ) if $Adresse_1 ; + push( @address, $Adresse_2_district_quartier ) if $Adresse_2_district_quartier ; + push( @address, "$Ville $Code_postal" ) if ( $Ville or $Code_postal ); + push( @address, $Etat_Province ) if $Etat_Province ; + push( @address, $Pays, ) if $Pays ; + + + my $clientAdrA = shift( @address ) || '' ; + my $clientAdrB = shift( @address ) || '' ; + my $clientAdrC = shift( @address ) || '' ; + my $clientAdrD = shift( @address ) || '' ; + my $clientAdrE = shift( @address ) || '' ; + my $clientAdrF = shift( @address ) || '' ; + +$addr = " +[$clientAdrA] +[$clientAdrB] +[$clientAdrC] +[$clientAdrD] +[$clientAdrE] +[$clientAdrF] +"; + #print $addr ; + + return( + $clientAdrA, + $clientAdrB, + $clientAdrC, + $clientAdrD, + $clientAdrE, + $clientAdrF, + ) ; +} diff --git a/paypal_reply/paypal_build_invoices b/paypal_reply/paypal_build_invoices new file mode 100644 index 0000000..98faf5c --- /dev/null +++ b/paypal_reply/paypal_build_invoices @@ -0,0 +1,83 @@ +#!/bin/sh + +# usage: sh paypal_build_invoices/g/var/paypal_invoices/??? + +cp /home/gilles/public_html/AGIL/factures/000/facture_imapsync-000.tex /g/var/paypal_invoices/ + +set -x +/g/public_html/imapsync/paypal_reply/paypal_bilan --write_invoices --first_in 147 /g/paypal/paypal_2010_11_complet.csv +/g/public_html/imapsync/paypal_reply/paypal_bilan --write_invoices --first_in 214 /g/paypal/paypal_2010_12_complet.csv +/g/public_html/imapsync/paypal_reply/paypal_bilan --write_invoices --first_in 294 /g/paypal/paypal_2011_01_complet.csv +/g/public_html/imapsync/paypal_reply/paypal_bilan --write_invoices --first_in 382 /g/paypal/paypal_2011_02_complet.csv +/g/public_html/imapsync/paypal_reply/paypal_bilan --write_invoices --first_in 473 /g/paypal/paypal_2011_03_complet.csv +set +x + +# USD de 147 à 340 +# EUR de 341 à ... + +# 20110413 Found problems with 189 199 249 258 263 359 537 +# 20110412 Found problems with 189 199 242 249 258 263 359 382 537 +# cen cen JAP cen cen cen cen TCH JAP +# cen +# 155 TVA 1,89 +# 171 TVA 4,42 +# 220 TVA 3,16 +# 225 TVA 3,16 +# 236 TVA 4,42 +# 298 TVA 3,16 +# 307 TVA 4,42 +# 312 TVA 4,42 +# 324 TVA 4,42 +# 351 TVA 4,92 +# 395 TVA 4,92 +# 408 TVA 4,92 +# 419 TVA 4,92 +# 432 TVA 4,92 +# 435 TVA 4,92 +# 452 TVA 4,92 +# 460 TVA 4,92 +# 461 TVA 4,92 +# 463 TVA 4,92 +# 464 TVA 4,92 +# 475 TVA 4,92 +# 487 TVA 4,92 +# 489 TVA 4,92 +# 502 TVA 4,92 +# 504 TVA 4,92 +# 511 TVA 4,92 +# 522 TVA 4,92 +# 523 TVA 4,92 +# 533 TVA 4,92 +# 537 TVA 4,92 +# 540 TVA 4,92 +# 543 TVA 4,92 +# 549 TVA 4,92 +# 551 TVA 4,92 +# 552 TVA 4,92 +# 556 TVA 4,92 +# 563 TVA 4,92 + +for d in "$@"; do + echo "==== $d ====" + cd $d + bd=`basename $d` + ln -f ../facture_imapsync-000.tex facture_imapsync-$bd.tex; + if ! pdflatex facture_imapsync-$bd.tex < /dev/null > /dev/null; then + echo "PB $bd" + if test -f facture_imapsync-${bd}_good.tex \ + && pdflatex facture_imapsync-${bd}_good.tex < /dev/null > /dev/null + then + ln -f facture_imapsync-${bd}_good.pdf facture_imapsync-$bd.pdf + echo "PB $bd solved with manual facture_imapsync-${bd}_good.tex" + PB_LIST_MANUAL="$PB_LIST_MANUAL $bd" + else + PB_LIST="$PB_LIST $bd" + rm -f facture_imapsync-$bd.pdf + continue + fi + fi + gpg --use-agent --armor --detach-sign --yes facture_imapsync-$bd.pdf +done + +echo "Found problems with $PB_LIST" +echo "Manual invoices for $PB_LIST_MANUAL" diff --git a/paypal_reply/paypal_build_reply b/paypal_reply/paypal_build_reply index ca1c72d..f112439 100755 --- a/paypal_reply/paypal_build_reply +++ b/paypal_reply/paypal_build_reply @@ -1,9 +1,10 @@ #!/usr/bin/perl -# $Id: paypal_build_reply,v 1.10 2011/02/02 22:31:41 gilles Exp gilles $ +# $Id: paypal_build_reply,v 1.12 2011/03/23 18:31:52 gilles Exp gilles $ use warnings; use strict; +use Getopt::Long; my ($msg_id_file, $msg_id); my ($amount, $name, $email); @@ -13,23 +14,39 @@ my ( $url_source, $url_exe, $url, $release, ); +my $help ; +my $debug ; + +my $numopt = scalar(@ARGV); +my $opt_ret = GetOptions( + "help" => \$help, + "debug!" => \$debug, +); + +usage() and exit if ($help or ! $numopt) ; + $msg_id_file = $ARGV[1]; $msg_id = firstline($msg_id_file); +$debug and print "Hi!\n" ; while(<>) { - next if ( ! /^(.*Num.+ro de transaction :.*)$/ ); + next if ( ! /^(.*Num.+ro de transaction.*)$/ ); $paypal_line = $1; $paypal_info = "===== Paypal id =====\n$paypal_line\n"; + $debug and print "$paypal_info" ; last; } - while(<>) { - next if ( ! /^Vous avez re.*paiement d'un montant de (.*) de la part de (.*) \((.*)\)/); - ($amount, $name, $email) = ($1, $2, $3); - last; + if ( /^Vous avez re.*paiement d'un montant de (.*) de la part de (.*) \((.*)\)/) { + ($amount, $name, $email) = ($1, $2, $3); + last; + } + if ( /^Vous avez re.*paiement d'un montant de (.*) de la part de (.*)/) { + ($amount, $name, $email) = ($1, "", $2); + last; + } } - $url_source = firstline('/g/var/paypal_reply/url_source'); $url_exe = firstline('/g/var/paypal_reply/url_exe'); $release = firstline('/g/var/paypal_reply/url_release'); @@ -37,18 +54,25 @@ $release = firstline('/g/var/paypal_reply/url_release'); #print "[$amount] [$name] [$email] [$paypal_line]\n"; - while(<>) { - next if ( ! /^Acheteur/ ); - $buyer .= "===== Acheteur =====\n"; - last; + if ( /^Acheteur/ ) { + $buyer .= "===== Acheteur =====\n"; + last; + } + if ( /^Informations sur l'acheteur/ ) { + $buyer .= "===== Acheteur =====\n"; + chomp( $name = <> ); + $buyer .= "$name\n" ; + last; + } } while(<>) { - $buyer .= $_ if ( ! /^Instructions/ ); - last if ( /^Instructions/ ); + $buyer .= $_ if ( ! /^-----------------------------------/ ); + last if ( /^-----------------------------------/ ); } + while(<>) { next if ( ! /^Description :(.*)/ ); $description = "===== Details =====\n"; @@ -57,13 +81,16 @@ while(<>) { } while(<>) { + $debug and print "LINE:$_" ; $description .= $_; last if ( /^Paiement envoy/ ); + last if ( /^N.*d'avis de r.*ception/ ); } + my $address = 'gilles.lamiral@laposte.net'; my $address2 = 'gilles@lamiral.info'; -my $rcstag = '$Id: paypal_build_reply,v 1.10 2011/02/02 22:31:41 gilles Exp gilles $'; +my $rcstag = '$Id: paypal_build_reply,v 1.12 2011/03/23 18:31:52 gilles Exp gilles $'; my $message = < \$password, "passfile=s" => \$passfile, "folder=s" => \$folder, + "search=s" => \@search, "help" => \$help, "delete!" => \$delete, "expunge!" => \$expunge, @@ -51,7 +53,10 @@ $imap->select($folder) or die "Error select folder [$folder] host [$host] user [ #my @uids = $imap->search('HEADER', 'SUBJECT',"=?windows-1252?Q?Avis_de_r=E9ception_d=27un_paiement?="); #my @uids = $imap->search('HEADER', 'Sender','sendmail@paypal.com'); -my @uids = $imap->search('TEXT', 'PP341'); +#my @uids = $imap->search('TEXT', 'PP341'); +print "@search\n" ; +@search = ('TEXT', 'PP341') if not @search ; +my @uids = $imap->search('HEADER', 'Sender','sendmail@paypal.com', @search ); print "Search: [@uids]\n"; foreach $msg (@uids) { diff --git a/paypal_reply/paypal_run_test b/paypal_reply/paypal_run_dev similarity index 71% rename from paypal_reply/paypal_run_test rename to paypal_reply/paypal_run_dev index b3f262c..1303460 100755 --- a/paypal_reply/paypal_run_test +++ b/paypal_reply/paypal_run_dev @@ -1,6 +1,6 @@ #!/bin/sh -# $Id: paypal_run_test,v 1.1 2010/11/28 01:00:45 gilles Exp gilles $ +# $Id: paypal_run_dev,v 1.4 2011/03/23 19:08:30 gilles Exp gilles $ set -e #set -x @@ -8,7 +8,7 @@ set -e # Add path to commands at home PATH=$PATH:/g/public_html/imapsync/paypal_reply -PERL5LIB=/g/public_html/imapsync/Mail-IMAPClient-3.25/lib +PERL5LIB=/g/public_html/imapsync/Mail-IMAPClient-3.28/lib export PERL5LIB test -f /g/public_html/imapsync/paypal_reply/paypal_functions \ @@ -18,7 +18,7 @@ test -f /g/public_html/imapsync/paypal_reply/paypal_functions \ DATE_1=`date` echo "==== paypal_reply_test ====" -paypal_reply_test +paypal_reply_petite_dev "$@" echo diff --git a/paypal_reply/paypal_run_laposte b/paypal_reply/paypal_run_laposte index dad363d..1831206 100755 --- a/paypal_reply/paypal_run_laposte +++ b/paypal_reply/paypal_run_laposte @@ -1,6 +1,6 @@ #!/bin/sh -# $Id: paypal_run_laposte,v 1.2 2010/11/28 05:27:12 gilles Exp gilles $ +# $Id: paypal_run_laposte,v 1.3 2011/03/23 17:02:39 gilles Exp $ set -e #set -x @@ -8,7 +8,7 @@ set -e # Add path to commands at home PATH=$PATH:/g/public_html/imapsync/paypal_reply -PERL5LIB=/g/public_html/imapsync/Mail-IMAPClient-3.25/lib +PERL5LIB=/g/public_html/imapsync/Mail-IMAPClient-3.28/lib export PERL5LIB test -f /g/public_html/imapsync/paypal_reply/paypal_functions \ diff --git a/paypal_reply/paypal_run_petite b/paypal_reply/paypal_run_petite index 742c0b3..5ed89d0 100755 --- a/paypal_reply/paypal_run_petite +++ b/paypal_reply/paypal_run_petite @@ -1,6 +1,6 @@ #!/bin/sh -# $Id: paypal_run_petite,v 1.4 2010/12/14 15:40:13 gilles Exp gilles $ +# $Id: paypal_run_petite,v 1.5 2011/03/23 17:02:39 gilles Exp $ set -e #set -x @@ -8,7 +8,7 @@ set -e # Add path to commands at home PATH=$PATH:/g/public_html/imapsync/paypal_reply -PERL5LIB=/g/public_html/imapsync/Mail-IMAPClient-3.25/lib +PERL5LIB=/g/public_html/imapsync/Mail-IMAPClient-3.28/lib export PERL5LIB test -f /g/public_html/imapsync/paypal_reply/paypal_functions \ diff --git a/paypal_reply/paypal_send_invoices b/paypal_reply/paypal_send_invoices new file mode 100644 index 0000000..bad84bc --- /dev/null +++ b/paypal_reply/paypal_send_invoices @@ -0,0 +1,43 @@ +#!/bin/sh + +# usages: +# sh paypal_send_invoices /g/var/paypal_invoices/147 +# sh paypal_send_invoices /g/var/paypal_invoices/15? + + +send_invoice() { + test X"" = X"$1" && { echo "usage: send_invoice /g/var/paypal_invoices/147 vince@norestech.net"; return; } + d="$1" + echo "====== $d ======" + #echo + cd $d || return + bd=`basename $d` + #echo "$bd" + invoice="$bd" + test -f facture_imapsync-${invoice}.pdf || { echo NO facture_imapsync-${invoice}.pdf ; return; } + test -f facture_imapsync-${invoice}.pdf.asc || { echo NO facture_imapsync-${invoice}.pdf.asc ; return; } + test -f facture_message_header.txt || { echo NO facture_message_header.txt ; return; } + test -f facture_message_body.txt || { echo NO facture_message_body.txt ; return; } + test -f email_address.txt || { echo NO email_address.txt ; return; } + + email=${2:-`cat email_address.txt`} + > facture_message_to.txt + egrep '^To: ' facture_message_header.txt > /dev/null || echo "To: $email" > facture_message_to.txt + cat facture_message_header.txt facture_message_to.txt facture_message_body.txt > facture_message.txt + more facture_message.txt + + echo '====== END of message ======' + test -f "SENT_TO_$email" && { echo "Already SENT_TO_$email"; } + test -f "SENT_TO_$email" || acroread facture_imapsync-${invoice}.pdf& + echo "Send this invoice ${invoice} to $email?" + read r < /dev/tty + echo SAID "[$r]" + test X"$r" = Xy && { + echo | mutt -H facture_message.txt -a facture_imapsync-${invoice}.pdf facture_imapsync-${invoice}.pdf.asc -- + touch SENT_TO_$email + } +} + +for d in "$@"; do + send_invoice "$d" +done diff --git a/paypal_return.shtml b/paypal_return.shtml new file mode 100644 index 0000000..b3b049b --- /dev/null +++ b/paypal_return.shtml @@ -0,0 +1,113 @@ + + + + +imapsync download + + + + + + + + + + + + + + + + + + + + +

    imapsync download

    + +

    I thank you for buying Imapsync!

    + +

    The payment has been made and the transaction has been completed.
    +A receipt for your purchase has been emailed to you.
    +You may log into your account at www.paypal.com +to view details of this transaction. +

    + +

    You will find the latest imapsync source code release 1.404 at the following link:
    +http://www.linux-france.org/depot/2011_02_21/OUMbo7/ +

    + +

    You will find the latest imapsync.exe binary release 1.404 at the following link:
    +http://www.linux-france.org/depot/2011_02_21/rHSVNs/ +

    + +

    You will receive an invoice soon.

    + +

    Next imapsync releases will be available for one year without extra payment.
    +I will send you a message explaining how to get them

    + +

    I thank you again for buying and using imapsync, +I wish you successful imap transfers!

    + +

    imapsync homepage

    + +

    Gilles LAMIRAL
    +gilles.lamiral@laposte.net

    + +
    +

    + Valid XHTML 1.0 Strict + + + CSS Valide ! + +
    + + +This document last modified on
    +($Id: paypal_return.shtml,v 1.2 2011/03/24 01:21:27 gilles Exp gilles $) +

    + + + + + + + + + + diff --git a/paypal_return_support.shtml b/paypal_return_support.shtml new file mode 100644 index 0000000..4d0ea17 --- /dev/null +++ b/paypal_return_support.shtml @@ -0,0 +1,109 @@ + + + + +imapsync support + + + + + + + + + + + + + + + + + + + + +

    imapsync support

    + +

    I thank you for buying Imapsync support!

    + +

    The payment has been made and the transaction has been completed.
    +A receipt for your purchase has been emailed to you.
    +You may log into your account at www.paypal.com +to view details of this transaction. +

    + +

    You will receive an invoice soon.

    + +

    Now you can contact me (Gilles LAMIRAL) by email or phone

    +
      +
    • Email address: gilles.lamiral@laposte.net.
    • +
    • Professionnal phone number: +33 9 51 84 42 42 (in France) I can call you back for free in many countries.
    • +
    • Mobile phone number: +33 620 79 76 06 (in France).
    • +
    + +

    I thank you again for buying imapsync support, +I wish you successful imap transfers and I will help you until you reach this goal!

    + +

    imapsync homepage

    + +

    Gilles LAMIRAL
    +gilles.lamiral@laposte.net

    + +
    +

    + Valid XHTML 1.0 Strict + + + CSS Valide ! + +
    + + +This document last modified on
    +($Id: paypal_return_support.shtml,v 1.2 2011/04/19 13:09:12 gilles Exp gilles $) +

    + + + + + + + + + + diff --git a/test2.bat b/test2.bat index 63037d3..e23f935 100755 --- a/test2.bat +++ b/test2.bat @@ -3,5 +3,12 @@ REM $Id: test.bat,v 1.8 2011/01/15 06:30:33 gilles Exp gilles $ cd C:\msys\1.0\home\Admin\imapsync REM perl ./imapsync --host1 p --user1 tata --passfile1 secret.tata --host2 p --user2 titi --passfile2 secret.titi --delete2 --expunge2 --folder INBOX -perl ./imapsync --host1 p --user1 tata --passfile1 secret.tata --host2 p --user2 titi --passfile2 secret.titi --delete2 --expunge1 --expunge2 --folder INBOX --usecache +REM perl ./imapsync --host1 p --user1 tata --passfile1 secret.tata --host2 p --user2 titi --passfile2 secret.titi --delete2 --expunge1 --expunge2 --folder INBOX --usecache + + + + +REM imapsync --host1 p --user1 tata --passfile1 secret.tata --host2 p --user2 titi --passfile2 secret.titi --justfolders --nofoldersize --folder INBOX.yop.yap --sep1 / --regextrans2 "s,/,_," +imapsync --host1 p --user1 tata --passfile1 secret.tata --host2 p --user2 titi --passfile2 secret.titi --nofoldersize --folder INBOX.yop.yap --regexflag 's/\\Answered//g' --debug > out.txt + diff --git a/tests.sh b/tests.sh index 02891f0..0a17242 100644 --- a/tests.sh +++ b/tests.sh @@ -1,6 +1,6 @@ #!/bin/sh -# $Id: tests.sh,v 1.149 2011/02/21 02:13:52 gilles Exp gilles $ +# $Id: tests.sh,v 1.159 2011/04/20 01:18:40 gilles Exp gilles $ # Example 1: # CMD_PERL='perl -I./Mail-IMAPClient-3.25/lib' sh -x tests.sh @@ -24,7 +24,7 @@ CMD_PERL=${CMD_PERL:-'perl -I./Mail-IMAPClient-2.2.9'} # few debugging tests use: CMD_PERL_2xx='perl -I./Mail-IMAPClient-2.2.9' -CMD_PERL_3xx='perl -I./Mail-IMAPClient-3.27/lib' +CMD_PERL_3xx='perl -I./Mail-IMAPClient-3.28/lib' #### Shell pragmas @@ -922,7 +922,7 @@ ll_regex_flag() --host2 $HOST2 --user2 titi \ --passfile2 ../../var/pass/secret.titi \ --folder INBOX.yop.yap \ - --debug --regexflag 's/\\Answered/\\Seen/g' + --regexflag 's/\\Answered/\$Forwarded/g' echo 'rm -f /home/vmail/titi/.yop.yap/cur/*' } @@ -994,9 +994,9 @@ ll_tls_justlogin() { ll_tls_devel() { CMD_PERL='perl -I./Mail-IMAPClient-2.2.9' ll_justlogin ll_ssl_justlogin \ -&& CMD_PERL='perl -I./Mail-IMAPClient-3.27/lib' ll_justlogin ll_ssl_justlogin \ +&& CMD_PERL='perl -I./Mail-IMAPClient-3.28/lib' ll_justlogin ll_ssl_justlogin \ && CMD_PERL='perl -I./Mail-IMAPClient-2.2.9' ll_tls_justconnect ll_tls_justlogin \ -&& CMD_PERL='perl -I./Mail-IMAPClient-3.27/lib' ll_tls_justconnect ll_tls_justlogin +&& CMD_PERL='perl -I./Mail-IMAPClient-3.28/lib' ll_tls_justconnect ll_tls_justlogin } ll_tls() { @@ -1099,6 +1099,17 @@ ll_authuser() { --authuser2 titi } +ll_authuser_2() { + + $CMD_PERL ./imapsync \ + --host1 $HOST1 --user1 tata \ + --passfile1 ../../var/pass/secret.tata \ + --host2 $HOST2 --user2 anything \ + --passfile2 ../../var/pass/secret.titi \ + --justfoldersizes \ + --authuser2 titi --folder INBOX.lalala +} + ll_authmech_LOGIN() { @@ -1214,6 +1225,65 @@ xxxxx_gmail() { --justfolders --dry --prefix2 '[Gmail]/' } +xxxxx_gmail_2() { + + ! ping -c1 imap.gmail.com || $CMD_PERL ./imapsync \ + --host1 $HOST2 \ + --user1 tata \ + --passfile1 ../../var/pass/secret.tata \ + --host2 imap.gmail.com \ + --ssl2 \ + --user2 gilles.lamiral@gmail.com \ + --passfile2 ../../var/pass/secret.gilles_gmail \ + --nofoldersizes \ + --regextrans2 's,(.*),SMS,' +#--dry --prefix2 '[Gmail]/' +} + +xxxxx_gmail_3() { + + ! ping -c1 imap.gmail.com || $CMD_PERL ./imapsync \ + --host1 $HOST2 \ + --user1 tata \ + --passfile1 ../../var/pass/secret.tata \ + --host2 imap.gmail.com \ + --ssl2 \ + --user2 gilles.lamiral@gmail.com \ + --passfile2 ../../var/pass/secret.gilles_gmail \ + --nofoldersizes \ + --folder INBOX.few_emails --justfolders --debug \ + --regextrans2 's,few_emails,Gmail/Messages envoyes,' +} + +xxxxx_gmail_4() { + + ! ping -c1 imap.gmail.com || $CMD_PERL ./imapsync \ + --host1 $HOST2 \ + --user1 tata \ + --passfile1 ../../var/pass/secret.tata \ + --host2 imap.gmail.com \ + --ssl2 \ + --user2 gilles.lamiral@gmail.com \ + --passfile2 ../../var/pass/secret.gilles_gmail \ + --nofoldersizes \ + --folder INBOX.Sent \ + --regextrans2 's{Sent}{Gmail/Messages envoyes}' +} + +xxxxx_gmail_5_justlogin() { + + ! ping -c1 imap.gmail.com || $CMD_PERL ./imapsync \ + --host1 $HOST2 \ + --user1 tata \ + --passfile1 ../../var/pass/secret.tata \ + --host2 imap.gmail.com \ + --ssl2 \ + --user2 gilles.lamiral@gmail.com \ + --passfile2 ../../var/pass/secret.gilles_gmail \ + --justlogin +} + + gmail_xxxxx() { ! ping -c1 imap.gmail.com || $CMD_PERL ./imapsync \ @@ -1292,7 +1362,7 @@ allow3xx() { } noallow3xx() { - ! perl -I./Mail-IMAPClient-3.27/lib ./imapsync \ + ! perl -I./Mail-IMAPClient-3.28/lib ./imapsync \ --host1 $HOST1 --user1 tata \ --passfile1 ../../var/pass/secret.tata \ --host2 $HOST2 --user2 titi \ @@ -1480,6 +1550,59 @@ ll_useuid_nousecache() # specific tests ########################## +godaddy_1_justlogin() { + $CMD_PERL ./imapsync \ + --host1 $HOST1 --user1 tata \ + --passfile1 ../../var/pass/secret.tata \ + --host2 imap.secureserver.net --user2 migrationtest@overnightmac.com \ + --passfile2 ../../var/pass/secret.overnightmac --tls2 \ + --folder INBOX.oneemail --folder INBOX.few_emails +} + +mailenable_1() { + $CMD_PERL ./imapsync \ + --host1 $HOST1 --user1 tata \ + --passfile1 ../../var/pass/secret.tata \ + --host2 email.avonvalley.wilts.sch.uk --user2 "GLamiral" \ + --passfile2 ../../var/pass/secret.avonvalley \ + --sep2 / --prefix2 '' --useuid \ + --folder INBOX.Junk --folder INBOX.few_emails \ + --delete2 --expunge2 +} + +mailenable_2_justfolders() { + $CMD_PERL ./imapsync \ + --host1 $HOST1 --user1 tata \ + --passfile1 ../../var/pass/secret.tata \ + --host2 email.avonvalley.wilts.sch.uk --user2 "GLamiral" \ + --passfile2 ../../var/pass/secret.avonvalley \ + --sep2 / --prefix2 '' --useuid \ + --justfolders --exclude "Gmail" --exclude ' ' +} + + +mailenable_3_reverse() { + $CMD_PERL ./imapsync \ + --host2 $HOST1 --user2 tata \ + --passfile2 ../../var/pass/secret.tata \ + --host1 email.avonvalley.wilts.sch.uk --user1 "GLamiral" \ + --passfile1 ../../var/pass/secret.avonvalley \ + --sep1 / --prefix1 '' \ + --folder few_emails \ + --delete2 --expunge2 --debug --useuid +} + + + +bug_zero_byte() { + $CMD_PERL ./imapsync \ + --host1 buzon.us.es --user1 rafaeltovar \ + --passfile1 ../../var/pass/secret.rafaeltovar \ + --host2 $HOST2 --user2 titi \ + --passfile2 ../../var/pass/secret.titi \ + --folder INBOX --regextrans2 s/INBOX/INBOX.rafaeltovar/ +} + exchange_1() { $CMD_PERL ./imapsync \ --host1 $HOST1 --user1 tata \ @@ -1489,11 +1612,32 @@ exchange_1() { --folder INBOX.oneemail --folder INBOX.few_emails --folder INBOX -maxage 1 } +exchange_2() { + $CMD_PERL ./imapsync \ + --host1 $HOST1 --user1 tata \ + --passfile1 ../../var/pass/secret.tata \ + --host2 mail.ethz.ch --ssl2 --user2 glamiral \ + --passfile2 ../../var/pass/secret.ethz.ch \ + --folder INBOX.Junk --useuid +} + +exchange_3_delete2() { + $CMD_PERL ./imapsync \ + --host1 $HOST1 --user1 tata \ + --passfile1 ../../var/pass/secret.tata \ + --host2 mail.ethz.ch --ssl2 --user2 glamiral \ + --passfile2 ../../var/pass/secret.ethz.ch \ + --folder INBOX.Junk --useuid --delete2 +} + + + jong_1() { $CMD_PERL ./imapsync \ --host1 mail.y-publicaties.nl --user1 gillesl --passfile1 ../../var/pass/secret.jong \ --host2 $HOST2 --user2 titi --passfile2 ../../var/pass/secret.titi --sep1 / --prefix1 '' \ - --delete2 --expunge2 --folder INBOX --nofoldersizes + --delete2 --expunge2 --expunge1 --expunge \ + --foldersizes --folder Junk/2009 --useuid # --debugimap1 --dry } @@ -1502,7 +1646,7 @@ $CMD_PERL ./imapsync \ --host2 mail.y-publicaties.nl --user2 gillesl --passfile2 ../../var/pass/secret.jong \ --host1 $HOST2 --user1 gilles@est.belle --passfile1 ../../var/pass/secret.gilles_mbox \ --sep2 / --prefix2 '' \ - --folder INBOX.Junk.2009 --delete2 --expunge2 --debug > zzz 2>&1 + --folder INBOX.Junk.2009 --delete2 --expunge2 --expunge1 --expunge --useuid #--nofoldersizes # --debugimap1 --dry }